mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-02-06 02:14:58 +01:00
Signal Station
- Refactored Stations and Signals into a more unified and expandable edge point abstraction - Trains no longer depart a station when a red signal is close by - Fixed inconsistent pathfinding when stations, signals and trains are sharing a graph edge
This commit is contained in:
parent
cf308cdc7f
commit
3362e6a05e
32 changed files with 884 additions and 659 deletions
|
@ -1,6 +1,9 @@
|
||||||
package com.simibubi.create.content.logistics.trains;
|
package com.simibubi.create.content.logistics.trains;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -118,6 +121,16 @@ public class GlobalRailwayManager {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<TrackGraph> getGraphs(LevelAccessor level, TrackNodeLocation vertex) {
|
||||||
|
if (trackNetworks == null)
|
||||||
|
return Collections.emptyList();
|
||||||
|
ArrayList<TrackGraph> intersecting = new ArrayList<>();
|
||||||
|
for (TrackGraph railGraph : trackNetworks.values())
|
||||||
|
if (railGraph.locateNode(vertex) != null)
|
||||||
|
intersecting.add(railGraph);
|
||||||
|
return intersecting;
|
||||||
|
}
|
||||||
|
|
||||||
public void tick(Level level) {
|
public void tick(Level level) {
|
||||||
ResourceLocation location2 = DimensionType.OVERWORLD_LOCATION.location();
|
ResourceLocation location2 = DimensionType.OVERWORLD_LOCATION.location();
|
||||||
ResourceLocation location = level.dimension()
|
ResourceLocation location = level.dimension()
|
||||||
|
@ -131,9 +144,7 @@ public class GlobalRailwayManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TrackGraph graph : trackNetworks.values())
|
for (TrackGraph graph : trackNetworks.values())
|
||||||
graph.getSignals()
|
graph.tickPoints();
|
||||||
.forEach(sb -> sb.tick(graph));
|
|
||||||
|
|
||||||
for (Train train : trains.values())
|
for (Train train : trains.values())
|
||||||
train.earlyTick(level);
|
train.earlyTick(level);
|
||||||
for (Train train : trains.values())
|
for (Train train : trains.values())
|
||||||
|
@ -143,10 +154,14 @@ public class GlobalRailwayManager {
|
||||||
trackNetworks.values()
|
trackNetworks.values()
|
||||||
.forEach(TrackGraph::debugViewSignalData);
|
.forEach(TrackGraph::debugViewSignalData);
|
||||||
}
|
}
|
||||||
|
if (AllKeys.isKeyDown(GLFW.GLFW_KEY_J) && AllKeys.altDown()) {
|
||||||
|
trackNetworks.values()
|
||||||
|
.forEach(TrackGraph::debugViewNodes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clientTick() {
|
public void clientTick() {
|
||||||
if (AllKeys.isKeyDown(GLFW.GLFW_KEY_J)) {
|
if (AllKeys.isKeyDown(GLFW.GLFW_KEY_J) && !AllKeys.altDown()) {
|
||||||
trackNetworks.values()
|
trackNetworks.values()
|
||||||
.forEach(TrackGraph::debugViewNodes);
|
.forEach(TrackGraph::debugViewNodes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,14 @@ import com.simibubi.create.CreateClient;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
|
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.entity.Train;
|
||||||
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
|
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
|
||||||
|
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.signal.EdgeData;
|
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
|
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.SignalEdgeGroup;
|
import com.simibubi.create.content.logistics.trains.management.signal.SignalEdgeGroup;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.SignalPropagator;
|
import com.simibubi.create.content.logistics.trains.management.signal.TrackEdgePoint;
|
||||||
import com.simibubi.create.foundation.utility.Color;
|
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.NBTHelper;
|
||||||
import com.simibubi.create.foundation.utility.Pair;
|
import com.simibubi.create.foundation.utility.Pair;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
@ -54,67 +56,47 @@ public class TrackGraph {
|
||||||
Map<TrackNodeLocation, TrackNode> nodes;
|
Map<TrackNodeLocation, TrackNode> nodes;
|
||||||
Map<Integer, TrackNode> nodesById;
|
Map<Integer, TrackNode> nodesById;
|
||||||
Map<TrackNode, Map<TrackNode, TrackEdge>> connectionsByNode;
|
Map<TrackNode, Map<TrackNode, TrackEdge>> connectionsByNode;
|
||||||
|
EdgePointStorage edgePoints;
|
||||||
private Map<UUID, GlobalStation> stations;
|
|
||||||
private Map<UUID, SignalBoundary> signals;
|
|
||||||
|
|
||||||
public TrackGraph() {
|
public TrackGraph() {
|
||||||
this(UUID.randomUUID());
|
this(UUID.randomUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
public TrackGraph(UUID graphID) {
|
public TrackGraph(UUID graphID) {
|
||||||
id = graphID;
|
setId(graphID);
|
||||||
nodes = new HashMap<>();
|
nodes = new HashMap<>();
|
||||||
nodesById = new HashMap<>();
|
nodesById = new HashMap<>();
|
||||||
connectionsByNode = new IdentityHashMap<>();
|
connectionsByNode = new IdentityHashMap<>();
|
||||||
color = Color.rainbowColor(new Random(graphID.getLeastSignificantBits()).nextInt());
|
edgePoints = new EdgePointStorage();
|
||||||
stations = new HashMap<>();
|
|
||||||
signals = new HashMap<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
@Nullable
|
public <T extends TrackEdgePoint> void addPoint(EdgePointType<T> type, T point) {
|
||||||
public GlobalStation getStation(UUID id) {
|
edgePoints.put(type, point);
|
||||||
return stations.get(id);
|
EdgePointManager.onEdgePointAdded(this, point, type);
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public SignalBoundary getSignal(UUID id) {
|
|
||||||
return signals.get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<GlobalStation> getStations() {
|
|
||||||
return stations.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<SignalBoundary> getSignals() {
|
|
||||||
return signals.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addStation(GlobalStation station) {
|
|
||||||
stations.put(station.id, station);
|
|
||||||
SignalPropagator.onEdgePointAdded(this, station, GlobalStation.class);
|
|
||||||
markDirty();
|
markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addSignal(SignalBoundary signal) {
|
public <T extends TrackEdgePoint> T getPoint(EdgePointType<T> type, UUID id) {
|
||||||
signals.put(signal.id, signal);
|
return edgePoints.get(type, id);
|
||||||
SignalPropagator.onEdgePointAdded(this, signal, SignalBoundary.class);
|
|
||||||
markDirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeStation(UUID id) {
|
public <T extends TrackEdgePoint> Collection<T> getPoints(EdgePointType<T> type) {
|
||||||
stations.remove(id);
|
return edgePoints.values(type);
|
||||||
markDirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeSignal(UUID id) {
|
public <T extends TrackEdgePoint> T removePoint(EdgePointType<T> type, UUID id) {
|
||||||
SignalBoundary signal = signals.remove(id);
|
T removed = edgePoints.remove(type, id);
|
||||||
if (signal == null)
|
if (removed == null)
|
||||||
return;
|
return null;
|
||||||
SignalPropagator.onSignalRemoved(this, signal);
|
EdgePointManager.onEdgePointRemoved(this, removed, type);
|
||||||
markDirty();
|
markDirty();
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tickPoints() {
|
||||||
|
edgePoints.tick(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -135,8 +117,8 @@ public class TrackGraph {
|
||||||
return nodesById.get(netId);
|
return nodesById.get(netId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean createNode(DiscoveredLocation location) {
|
public boolean createNodeIfAbsent(DiscoveredLocation location) {
|
||||||
if (!createSpecificNode(location, nextNodeId(), location.normal))
|
if (!addNodeIfAbsent(new TrackNode(location, nextNodeId(), location.normal)))
|
||||||
return false;
|
return false;
|
||||||
TrackNode newNode = nodes.get(location);
|
TrackNode newNode = nodes.get(location);
|
||||||
Create.RAILWAYS.sync.nodeAdded(this, newNode);
|
Create.RAILWAYS.sync.nodeAdded(this, newNode);
|
||||||
|
@ -144,11 +126,19 @@ public class TrackGraph {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean createSpecificNode(TrackNodeLocation location, int netId, Vec3 normal) {
|
public void loadNode(TrackNodeLocation location, int netId, Vec3 normal) {
|
||||||
return addNode(new TrackNode(location, netId, normal));
|
addNode(new TrackNode(location, netId, normal));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addNode(TrackNode node) {
|
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)
|
if (nodes.putIfAbsent(node.getLocation(), node) != null)
|
||||||
return false;
|
return false;
|
||||||
nodesById.put(node.getNetId(), node);
|
nodesById.put(node.getNetId(), node);
|
||||||
|
@ -160,22 +150,6 @@ public class TrackGraph {
|
||||||
if (removed == null)
|
if (removed == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (level != null) {
|
|
||||||
for (Iterator<UUID> iterator = stations.keySet()
|
|
||||||
.iterator(); iterator.hasNext();) {
|
|
||||||
UUID uuid = iterator.next();
|
|
||||||
GlobalStation globalStation = stations.get(uuid);
|
|
||||||
Couple<TrackNodeLocation> loc = globalStation.edgeLocation;
|
|
||||||
if (loc.getFirst()
|
|
||||||
.equals(location)
|
|
||||||
|| loc.getSecond()
|
|
||||||
.equals(location)) {
|
|
||||||
globalStation.migrate(level);
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<UUID, Train> trains = Create.RAILWAYS.trains;
|
Map<UUID, Train> trains = Create.RAILWAYS.trains;
|
||||||
for (Iterator<UUID> iterator = trains.keySet()
|
for (Iterator<UUID> iterator = trains.keySet()
|
||||||
.iterator(); iterator.hasNext();) {
|
.iterator(); iterator.hasNext();) {
|
||||||
|
@ -193,13 +167,18 @@ public class TrackGraph {
|
||||||
|
|
||||||
Map<TrackNode, TrackEdge> connections = connectionsByNode.remove(removed);
|
Map<TrackNode, TrackEdge> connections = connectionsByNode.remove(removed);
|
||||||
for (TrackEdge trackEdge : connections.values())
|
for (TrackEdge trackEdge : connections.values())
|
||||||
for (SignalBoundary boundary : trackEdge.getEdgeData()
|
for (TrackEdgePoint point : trackEdge.getEdgeData()
|
||||||
.getBoundaries())
|
.getPoints()) {
|
||||||
signals.remove(boundary.id);
|
if (level != null)
|
||||||
|
point.invalidate(level);
|
||||||
|
edgePoints.remove(point.getType(), point.getId());
|
||||||
|
}
|
||||||
|
|
||||||
for (TrackNode railNode : connections.keySet())
|
for (TrackNode railNode : connections.keySet())
|
||||||
if (connectionsByNode.containsKey(railNode))
|
if (connectionsByNode.containsKey(railNode))
|
||||||
connectionsByNode.get(railNode)
|
connectionsByNode.get(railNode)
|
||||||
.remove(removed);
|
.remove(removed);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,20 +187,23 @@ public class TrackGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void transferAll(TrackGraph toOther) {
|
public void transferAll(TrackGraph toOther) {
|
||||||
toOther.nodes.putAll(nodes);
|
nodes.forEach((loc, node) -> {
|
||||||
toOther.nodesById.putAll(nodesById);
|
if (toOther.addNodeIfAbsent(node))
|
||||||
toOther.connectionsByNode.putAll(connectionsByNode);
|
Create.RAILWAYS.sync.nodeAdded(toOther, node);
|
||||||
for (GlobalStation globalStation : stations.values())
|
});
|
||||||
toOther.addStation(globalStation);
|
|
||||||
|
|
||||||
nodesById.forEach((id, node) -> Create.RAILWAYS.sync.nodeAdded(toOther, node));
|
connectionsByNode.forEach((node1, map) -> map.forEach((node2, edge) -> {
|
||||||
connectionsByNode.forEach(
|
TrackNode n1 = toOther.locateNode(node1.location);
|
||||||
(node1, map) -> map.forEach((node2, edge) -> Create.RAILWAYS.sync.edgeAdded(toOther, node1, node2, edge)));
|
TrackNode n2 = toOther.locateNode(node2.location);
|
||||||
markDirty();
|
if (n1 == null || n2 == null)
|
||||||
|
return;
|
||||||
|
toOther.putConnection(n1, n2, edge);
|
||||||
|
Create.RAILWAYS.sync.edgeAdded(toOther, n1, n2, edge);
|
||||||
|
}));
|
||||||
|
|
||||||
|
edgePoints.transferAll(toOther.edgePoints);
|
||||||
|
|
||||||
stations.clear();
|
|
||||||
nodes.clear();
|
nodes.clear();
|
||||||
nodesById.clear();
|
|
||||||
connectionsByNode.clear();
|
connectionsByNode.clear();
|
||||||
|
|
||||||
Map<UUID, Train> trains = Create.RAILWAYS.trains;
|
Map<UUID, Train> trains = Create.RAILWAYS.trains;
|
||||||
|
@ -263,7 +245,7 @@ public class TrackGraph {
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
transfer(currentNode, target);
|
transfer(currentNode, target);
|
||||||
if (preAssignedIds != null && preAssignedIds.containsKey(currentNode.getNetId()))
|
if (preAssignedIds != null && preAssignedIds.containsKey(currentNode.getNetId()))
|
||||||
target.id = preAssignedIds.get(currentNode.getNetId());
|
target.setId(preAssignedIds.get(currentNode.getNetId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,31 +256,29 @@ public class TrackGraph {
|
||||||
return dicovered;
|
return dicovered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setId(UUID id) {
|
||||||
|
this.id = id;
|
||||||
|
color = Color.rainbowColor(new Random(id.getLeastSignificantBits()).nextInt());
|
||||||
|
}
|
||||||
|
|
||||||
public void transfer(TrackNode node, TrackGraph target) {
|
public void transfer(TrackNode node, TrackGraph target) {
|
||||||
target.addNode(node);
|
target.addNode(node);
|
||||||
TrackNodeLocation location1 = node.getLocation();
|
|
||||||
|
|
||||||
|
TrackNodeLocation nodeLoc = node.getLocation();
|
||||||
Map<TrackNode, TrackEdge> connections = getConnectionsFrom(node);
|
Map<TrackNode, TrackEdge> connections = getConnectionsFrom(node);
|
||||||
|
Map<UUID, Train> trains = Create.RAILWAYS.trains;
|
||||||
|
|
||||||
if (!connections.isEmpty()) {
|
if (!connections.isEmpty()) {
|
||||||
target.connectionsByNode.put(node, connections);
|
target.connectionsByNode.put(node, connections);
|
||||||
for (TrackNode entry : connections.keySet()) {
|
for (TrackEdge entry : connections.values()) {
|
||||||
for (Iterator<UUID> iterator = stations.keySet()
|
EdgeData edgeData = entry.getEdgeData();
|
||||||
.iterator(); iterator.hasNext();) {
|
for (TrackEdgePoint trackEdgePoint : edgeData.getPoints()) {
|
||||||
UUID uuid = iterator.next();
|
target.edgePoints.put(trackEdgePoint.getType(), trackEdgePoint);
|
||||||
GlobalStation globalStation = stations.get(uuid);
|
edgePoints.remove(trackEdgePoint.getType(), trackEdgePoint.getId());
|
||||||
Couple<TrackNodeLocation> loc = globalStation.edgeLocation;
|
|
||||||
if (loc.getFirst()
|
|
||||||
.equals(location1)
|
|
||||||
&& loc.getSecond()
|
|
||||||
.equals(entry.getLocation())) {
|
|
||||||
target.addStation(globalStation);
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<UUID, Train> trains = Create.RAILWAYS.trains;
|
|
||||||
for (Iterator<UUID> iterator = trains.keySet()
|
for (Iterator<UUID> iterator = trains.keySet()
|
||||||
.iterator(); iterator.hasNext();) {
|
.iterator(); iterator.hasNext();) {
|
||||||
UUID uuid = iterator.next();
|
UUID uuid = iterator.next();
|
||||||
|
@ -310,7 +290,7 @@ public class TrackGraph {
|
||||||
train.graph = target;
|
train.graph = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes.remove(location1);
|
nodes.remove(nodeLoc);
|
||||||
nodesById.remove(node.getNetId());
|
nodesById.remove(node.getNetId());
|
||||||
connectionsByNode.remove(node);
|
connectionsByNode.remove(node);
|
||||||
}
|
}
|
||||||
|
@ -391,19 +371,14 @@ public class TrackGraph {
|
||||||
});
|
});
|
||||||
|
|
||||||
tag.put("Nodes", nodesList);
|
tag.put("Nodes", nodesList);
|
||||||
tag.put("Stations", NBTHelper.writeCompoundList(getStations(), GlobalStation::write));
|
tag.put("Points", edgePoints.write());
|
||||||
tag.put("Signals", NBTHelper.writeCompoundList(getSignals(), SignalBoundary::write));
|
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TrackGraph read(CompoundTag tag) {
|
public static TrackGraph read(CompoundTag tag) {
|
||||||
TrackGraph graph = new TrackGraph(tag.getUUID("Id"));
|
TrackGraph graph = new TrackGraph(tag.getUUID("Id"));
|
||||||
graph.color = new Color(tag.getInt("Color"));
|
graph.color = new Color(tag.getInt("Color"));
|
||||||
|
graph.edgePoints.read(tag.getCompound("Points"));
|
||||||
NBTHelper.readCompoundList(tag.getList("Signals", Tag.TAG_COMPOUND), SignalBoundary::new)
|
|
||||||
.forEach(s -> graph.signals.put(s.id, s));
|
|
||||||
NBTHelper.readCompoundList(tag.getList("Stations", Tag.TAG_COMPOUND), GlobalStation::new)
|
|
||||||
.forEach(s -> graph.stations.put(s.id, s));
|
|
||||||
|
|
||||||
Map<Integer, TrackNode> indexTracker = new HashMap<>();
|
Map<Integer, TrackNode> indexTracker = new HashMap<>();
|
||||||
ListTag nodesList = tag.getList("Nodes", Tag.TAG_COMPOUND);
|
ListTag nodesList = tag.getList("Nodes", Tag.TAG_COMPOUND);
|
||||||
|
@ -414,7 +389,7 @@ public class TrackGraph {
|
||||||
TrackNodeLocation location =
|
TrackNodeLocation location =
|
||||||
TrackNodeLocation.fromPackedPos(NbtUtils.readBlockPos(nodeTag.getCompound("Location")));
|
TrackNodeLocation.fromPackedPos(NbtUtils.readBlockPos(nodeTag.getCompound("Location")));
|
||||||
Vec3 normal = VecHelper.readNBT(nodeTag.getList("Normal", Tag.TAG_DOUBLE));
|
Vec3 normal = VecHelper.readNBT(nodeTag.getList("Normal", Tag.TAG_DOUBLE));
|
||||||
graph.createSpecificNode(location, nextNodeId(), normal);
|
graph.loadNode(location, nextNodeId(), normal);
|
||||||
indexTracker.put(i, graph.locateNode(location));
|
indexTracker.put(i, graph.locateNode(location));
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -430,7 +405,6 @@ public class TrackGraph {
|
||||||
NBTHelper.iterateCompoundList(nodeTag.getList("Connections", Tag.TAG_COMPOUND), c -> {
|
NBTHelper.iterateCompoundList(nodeTag.getList("Connections", Tag.TAG_COMPOUND), c -> {
|
||||||
TrackNode node2 = indexTracker.get(c.getInt("To"));
|
TrackNode node2 = indexTracker.get(c.getInt("To"));
|
||||||
TrackEdge edge = TrackEdge.read(c.getCompound("EdgeData"), graph);
|
TrackEdge edge = TrackEdge.read(c.getCompound("EdgeData"), graph);
|
||||||
edge.edgeData.updateDelegates(node1, node2, edge);
|
|
||||||
graph.putConnection(node1, node2, edge);
|
graph.putConnection(node1, node2, edge);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -475,13 +449,30 @@ public class TrackGraph {
|
||||||
Vec3 p1 = edge.getPosition(node, other, 0);
|
Vec3 p1 = edge.getPosition(node, other, 0);
|
||||||
Vec3 p2 = edge.getPosition(node, other, 1);
|
Vec3 p2 = edge.getPosition(node, other, 1);
|
||||||
|
|
||||||
if (signalData.hasBoundaries()) {
|
if (signalData.hasPoints()) {
|
||||||
SignalBoundary boundary = signalData.nextBoundary(node, other, edge, 0);
|
|
||||||
SignalBoundary prevBoundaryNonNull = boundary;
|
|
||||||
double prev = 0;
|
double prev = 0;
|
||||||
double length = edge.getLength(node, other);
|
double length = edge.getLength(node, other);
|
||||||
SignalEdgeGroup group = Create.RAILWAYS.signalEdgeGroups.get(boundary.getGroup(node));
|
SignalBoundary prevBoundary = null;
|
||||||
while (boundary != null) {
|
SignalEdgeGroup group = null;
|
||||||
|
|
||||||
|
for (TrackEdgePoint trackEdgePoint : signalData.getPoints()) {
|
||||||
|
if (trackEdgePoint instanceof GlobalStation) {
|
||||||
|
Vec3 v1 = edge
|
||||||
|
.getPosition(node, other,
|
||||||
|
(trackEdgePoint.getLocationOn(node, other, edge) / length))
|
||||||
|
.add(yOffset);
|
||||||
|
Vec3 v2 = v1.add(node.normal.scale(3 / 16f));
|
||||||
|
CreateClient.OUTLINER.showLine(trackEdgePoint.id, v1, v2)
|
||||||
|
.colored(Color.mixColors(Color.WHITE, color, 1))
|
||||||
|
.lineWidth(1 / 8f);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!(trackEdgePoint instanceof SignalBoundary boundary))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
prevBoundary = boundary;
|
||||||
|
group = Create.RAILWAYS.signalEdgeGroups.get(boundary.getGroup(node));
|
||||||
|
|
||||||
if (group != null)
|
if (group != null)
|
||||||
CreateClient.OUTLINER
|
CreateClient.OUTLINER
|
||||||
.showLine(Pair.of(boundary, edge),
|
.showLine(Pair.of(boundary, edge),
|
||||||
|
@ -493,21 +484,20 @@ public class TrackGraph {
|
||||||
.add(yOffset))
|
.add(yOffset))
|
||||||
.colored(group.color.getRGB())
|
.colored(group.color.getRGB())
|
||||||
.lineWidth(1 / 16f);
|
.lineWidth(1 / 16f);
|
||||||
boundary =
|
|
||||||
signalData.nextBoundary(node, other, edge, boundary.getLocationOn(node, other, edge));
|
|
||||||
if (boundary != null) {
|
|
||||||
group = Create.RAILWAYS.signalEdgeGroups.get(boundary.getGroup(node));
|
|
||||||
prevBoundaryNonNull = boundary;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
group = Create.RAILWAYS.signalEdgeGroups.get(prevBoundaryNonNull.getGroup(other));
|
if (prevBoundary != null) {
|
||||||
|
group = Create.RAILWAYS.signalEdgeGroups.get(prevBoundary.getGroup(other));
|
||||||
if (group != null)
|
if (group != null)
|
||||||
CreateClient.OUTLINER.showLine(edge, edge.getPosition(node, other, prev + 1 / 16f / length)
|
CreateClient.OUTLINER
|
||||||
|
.showLine(edge, edge.getPosition(node, other, prev + 1 / 16f / length)
|
||||||
.add(yOffset), p2.add(yOffset))
|
.add(yOffset), p2.add(yOffset))
|
||||||
.colored(group.color.getRGB())
|
.colored(group.color.getRGB())
|
||||||
.lineWidth(1 / 16f);
|
.lineWidth(1 / 16f);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (signalEdgeGroup == null)
|
if (signalEdgeGroup == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -56,8 +56,16 @@ public class TrackGraphSync {
|
||||||
|
|
||||||
public void nodeRemoved(TrackGraph graph, TrackNode node) {
|
public void nodeRemoved(TrackGraph graph, TrackNode node) {
|
||||||
flushPacket(graph.id);
|
flushPacket(graph.id);
|
||||||
if (currentPacket.addedNodes.remove(node.getNetId()) == null)
|
int nodeId = node.getNetId();
|
||||||
currentPacket.removedNodes.add(node.getNetId());
|
if (currentPacket.addedNodes.remove(nodeId) == null)
|
||||||
|
currentPacket.removedNodes.add(nodeId);
|
||||||
|
currentPacket.addedEdges.removeIf(pair -> {
|
||||||
|
Couple<Integer> ids = pair.getFirst();
|
||||||
|
return ids.getFirst()
|
||||||
|
.intValue() == nodeId
|
||||||
|
|| ids.getSecond()
|
||||||
|
.intValue() == nodeId;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void graphSplit(TrackGraph graph, Set<TrackGraph> additional) {
|
public void graphSplit(TrackGraph graph, Set<TrackGraph> additional) {
|
||||||
|
@ -80,18 +88,24 @@ public class TrackGraphSync {
|
||||||
//
|
//
|
||||||
|
|
||||||
public void sendFullGraphTo(TrackGraph graph, ServerPlayer player) {
|
public void sendFullGraphTo(TrackGraph graph, ServerPlayer player) {
|
||||||
// TODO ensure packet size limit
|
|
||||||
|
|
||||||
RailGraphSyncPacket packet = new RailGraphSyncPacket(graph.id);
|
RailGraphSyncPacket packet = new RailGraphSyncPacket(graph.id);
|
||||||
|
int sent = 0;
|
||||||
for (TrackNode node : graph.nodes.values()) {
|
for (TrackNode node : graph.nodes.values()) {
|
||||||
packet.addedNodes.put(node.getNetId(), Pair.of(node.getLocation(), node.getNormal()));
|
RailGraphSyncPacket currentPacket = packet;
|
||||||
|
currentPacket.addedNodes.put(node.getNetId(), Pair.of(node.getLocation(), node.getNormal()));
|
||||||
if (!graph.connectionsByNode.containsKey(node))
|
if (!graph.connectionsByNode.containsKey(node))
|
||||||
continue;
|
continue;
|
||||||
graph.connectionsByNode.get(node)
|
graph.connectionsByNode.get(node)
|
||||||
.forEach((node2, edge) -> packet.addedEdges
|
.forEach((node2, edge) -> currentPacket.addedEdges
|
||||||
.add(Pair.of(Couple.create(node.getNetId(), node2.getNetId()), edge)));
|
.add(Pair.of(Couple.create(node.getNetId(), node2.getNetId()), edge)));
|
||||||
}
|
|
||||||
|
|
||||||
|
if (sent++ > 1000) {
|
||||||
|
sent = 0;
|
||||||
|
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), packet);
|
||||||
|
packet = new RailGraphSyncPacket(graph.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sent > 0)
|
||||||
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), packet);
|
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +175,7 @@ public class TrackGraphSync {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(FriendlyByteBuf buffer) {
|
public void write(FriendlyByteBuf buffer) {
|
||||||
|
|
||||||
buffer.writeUUID(graphId);
|
buffer.writeUUID(graphId);
|
||||||
buffer.writeBoolean(delete);
|
buffer.writeBoolean(delete);
|
||||||
if (delete)
|
if (delete)
|
||||||
|
@ -209,11 +224,11 @@ public class TrackGraphSync {
|
||||||
railGraph.removeNode(null, node.getLocation());
|
railGraph.removeNode(null, node.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Entry<Integer, Pair<TrackNodeLocation, Vec3>> entry : addedNodes.entrySet())
|
for (Entry<Integer, Pair<TrackNodeLocation, Vec3>> entry : addedNodes.entrySet()) {
|
||||||
railGraph.createSpecificNode(entry.getValue()
|
Integer nodeId = entry.getKey();
|
||||||
.getFirst(), entry.getKey(),
|
Pair<TrackNodeLocation, Vec3> nodeLocation = entry.getValue();
|
||||||
entry.getValue()
|
railGraph.loadNode(nodeLocation.getFirst(), nodeId, nodeLocation.getSecond());
|
||||||
.getSecond());
|
}
|
||||||
|
|
||||||
for (Pair<Couple<Integer>, TrackEdge> pair : addedEdges) {
|
for (Pair<Couple<Integer>, TrackEdge> pair : addedEdges) {
|
||||||
Couple<TrackNode> nodes = pair.getFirst()
|
Couple<TrackNode> nodes = pair.getFirst()
|
||||||
|
|
|
@ -38,26 +38,23 @@ public class TrackPropagator {
|
||||||
Collection<DiscoveredLocation> ends = track.getConnected(reader, pos, state, false, null);
|
Collection<DiscoveredLocation> ends = track.getConnected(reader, pos, state, false, null);
|
||||||
GlobalRailwayManager manager = Create.RAILWAYS;
|
GlobalRailwayManager manager = Create.RAILWAYS;
|
||||||
TrackGraphSync sync = manager.sync;
|
TrackGraphSync sync = manager.sync;
|
||||||
TrackGraph foundGraph = null;
|
|
||||||
|
|
||||||
// 1. Remove any nodes this rail was part of
|
// 1. Remove any nodes this rail was part of
|
||||||
|
|
||||||
for (DiscoveredLocation removedLocation : ends) {
|
for (DiscoveredLocation removedLocation : ends) {
|
||||||
if (foundGraph == null)
|
List<TrackGraph> intersecting = manager.getGraphs(reader, removedLocation);
|
||||||
foundGraph = manager.getGraph(reader, removedLocation);
|
for (TrackGraph foundGraph : intersecting) {
|
||||||
if (foundGraph == null)
|
|
||||||
continue;
|
|
||||||
TrackNode removedNode = foundGraph.locateNode(removedLocation);
|
TrackNode removedNode = foundGraph.locateNode(removedLocation);
|
||||||
if (removedNode != null) {
|
if (removedNode == null)
|
||||||
|
continue;
|
||||||
foundGraph.removeNode(reader, removedLocation);
|
foundGraph.removeNode(reader, removedLocation);
|
||||||
sync.nodeRemoved(foundGraph, removedNode);
|
sync.nodeRemoved(foundGraph, removedNode);
|
||||||
}
|
if (!foundGraph.isEmpty())
|
||||||
}
|
continue;
|
||||||
|
|
||||||
if (foundGraph != null && foundGraph.isEmpty()) {
|
|
||||||
manager.removeGraph(foundGraph);
|
manager.removeGraph(foundGraph);
|
||||||
sync.graphRemoved(foundGraph);
|
sync.graphRemoved(foundGraph);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Set<BlockPos> positionsToUpdate = new HashSet<>();
|
Set<BlockPos> positionsToUpdate = new HashSet<>();
|
||||||
for (DiscoveredLocation removedEnd : ends)
|
for (DiscoveredLocation removedEnd : ends)
|
||||||
|
@ -100,8 +97,8 @@ public class TrackPropagator {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
FrontierEntry entry = frontier.remove(0);
|
FrontierEntry entry = frontier.remove(0);
|
||||||
TrackGraph graph = manager.getGraph(reader, entry.currentNode);
|
List<TrackGraph> intersecting = manager.getGraphs(reader, entry.currentNode);
|
||||||
if (graph != null) {
|
for (TrackGraph graph : intersecting) {
|
||||||
TrackNode node = graph.locateNode(entry.currentNode);
|
TrackNode node = graph.locateNode(entry.currentNode);
|
||||||
graph.removeNode(reader, entry.currentNode);
|
graph.removeNode(reader, entry.currentNode);
|
||||||
sync.nodeRemoved(graph, node);
|
sync.nodeRemoved(graph, node);
|
||||||
|
@ -109,6 +106,9 @@ public class TrackPropagator {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!intersecting.isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
Collection<DiscoveredLocation> ends = ITrackBlock.walkConnectedTracks(reader, entry.currentNode, false);
|
Collection<DiscoveredLocation> ends = ITrackBlock.walkConnectedTracks(reader, entry.currentNode, false);
|
||||||
if (entry.prevNode != null)
|
if (entry.prevNode != null)
|
||||||
ends.remove(entry.prevNode);
|
ends.remove(entry.prevNode);
|
||||||
|
@ -117,7 +117,6 @@ public class TrackPropagator {
|
||||||
|
|
||||||
frontier.clear();
|
frontier.clear();
|
||||||
visited.clear();
|
visited.clear();
|
||||||
|
|
||||||
TrackGraph graph = null;
|
TrackGraph graph = null;
|
||||||
|
|
||||||
// Remove empty graphs
|
// Remove empty graphs
|
||||||
|
@ -173,11 +172,7 @@ public class TrackPropagator {
|
||||||
|
|
||||||
frontier.clear();
|
frontier.clear();
|
||||||
Set<TrackNode> addedNodes = new HashSet<>();
|
Set<TrackNode> addedNodes = new HashSet<>();
|
||||||
if (graph.createNode(startNode)) {
|
graph.createNodeIfAbsent(startNode);
|
||||||
TrackNode node = graph.locateNode(startNode);
|
|
||||||
sync.nodeAdded(graph, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
frontier.add(new FrontierEntry(startNode, null, startNode));
|
frontier.add(new FrontierEntry(startNode, null, startNode));
|
||||||
|
|
||||||
// 3. Build up the graph via all connected nodes
|
// 3. Build up the graph via all connected nodes
|
||||||
|
@ -195,11 +190,7 @@ public class TrackPropagator {
|
||||||
ends.remove(entry.prevNode);
|
ends.remove(entry.prevNode);
|
||||||
|
|
||||||
if (isValidGraphNodeLocation(entry.currentNode, ends, first) && entry.currentNode != startNode) {
|
if (isValidGraphNodeLocation(entry.currentNode, ends, first) && entry.currentNode != startNode) {
|
||||||
boolean nodeIsNew = graph.createNode(entry.currentNode);
|
boolean nodeIsNew = graph.createNodeIfAbsent(entry.currentNode);
|
||||||
if (nodeIsNew) {
|
|
||||||
TrackNode node = graph.locateNode(entry.currentNode);
|
|
||||||
sync.nodeAdded(graph, node);
|
|
||||||
}
|
|
||||||
graph.connectNodes(parentNode, entry.currentNode, new TrackEdge(entry.currentNode.getTurn()));
|
graph.connectNodes(parentNode, entry.currentNode, new TrackEdge(entry.currentNode.getTurn()));
|
||||||
addedNodes.add(graph.locateNode(entry.currentNode));
|
addedNodes.add(graph.locateNode(entry.currentNode));
|
||||||
parentNode = entry.currentNode;
|
parentNode = entry.currentNode;
|
||||||
|
|
|
@ -9,7 +9,6 @@ import java.util.Map.Entry;
|
||||||
import java.util.PriorityQueue;
|
import java.util.PriorityQueue;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.BiPredicate;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.mutable.MutableObject;
|
import org.apache.commons.lang3.mutable.MutableObject;
|
||||||
|
|
||||||
|
@ -17,12 +16,13 @@ import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackEdge;
|
import com.simibubi.create.content.logistics.trains.TrackEdge;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackNode;
|
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.entity.TravellingPoint.ITrackSelector;
|
||||||
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
|
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
|
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
|
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.SignalEdgeGroup;
|
import com.simibubi.create.content.logistics.trains.management.signal.SignalEdgeGroup;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.signal.TrackEdgePoint;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
@ -79,13 +79,14 @@ public class Navigation {
|
||||||
double acceleration = AllConfigs.SERVER.trains.getAccelerationMPTT();
|
double acceleration = AllConfigs.SERVER.trains.getAccelerationMPTT();
|
||||||
double brakingDistance = (train.speed * train.speed) / (2 * acceleration);
|
double brakingDistance = (train.speed * train.speed) / (2 * acceleration);
|
||||||
double speedMod = destinationBehindTrain ? -1 : 1;
|
double speedMod = destinationBehindTrain ? -1 : 1;
|
||||||
|
double preDepartureLookAhead = train.getCurrentStation() != null ? 4.5 : 0;
|
||||||
|
|
||||||
// Signals
|
// Signals
|
||||||
if (train.graph != null) {
|
if (train.graph != null) {
|
||||||
if (waitingForSignal != null && checkBlockingSignal())
|
if (waitingForSignal != null && checkBlockingSignal())
|
||||||
waitingForSignal = null;
|
waitingForSignal = null;
|
||||||
|
|
||||||
TravellingPoint leadingPoint = train.speed > 0 ? train.carriages.get(0)
|
TravellingPoint leadingPoint = !destinationBehindTrain ? train.carriages.get(0)
|
||||||
.getLeadingPoint()
|
.getLeadingPoint()
|
||||||
: train.carriages.get(train.carriages.size() - 1)
|
: train.carriages.get(train.carriages.size() - 1)
|
||||||
.getTrailingPoint();
|
.getTrailingPoint();
|
||||||
|
@ -93,13 +94,19 @@ public class Navigation {
|
||||||
if (waitingForSignal == null)
|
if (waitingForSignal == null)
|
||||||
distanceToSignal = Double.MAX_VALUE;
|
distanceToSignal = Double.MAX_VALUE;
|
||||||
|
|
||||||
|
if (train.getCurrentStation() != null) {
|
||||||
|
int i = 0;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
if (distanceToSignal > 1 / 16f) {
|
if (distanceToSignal > 1 / 16f) {
|
||||||
signalScout.node1 = leadingPoint.node1;
|
signalScout.node1 = leadingPoint.node1;
|
||||||
signalScout.node2 = leadingPoint.node2;
|
signalScout.node2 = leadingPoint.node2;
|
||||||
signalScout.edge = leadingPoint.edge;
|
signalScout.edge = leadingPoint.edge;
|
||||||
signalScout.position = leadingPoint.position;
|
signalScout.position = leadingPoint.position;
|
||||||
|
|
||||||
double brakingDistanceNoFlicker = brakingDistance + 3 - (brakingDistance % 3);
|
double brakingDistanceNoFlicker =
|
||||||
|
Math.max(preDepartureLookAhead, brakingDistance + 3 - (brakingDistance % 3));
|
||||||
double scanDistance = Math.min(distanceToDestination - .5f, brakingDistanceNoFlicker);
|
double scanDistance = Math.min(distanceToDestination - .5f, brakingDistanceNoFlicker);
|
||||||
|
|
||||||
signalScout.travel(train.graph, scanDistance * speedMod, controlSignalScout(), (distance, couple) -> {
|
signalScout.travel(train.graph, scanDistance * speedMod, controlSignalScout(), (distance, couple) -> {
|
||||||
|
@ -133,6 +140,11 @@ public class Navigation {
|
||||||
train.arriveAt(destination);
|
train.arriveAt(destination);
|
||||||
destination = null;
|
destination = null;
|
||||||
return;
|
return;
|
||||||
|
} else if (train.getCurrentStation() != null) {
|
||||||
|
// dont leave until green light
|
||||||
|
if (waitingForSignal != null && distanceToSignal < preDepartureLookAhead)
|
||||||
|
return;
|
||||||
|
train.leaveStation();
|
||||||
}
|
}
|
||||||
|
|
||||||
train.currentlyBackwards = destinationBehindTrain;
|
train.currentlyBackwards = destinationBehindTrain;
|
||||||
|
@ -158,7 +170,7 @@ public class Navigation {
|
||||||
private boolean checkBlockingSignal() {
|
private boolean checkBlockingSignal() {
|
||||||
if (distanceToDestination < .5f)
|
if (distanceToDestination < .5f)
|
||||||
return true;
|
return true;
|
||||||
SignalBoundary signal = train.graph.getSignal(waitingForSignal.getFirst());
|
SignalBoundary signal = train.graph.getPoint(EdgePointType.SIGNAL, waitingForSignal.getFirst());
|
||||||
if (signal == null)
|
if (signal == null)
|
||||||
return true;
|
return true;
|
||||||
UUID groupId = signal.groups.get(waitingForSignal.getSecond());
|
UUID groupId = signal.groups.get(waitingForSignal.getSecond());
|
||||||
|
@ -167,11 +179,8 @@ public class Navigation {
|
||||||
SignalEdgeGroup signalEdgeGroup = Create.RAILWAYS.signalEdgeGroups.get(groupId);
|
SignalEdgeGroup signalEdgeGroup = Create.RAILWAYS.signalEdgeGroups.get(groupId);
|
||||||
if (signalEdgeGroup == null)
|
if (signalEdgeGroup == null)
|
||||||
return true;
|
return true;
|
||||||
if (!signalEdgeGroup.isOccupiedUnless(train)) {
|
if (!signalEdgeGroup.isOccupiedUnless(train))
|
||||||
if (train.currentStation != null)
|
|
||||||
train.leaveStation();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,20 +281,6 @@ public class Navigation {
|
||||||
train.status.foundConductor();
|
train.status.foundConductor();
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalStation currentStation = train.getCurrentStation();
|
|
||||||
if (currentStation != null) {
|
|
||||||
SignalBoundary boundary = currentStation.boundary;
|
|
||||||
if (boundary != null) {
|
|
||||||
TrackNode node1 = train.graph.locateNode(currentStation.edgeLocation.getFirst());
|
|
||||||
UUID group = boundary.getGroup(node1);
|
|
||||||
if (group != null) {
|
|
||||||
waitingForSignal = Pair.of(boundary.id, !boundary.isPrimary(node1));
|
|
||||||
distanceToSignal = 0;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
train.leaveStation();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
return distanceToDestination;
|
return distanceToDestination;
|
||||||
}
|
}
|
||||||
|
@ -297,7 +292,6 @@ public class Navigation {
|
||||||
if (graph == null)
|
if (graph == null)
|
||||||
return Pair.of(null, path);
|
return Pair.of(null, path);
|
||||||
|
|
||||||
Couple<TrackNodeLocation> target = destination.edgeLocation;
|
|
||||||
MutableObject<Pair<Double, List<TrackEdge>>> frontResult = new MutableObject<>(Pair.of(null, path));
|
MutableObject<Pair<Double, List<TrackEdge>>> frontResult = new MutableObject<>(Pair.of(null, path));
|
||||||
MutableObject<Pair<Double, List<TrackEdge>>> backResult = new MutableObject<>(Pair.of(null, path));
|
MutableObject<Pair<Double, List<TrackEdge>>> backResult = new MutableObject<>(Pair.of(null, path));
|
||||||
|
|
||||||
|
@ -314,21 +308,16 @@ public class Navigation {
|
||||||
: graph.getConnectionsFrom(initialPoint.node2)
|
: graph.getConnectionsFrom(initialPoint.node2)
|
||||||
.get(initialPoint.node1);
|
.get(initialPoint.node1);
|
||||||
|
|
||||||
search(Double.MAX_VALUE, forward, (reachedVia, poll) -> {
|
search(Double.MAX_VALUE, forward, (distance, reachedVia, currentEntry, globalStation) -> {
|
||||||
|
if (globalStation != destination)
|
||||||
|
return false;
|
||||||
|
|
||||||
double distance = poll.getFirst();
|
|
||||||
Pair<Couple<TrackNode>, TrackEdge> currentEntry = poll.getSecond();
|
|
||||||
TrackEdge edge = currentEntry.getSecond();
|
TrackEdge edge = currentEntry.getSecond();
|
||||||
TrackNode node1 = currentEntry.getFirst()
|
TrackNode node1 = currentEntry.getFirst()
|
||||||
.getFirst();
|
.getFirst();
|
||||||
TrackNode node2 = currentEntry.getFirst()
|
TrackNode node2 = currentEntry.getFirst()
|
||||||
.getSecond();
|
.getSecond();
|
||||||
|
|
||||||
TrackNodeLocation loc1 = node1.getLocation();
|
|
||||||
TrackNodeLocation loc2 = node2.getLocation();
|
|
||||||
if (!loc1.equals(target.getFirst()) || !loc2.equals(target.getSecond()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Pair<Boolean, TrackEdge> backTrack = reachedVia.get(edge);
|
Pair<Boolean, TrackEdge> backTrack = reachedVia.get(edge);
|
||||||
TrackEdge toReach = edge;
|
TrackEdge toReach = edge;
|
||||||
while (backTrack != null && toReach != initialEdge) {
|
while (backTrack != null && toReach != initialEdge) {
|
||||||
|
@ -338,7 +327,7 @@ public class Navigation {
|
||||||
backTrack = reachedVia.get(backTrack.getSecond());
|
backTrack = reachedVia.get(backTrack.getSecond());
|
||||||
}
|
}
|
||||||
|
|
||||||
double position = edge.getLength(node1, node2) - destination.position;
|
double position = edge.getLength(node1, node2) - destination.getLocationOn(node1, node2, edge);
|
||||||
double distanceToDestination = distance - position;
|
double distanceToDestination = distance - position;
|
||||||
|
|
||||||
if (forward)
|
if (forward)
|
||||||
|
@ -383,40 +372,27 @@ public class Navigation {
|
||||||
double minDistance = .75f * (train.speed * train.speed) / (2 * acceleration);
|
double minDistance = .75f * (train.speed * train.speed) / (2 * acceleration);
|
||||||
double maxDistance = Math.max(32, 1.5f * (train.speed * train.speed) / (2 * acceleration));
|
double maxDistance = Math.max(32, 1.5f * (train.speed * train.speed) / (2 * acceleration));
|
||||||
|
|
||||||
search(maxDistance, forward, (reachedVia, poll) -> {
|
search(maxDistance, forward, (distance, reachedVia, currentEntry, globalStation) -> {
|
||||||
double distance = poll.getFirst();
|
|
||||||
if (distance < minDistance)
|
if (distance < minDistance)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Pair<Couple<TrackNode>, TrackEdge> currentEntry = poll.getSecond();
|
|
||||||
TrackEdge edge = currentEntry.getSecond();
|
TrackEdge edge = currentEntry.getSecond();
|
||||||
TrackNode node1 = currentEntry.getFirst()
|
TrackNode node1 = currentEntry.getFirst()
|
||||||
.getFirst();
|
.getFirst();
|
||||||
TrackNode node2 = currentEntry.getFirst()
|
TrackNode node2 = currentEntry.getFirst()
|
||||||
.getSecond();
|
.getSecond();
|
||||||
|
|
||||||
for (GlobalStation globalStation : edge.getEdgeData()
|
double position = edge.getLength(node1, node2) - globalStation.getLocationOn(node1, node2, edge);
|
||||||
.getStations()) {
|
|
||||||
Couple<TrackNodeLocation> target = globalStation.edgeLocation;
|
|
||||||
TrackNodeLocation loc1 = node1.getLocation();
|
|
||||||
TrackNodeLocation loc2 = node2.getLocation();
|
|
||||||
if (!loc1.equals(target.getFirst()) || !loc2.equals(target.getSecond()))
|
|
||||||
continue;
|
|
||||||
double position = edge.getLength(node1, node2) - globalStation.position;
|
|
||||||
if (distance - position < minDistance)
|
if (distance - position < minDistance)
|
||||||
continue;
|
return false;
|
||||||
result.setValue(globalStation);
|
result.setValue(globalStation);
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return result.getValue();
|
return result.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void search(double maxDistance, boolean forward,
|
public void search(double maxDistance, boolean forward, StationTest stationTest) {
|
||||||
BiPredicate<Map<TrackEdge, Pair<Boolean, TrackEdge>>, Pair<Double, Pair<Couple<TrackNode>, TrackEdge>>> condition) {
|
|
||||||
TrackGraph graph = train.graph;
|
TrackGraph graph = train.graph;
|
||||||
if (graph == null)
|
if (graph == null)
|
||||||
return;
|
return;
|
||||||
|
@ -440,7 +416,7 @@ public class Navigation {
|
||||||
|
|
||||||
frontier.add(Pair.of(distanceToNode2, Pair.of(Couple.create(initialNode1, initialNode2), initialEdge)));
|
frontier.add(Pair.of(distanceToNode2, Pair.of(Couple.create(initialNode1, initialNode2), initialEdge)));
|
||||||
|
|
||||||
while (!frontier.isEmpty()) {
|
Search: while (!frontier.isEmpty()) {
|
||||||
Pair<Double, Pair<Couple<TrackNode>, TrackEdge>> poll = frontier.poll();
|
Pair<Double, Pair<Couple<TrackNode>, TrackEdge>> poll = frontier.poll();
|
||||||
double distance = poll.getFirst();
|
double distance = poll.getFirst();
|
||||||
if (distance > maxDistance)
|
if (distance > maxDistance)
|
||||||
|
@ -452,12 +428,24 @@ public class Navigation {
|
||||||
.getFirst();
|
.getFirst();
|
||||||
TrackNode node2 = currentEntry.getFirst()
|
TrackNode node2 = currentEntry.getFirst()
|
||||||
.getSecond();
|
.getSecond();
|
||||||
if (condition.test(reachedVia, poll))
|
|
||||||
|
EdgeData signalData = edge.getEdgeData();
|
||||||
|
if (signalData.hasPoints()) {
|
||||||
|
for (TrackEdgePoint point : signalData.getPoints()) {
|
||||||
|
if (node1 == initialNode1
|
||||||
|
&& point.getLocationOn(node1, node2, edge) < edge.getLength(node1, node2) - distanceToNode2)
|
||||||
|
continue;
|
||||||
|
if (!point.canNavigateVia(node2))
|
||||||
|
continue Search;
|
||||||
|
if (point instanceof GlobalStation station && station.canApproachFrom(node2)
|
||||||
|
&& stationTest.test(distance, reachedVia, currentEntry, station))
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<Entry<TrackNode, TrackEdge>> validTargets = new ArrayList<>();
|
List<Entry<TrackNode, TrackEdge>> validTargets = new ArrayList<>();
|
||||||
EdgeWalk: for (Entry<TrackNode, TrackEdge> entry : graph.getConnectionsFrom(node2)
|
Map<TrackNode, TrackEdge> connectionsFrom = graph.getConnectionsFrom(node2);
|
||||||
.entrySet()) {
|
for (Entry<TrackNode, TrackEdge> entry : connectionsFrom.entrySet()) {
|
||||||
TrackNode newNode = entry.getKey();
|
TrackNode newNode = entry.getKey();
|
||||||
TrackEdge newEdge = entry.getValue();
|
TrackEdge newEdge = entry.getValue();
|
||||||
Vec3 currentDirection = edge.getDirection(node1, node2, false);
|
Vec3 currentDirection = edge.getDirection(node1, node2, false);
|
||||||
|
@ -466,13 +454,6 @@ public class Navigation {
|
||||||
continue;
|
continue;
|
||||||
if (!visited.add(entry.getValue()))
|
if (!visited.add(entry.getValue()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
EdgeData signalData = newEdge.getEdgeData();
|
|
||||||
if (signalData.hasBoundaries())
|
|
||||||
for (SignalBoundary boundary : signalData.getBoundaries())
|
|
||||||
if (!boundary.canNavigateVia(node2))
|
|
||||||
continue EdgeWalk;
|
|
||||||
|
|
||||||
validTargets.add(entry);
|
validTargets.add(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,4 +470,10 @@ public class Navigation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface StationTest {
|
||||||
|
boolean test(double distance, Map<TrackEdge, Pair<Boolean, TrackEdge>> reachedVia,
|
||||||
|
Pair<Couple<TrackNode>, TrackEdge> current, GlobalStation station);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import com.simibubi.create.content.logistics.trains.management.GlobalStation;
|
||||||
import com.simibubi.create.content.logistics.trains.management.GraphLocation;
|
import com.simibubi.create.content.logistics.trains.management.GraphLocation;
|
||||||
import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime;
|
import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime;
|
||||||
import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime.State;
|
import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime.State;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
|
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
|
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.SignalEdgeGroup;
|
import com.simibubi.create.content.logistics.trains.management.signal.SignalEdgeGroup;
|
||||||
|
@ -556,7 +557,7 @@ public class Train {
|
||||||
return null;
|
return null;
|
||||||
if (graph == null)
|
if (graph == null)
|
||||||
return null;
|
return null;
|
||||||
return graph.getStation(currentStation);
|
return graph.getPoint(EdgePointType.STATION, currentStation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -596,16 +597,16 @@ public class Train {
|
||||||
Map<UUID, SignalEdgeGroup> allGroups = Create.RAILWAYS.signalEdgeGroups;
|
Map<UUID, SignalEdgeGroup> allGroups = Create.RAILWAYS.signalEdgeGroups;
|
||||||
MutableObject<UUID> prevGroup = new MutableObject<>(null);
|
MutableObject<UUID> prevGroup = new MutableObject<>(null);
|
||||||
|
|
||||||
if (signalData.hasBoundaries()) {
|
if (signalData.hasSignalBoundaries()) {
|
||||||
SignalBoundary nextBoundary = signalData.nextBoundary(node1, node2, edge, position);
|
SignalBoundary nextBoundary = signalData.next(EdgePointType.SIGNAL, node1, node2, edge, position);
|
||||||
if (nextBoundary == null) {
|
if (nextBoundary == null) {
|
||||||
double d = 0;
|
double d = 0;
|
||||||
SignalBoundary prev = null;
|
SignalBoundary prev = null;
|
||||||
SignalBoundary current = signalData.nextBoundary(node1, node2, edge, 0);
|
SignalBoundary current = signalData.next(EdgePointType.SIGNAL, node1, node2, edge, 0);
|
||||||
while (current != null) {
|
while (current != null) {
|
||||||
prev = current;
|
prev = current;
|
||||||
d = current.getLocationOn(node1, node2, edge);
|
d = current.getLocationOn(node1, node2, edge);
|
||||||
current = signalData.nextBoundary(node1, node2, edge, d);
|
current = signalData.next(EdgePointType.SIGNAL, node1, node2, edge, d);
|
||||||
}
|
}
|
||||||
if (prev != null) {
|
if (prev != null) {
|
||||||
UUID group = prev.getGroup(node2);
|
UUID group = prev.getGroup(node2);
|
||||||
|
|
|
@ -15,8 +15,9 @@ import com.simibubi.create.content.logistics.trains.TrackEdge;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackNode;
|
import com.simibubi.create.content.logistics.trains.TrackNode;
|
||||||
import com.simibubi.create.content.logistics.trains.management.GraphLocation;
|
import com.simibubi.create.content.logistics.trains.management.GraphLocation;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
|
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
import com.simibubi.create.foundation.utility.Pair;
|
import com.simibubi.create.foundation.utility.Pair;
|
||||||
|
|
||||||
|
@ -258,12 +259,12 @@ public class TravellingPoint {
|
||||||
private void edgeTraversedFrom(TrackGraph graph, boolean forward, ISignalBoundaryListener signalListener,
|
private void edgeTraversedFrom(TrackGraph graph, boolean forward, ISignalBoundaryListener signalListener,
|
||||||
double prevPos, double totalDistance) {
|
double prevPos, double totalDistance) {
|
||||||
EdgeData signalsOnEdge = edge.getEdgeData();
|
EdgeData signalsOnEdge = edge.getEdgeData();
|
||||||
if (!signalsOnEdge.hasBoundaries())
|
if (!signalsOnEdge.hasSignalBoundaries())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
double from = forward ? prevPos : position;
|
double from = forward ? prevPos : position;
|
||||||
double to = forward ? position : prevPos;
|
double to = forward ? position : prevPos;
|
||||||
SignalBoundary nextBoundary = signalsOnEdge.nextBoundary(node1, node2, edge, from);
|
SignalBoundary nextBoundary = signalsOnEdge.next(EdgePointType.SIGNAL, node1, node2, edge, from);
|
||||||
List<SignalBoundary> discoveredBoundaries = null;
|
List<SignalBoundary> discoveredBoundaries = null;
|
||||||
|
|
||||||
while (nextBoundary != null) {
|
while (nextBoundary != null) {
|
||||||
|
@ -273,7 +274,7 @@ public class TravellingPoint {
|
||||||
if (discoveredBoundaries == null)
|
if (discoveredBoundaries == null)
|
||||||
discoveredBoundaries = new ArrayList<>();
|
discoveredBoundaries = new ArrayList<>();
|
||||||
discoveredBoundaries.add(nextBoundary);
|
discoveredBoundaries.add(nextBoundary);
|
||||||
nextBoundary = signalsOnEdge.nextBoundary(node1, node2, edge, d);
|
nextBoundary = signalsOnEdge.next(EdgePointType.SIGNAL, node1, node2, edge, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (discoveredBoundaries == null)
|
if (discoveredBoundaries == null)
|
||||||
|
|
|
@ -1,57 +1,40 @@
|
||||||
package com.simibubi.create.content.logistics.trains.management;
|
package com.simibubi.create.content.logistics.trains.management;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
|
import com.simibubi.create.content.logistics.trains.TrackNode;
|
||||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
|
import com.simibubi.create.content.logistics.trains.management.signal.SingleTileEdgePoint;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.TrackEdgePoint;
|
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtUtils;
|
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
||||||
|
|
||||||
public class GlobalStation extends TrackEdgePoint {
|
public class GlobalStation extends SingleTileEdgePoint {
|
||||||
|
|
||||||
public String name;
|
public String name;
|
||||||
public BlockPos stationPos;
|
|
||||||
|
|
||||||
public WeakReference<Train> nearestTrain;
|
public WeakReference<Train> nearestTrain;
|
||||||
|
|
||||||
@Nullable
|
public GlobalStation() {
|
||||||
public SignalBoundary boundary;
|
|
||||||
|
|
||||||
public GlobalStation(UUID id, BlockPos stationPos) {
|
|
||||||
super(id);
|
|
||||||
this.stationPos = stationPos;
|
|
||||||
name = "Track Station";
|
name = "Track Station";
|
||||||
nearestTrain = new WeakReference<Train>(null);
|
nearestTrain = new WeakReference<Train>(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GlobalStation(CompoundTag nbt) {
|
@Override
|
||||||
super(nbt);
|
public void read(CompoundTag nbt, boolean migration) {
|
||||||
|
super.read(nbt, migration);
|
||||||
name = nbt.getString("Name");
|
name = nbt.getString("Name");
|
||||||
stationPos = NbtUtils.readBlockPos(nbt.getCompound("StationPos"));
|
|
||||||
nearestTrain = new WeakReference<Train>(null);
|
nearestTrain = new WeakReference<Train>(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void migrate(LevelAccessor level) {
|
@Override
|
||||||
BlockEntity blockEntity = level.getBlockEntity(stationPos);
|
public void write(CompoundTag nbt) {
|
||||||
if (blockEntity instanceof StationTileEntity station) {
|
super.write(nbt);
|
||||||
station.migrate(this);
|
nbt.putString("Name", name);
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLocation(Couple<TrackNodeLocation> nodes, double position) {
|
public boolean canApproachFrom(TrackNode side) {
|
||||||
this.edgeLocation = nodes;
|
return isPrimary(side);
|
||||||
this.position = position;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reserveFor(Train train) {
|
public void reserveFor(Train train) {
|
||||||
|
@ -97,14 +80,4 @@ public class GlobalStation extends TrackEdgePoint {
|
||||||
return this.nearestTrain.get();
|
return this.nearestTrain.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompoundTag write() {
|
|
||||||
CompoundTag nbt = new CompoundTag();
|
|
||||||
nbt.putUUID("Id", id);
|
|
||||||
nbt.putString("Name", name);
|
|
||||||
nbt.put("StationPos", NbtUtils.writeBlockPos(stationPos));
|
|
||||||
nbt.putDouble("Position", position);
|
|
||||||
nbt.put("Edge", edgeLocation.serializeEach(loc -> NbtUtils.writeBlockPos(new BlockPos(loc))));
|
|
||||||
return nbt;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
||||||
import com.simibubi.create.content.logistics.trains.management.schedule.FilteredDestination;
|
import com.simibubi.create.content.logistics.trains.management.schedule.FilteredDestination;
|
||||||
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
|
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
|
||||||
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleDestination;
|
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleDestination;
|
||||||
|
@ -128,7 +129,7 @@ public class ScheduleRuntime {
|
||||||
String regex = filtered.nameFilter.replace("*", ".*");
|
String regex = filtered.nameFilter.replace("*", ".*");
|
||||||
GlobalStation best = null;
|
GlobalStation best = null;
|
||||||
double bestCost = Double.MAX_VALUE;
|
double bestCost = Double.MAX_VALUE;
|
||||||
for (GlobalStation globalStation : train.graph.getStations()) {
|
for (GlobalStation globalStation : train.graph.getPoints(EdgePointType.STATION)) {
|
||||||
if (!globalStation.name.matches(regex))
|
if (!globalStation.name.matches(regex))
|
||||||
continue;
|
continue;
|
||||||
boolean matchesCurrent = train.currentStation != null && train.currentStation.equals(globalStation.id);
|
boolean matchesCurrent = train.currentStation != null && train.currentStation.equals(globalStation.id);
|
||||||
|
|
|
@ -75,10 +75,10 @@ public class StationBlock extends HorizontalDirectionalBlock implements ITE<Stat
|
||||||
protected void displayScreen(StationTileEntity te, Player player) {
|
protected void displayScreen(StationTileEntity te, Player player) {
|
||||||
if (!(player instanceof LocalPlayer))
|
if (!(player instanceof LocalPlayer))
|
||||||
return;
|
return;
|
||||||
GlobalStation station = te.getOrCreateGlobalStation();
|
GlobalStation station = te.getStation();
|
||||||
if (station == null)
|
|
||||||
return;
|
|
||||||
BlockState blockState = te.getBlockState();
|
BlockState blockState = te.getBlockState();
|
||||||
|
if (station == null || blockState == null)
|
||||||
|
return;
|
||||||
boolean assembling = blockState.getBlock() == this && blockState.getValue(ASSEMBLING);
|
boolean assembling = blockState.getBlock() == this && blockState.getValue(ASSEMBLING);
|
||||||
ScreenOpener.open(assembling ? new AssemblyScreen(te, station) : new StationScreen(te, station));
|
ScreenOpener.open(assembling ? new AssemblyScreen(te, station) : new StationScreen(te, station));
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class StationEditPacket extends TileEntityConfigurationPacket<StationTile
|
||||||
BlockState blockState = level.getBlockState(blockPos);
|
BlockState blockState = level.getBlockState(blockPos);
|
||||||
|
|
||||||
if (!name.isBlank()) {
|
if (!name.isBlank()) {
|
||||||
GlobalStation station = te.getOrCreateGlobalStation();
|
GlobalStation station = te.getStation();
|
||||||
if (station != null)
|
if (station != null)
|
||||||
station.name = name;
|
station.name = name;
|
||||||
Create.RAILWAYS.markTracksDirty();
|
Create.RAILWAYS.markTracksDirty();
|
||||||
|
@ -113,12 +113,11 @@ public class StationEditPacket extends TileEntityConfigurationPacket<StationTile
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean disassembleAndEnterMode(StationTileEntity te) {
|
private boolean disassembleAndEnterMode(StationTileEntity te) {
|
||||||
GlobalStation station = te.getOrCreateGlobalStation();
|
GlobalStation station = te.getStation();
|
||||||
if (station != null) {
|
if (station != null) {
|
||||||
Train train = station.getPresentTrain();
|
Train train = station.getPresentTrain();
|
||||||
if (train != null && !train.disassemble(te.getAssemblyDirection(), te.getTarget()
|
BlockPos trackPosition = te.edgePoint.getGlobalPosition();
|
||||||
.getGlobalPosition()
|
if (train != null && !train.disassemble(te.getAssemblyDirection(), trackPosition.above()))
|
||||||
.above()))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return te.tryEnterAssemblyMode();
|
return te.tryEnterAssemblyMode();
|
||||||
|
|
|
@ -29,7 +29,7 @@ public class StationRenderer extends SafeTileEntityRenderer<StationTileEntity> {
|
||||||
int light, int overlay) {
|
int light, int overlay) {
|
||||||
|
|
||||||
BlockPos pos = te.getBlockPos();
|
BlockPos pos = te.getBlockPos();
|
||||||
TrackTargetingBehaviour target = te.getTarget();
|
TrackTargetingBehaviour<GlobalStation> target = te.edgePoint;
|
||||||
BlockPos targetPosition = target.getGlobalPosition();
|
BlockPos targetPosition = target.getGlobalPosition();
|
||||||
Level level = te.getLevel();
|
Level level = te.getLevel();
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ public class StationRenderer extends SafeTileEntityRenderer<StationTileEntity> {
|
||||||
if (!(block instanceof ITrackBlock))
|
if (!(block instanceof ITrackBlock))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GlobalStation station = te.getOrCreateGlobalStation();
|
GlobalStation station = te.getStation();
|
||||||
|
|
||||||
if (!te.getBlockState()
|
if (!te.getBlockState()
|
||||||
.getValue(StationBlock.ASSEMBLING) || station == null || station.getPresentTrain() != null) {
|
.getValue(StationBlock.ASSEMBLING) || station == null || station.getPresentTrain() != null) {
|
||||||
|
|
|
@ -9,6 +9,8 @@ import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
|
||||||
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
||||||
|
@ -22,6 +24,7 @@ import com.simibubi.create.content.logistics.trains.entity.Carriage.CarriageBoge
|
||||||
import com.simibubi.create.content.logistics.trains.entity.CarriageContraption;
|
import com.simibubi.create.content.logistics.trains.entity.CarriageContraption;
|
||||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||||
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint;
|
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
||||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
@ -46,91 +49,42 @@ import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
public class StationTileEntity extends SmartTileEntity {
|
public class StationTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
UUID id;
|
public TrackTargetingBehaviour<GlobalStation> edgePoint;
|
||||||
|
|
||||||
protected int failedCarriageIndex;
|
protected int failedCarriageIndex;
|
||||||
protected AssemblyException lastException;
|
protected AssemblyException lastException;
|
||||||
protected CompoundTag toMigrate;
|
|
||||||
|
|
||||||
public StationTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
public StationTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||||
super(type, pos, state);
|
super(type, pos, state);
|
||||||
setLazyTickRate(20);
|
setLazyTickRate(20);
|
||||||
id = UUID.randomUUID();
|
|
||||||
lastException = null;
|
lastException = null;
|
||||||
toMigrate = null;
|
|
||||||
failedCarriageIndex = -1;
|
failedCarriageIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void migrate(GlobalStation globalStation) {
|
|
||||||
if (toMigrate != null)
|
|
||||||
return;
|
|
||||||
toMigrate = globalStation.write();
|
|
||||||
setChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
||||||
behaviours.add(new TrackTargetingBehaviour(this));
|
edgePoint = new TrackTargetingBehaviour<>(this, EdgePointType.STATION);
|
||||||
}
|
behaviours.add(edgePoint);
|
||||||
|
|
||||||
public TrackTargetingBehaviour getTarget() {
|
|
||||||
return getBehaviour(TrackTargetingBehaviour.TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initialize() {
|
|
||||||
if (!level.isClientSide)
|
|
||||||
getOrCreateGlobalStation();
|
|
||||||
super.initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public GlobalStation getOrCreateGlobalStation() {
|
|
||||||
for (TrackGraph trackGraph : Create.RAILWAYS.trackNetworks.values()) { // TODO thread breach
|
|
||||||
GlobalStation station = trackGraph.getStation(id);
|
|
||||||
if (station == null)
|
|
||||||
continue;
|
|
||||||
return station;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level.isClientSide)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
TrackTargetingBehaviour target = getTarget();
|
|
||||||
if (!target.hasValidTrack())
|
|
||||||
return null;
|
|
||||||
GraphLocation loc = target.determineGraphLocation();
|
|
||||||
if (loc == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
GlobalStation globalStation =
|
|
||||||
toMigrate != null ? new GlobalStation(toMigrate) : new GlobalStation(id, worldPosition);
|
|
||||||
globalStation.setLocation(loc.edge, loc.position);
|
|
||||||
loc.graph.addStation(globalStation);
|
|
||||||
toMigrate = null;
|
|
||||||
setChanged();
|
|
||||||
|
|
||||||
return globalStation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void read(CompoundTag tag, boolean clientPacket) {
|
protected void read(CompoundTag tag, boolean clientPacket) {
|
||||||
id = tag.getUUID("Id");
|
|
||||||
lastException = AssemblyException.read(tag);
|
lastException = AssemblyException.read(tag);
|
||||||
failedCarriageIndex = tag.getInt("FailedCarriageIndex");
|
failedCarriageIndex = tag.getInt("FailedCarriageIndex");
|
||||||
super.read(tag, clientPacket);
|
super.read(tag, clientPacket);
|
||||||
if (tag.contains("ToMigrate"))
|
|
||||||
toMigrate = tag.getCompound("ToMigrate");
|
|
||||||
invalidateRenderBoundingBox();
|
invalidateRenderBoundingBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void write(CompoundTag tag, boolean clientPacket) {
|
protected void write(CompoundTag tag, boolean clientPacket) {
|
||||||
tag.putUUID("Id", id);
|
|
||||||
AssemblyException.write(tag, lastException);
|
AssemblyException.write(tag, lastException);
|
||||||
tag.putInt("FailedCarriageIndex", failedCarriageIndex);
|
tag.putInt("FailedCarriageIndex", failedCarriageIndex);
|
||||||
super.write(tag, clientPacket);
|
super.write(tag, clientPacket);
|
||||||
if (!clientPacket && toMigrate != null)
|
}
|
||||||
tag.put("ToMigrate", toMigrate);
|
|
||||||
|
@Nullable
|
||||||
|
public GlobalStation getStation() {
|
||||||
|
return edgePoint.getEdgePoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Train Assembly
|
// Train Assembly
|
||||||
|
@ -147,8 +101,6 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
public void lazyTick() {
|
public void lazyTick() {
|
||||||
if (isAssembling() && !level.isClientSide)
|
if (isAssembling() && !level.isClientSide)
|
||||||
refreshAssemblyInfo();
|
refreshAssemblyInfo();
|
||||||
if (!level.isClientSide)
|
|
||||||
getOrCreateGlobalStation();
|
|
||||||
super.lazyTick();
|
super.lazyTick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,12 +109,6 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
if (isAssembling() && level.isClientSide)
|
if (isAssembling() && level.isClientSide)
|
||||||
refreshAssemblyInfo();
|
refreshAssemblyInfo();
|
||||||
super.tick();
|
super.tick();
|
||||||
|
|
||||||
if (level.isClientSide)
|
|
||||||
return;
|
|
||||||
if (toMigrate == null)
|
|
||||||
return;
|
|
||||||
getOrCreateGlobalStation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void trackClicked(Player player, ITrackBlock track, BlockState state, BlockPos pos) {
|
public void trackClicked(Player player, ITrackBlock track, BlockState state, BlockPos pos) {
|
||||||
|
@ -172,7 +118,7 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
if (bb == null || !bb.isInside(pos))
|
if (bb == null || !bb.isInside(pos))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int bogeyOffset = pos.distManhattan(getTarget().getGlobalPosition()) - 1;
|
int bogeyOffset = pos.distManhattan(edgePoint.getGlobalPosition()) - 1;
|
||||||
if (!isValidBogeyOffset(bogeyOffset))
|
if (!isValidBogeyOffset(bogeyOffset))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -187,13 +133,12 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean tryEnterAssemblyMode() {
|
public boolean tryEnterAssemblyMode() {
|
||||||
TrackTargetingBehaviour target = getTarget();
|
if (!edgePoint.hasValidTrack())
|
||||||
if (!target.hasValidTrack())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
BlockPos targetPosition = target.getGlobalPosition();
|
BlockPos targetPosition = edgePoint.getGlobalPosition();
|
||||||
BlockState trackState = target.getTrackBlockState();
|
BlockState trackState = edgePoint.getTrackBlockState();
|
||||||
ITrackBlock track = target.getTrack();
|
ITrackBlock track = edgePoint.getTrack();
|
||||||
Vec3 trackAxis = track.getTrackAxes(level, targetPosition, trackState)
|
Vec3 trackAxis = track.getTrackAxes(level, targetPosition, trackState)
|
||||||
.get(0);
|
.get(0);
|
||||||
|
|
||||||
|
@ -210,18 +155,17 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshAssemblyInfo() {
|
public void refreshAssemblyInfo() {
|
||||||
TrackTargetingBehaviour target = getTarget();
|
if (!edgePoint.hasValidTrack())
|
||||||
if (!target.hasValidTrack())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GlobalStation station = getOrCreateGlobalStation();
|
GlobalStation station = getStation();
|
||||||
if (station == null || station.getPresentTrain() != null)
|
if (station == null || station.getPresentTrain() != null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int prevLength = assemblyLength;
|
int prevLength = assemblyLength;
|
||||||
BlockPos targetPosition = target.getGlobalPosition();
|
BlockPos targetPosition = edgePoint.getGlobalPosition();
|
||||||
BlockState trackState = target.getTrackBlockState();
|
BlockState trackState = edgePoint.getTrackBlockState();
|
||||||
ITrackBlock track = target.getTrack();
|
ITrackBlock track = edgePoint.getTrack();
|
||||||
getAssemblyDirection();
|
getAssemblyDirection();
|
||||||
|
|
||||||
MutableBlockPos currentPos = targetPosition.mutable();
|
MutableBlockPos currentPos = targetPosition.mutable();
|
||||||
|
@ -285,13 +229,12 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
public Direction getAssemblyDirection() {
|
public Direction getAssemblyDirection() {
|
||||||
if (assemblyDirection != null)
|
if (assemblyDirection != null)
|
||||||
return assemblyDirection;
|
return assemblyDirection;
|
||||||
TrackTargetingBehaviour target = getTarget();
|
if (!edgePoint.hasValidTrack())
|
||||||
if (!target.hasValidTrack())
|
|
||||||
return null;
|
return null;
|
||||||
BlockPos targetPosition = target.getGlobalPosition();
|
BlockPos targetPosition = edgePoint.getGlobalPosition();
|
||||||
BlockState trackState = target.getTrackBlockState();
|
BlockState trackState = edgePoint.getTrackBlockState();
|
||||||
ITrackBlock track = target.getTrack();
|
ITrackBlock track = edgePoint.getTrack();
|
||||||
AxisDirection axisDirection = target.getTargetDirection();
|
AxisDirection axisDirection = edgePoint.getTargetDirection();
|
||||||
Vec3 axis = track.getTrackAxes(level, targetPosition, trackState)
|
Vec3 axis = track.getTrackAxes(level, targetPosition, trackState)
|
||||||
.get(0)
|
.get(0)
|
||||||
.normalize()
|
.normalize()
|
||||||
|
@ -303,8 +246,7 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
protected void setRemovedNotDueToChunkUnload() {
|
protected void setRemovedNotDueToChunkUnload() {
|
||||||
assemblyAreas.get(level)
|
assemblyAreas.get(level)
|
||||||
.remove(worldPosition);
|
.remove(worldPosition);
|
||||||
for (TrackGraph trackGraph : Create.RAILWAYS.trackNetworks.values())
|
|
||||||
trackGraph.removeStation(id);
|
|
||||||
super.setRemovedNotDueToChunkUnload();
|
super.setRemovedNotDueToChunkUnload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,13 +258,12 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackTargetingBehaviour target = getTarget();
|
if (!edgePoint.hasValidTrack())
|
||||||
if (!target.hasValidTrack())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BlockPos trackPosition = target.getGlobalPosition();
|
BlockPos trackPosition = edgePoint.getGlobalPosition();
|
||||||
BlockState trackState = target.getTrackBlockState();
|
BlockState trackState = edgePoint.getTrackBlockState();
|
||||||
ITrackBlock track = target.getTrack();
|
ITrackBlock track = edgePoint.getTrack();
|
||||||
BlockPos bogeyOffset = new BlockPos(track.getUpNormal(level, trackPosition, trackState));
|
BlockPos bogeyOffset = new BlockPos(track.getUpNormal(level, trackPosition, trackState));
|
||||||
|
|
||||||
DiscoveredLocation location = null;
|
DiscoveredLocation location = null;
|
||||||
|
@ -487,11 +428,13 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
Train train = new Train(UUID.randomUUID(), playerUUID, graph, carriages, spacing);
|
Train train = new Train(UUID.randomUUID(), playerUUID, graph, carriages, spacing);
|
||||||
GlobalStation station = getOrCreateGlobalStation();
|
GlobalStation station = getStation();
|
||||||
|
if (station != null) {
|
||||||
train.setCurrentStation(station);
|
train.setCurrentStation(station);
|
||||||
station.reserveFor(train);
|
station.reserveFor(train);
|
||||||
train.collectInitiallyOccupiedSignalBlocks();
|
}
|
||||||
|
|
||||||
|
train.collectInitiallyOccupiedSignalBlocks();
|
||||||
Create.RAILWAYS.trains.put(train.id, train);
|
Create.RAILWAYS.trains.put(train.id, train);
|
||||||
clearException();
|
clearException();
|
||||||
}
|
}
|
||||||
|
@ -523,7 +466,7 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AABB createRenderBoundingBox() {
|
protected AABB createRenderBoundingBox() {
|
||||||
return new AABB(worldPosition, getTarget().getGlobalPosition()).inflate(2);
|
return new AABB(worldPosition, edgePoint.getGlobalPosition()).inflate(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,20 @@
|
||||||
package com.simibubi.create.content.logistics.trains.management;
|
package com.simibubi.create.content.logistics.trains.management;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.logistics.trains.ITrackBlock;
|
import com.simibubi.create.content.logistics.trains.ITrackBlock;
|
||||||
|
import com.simibubi.create.content.logistics.trains.TrackEdge;
|
||||||
|
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackGraphHelper;
|
import com.simibubi.create.content.logistics.trains.TrackGraphHelper;
|
||||||
|
import com.simibubi.create.content.logistics.trains.TrackNode;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.signal.SingleTileEdgePoint;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.signal.TrackEdgePoint;
|
||||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||||
|
@ -23,33 +35,143 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
public class TrackTargetingBehaviour extends TileEntityBehaviour {
|
public class TrackTargetingBehaviour<T extends TrackEdgePoint> extends TileEntityBehaviour {
|
||||||
|
|
||||||
public static final BehaviourType<TrackTargetingBehaviour> TYPE = new BehaviourType<>();
|
public static final BehaviourType<TrackTargetingBehaviour<?>> TYPE = new BehaviourType<>();
|
||||||
|
|
||||||
private BlockPos targetTrack;
|
private BlockPos targetTrack;
|
||||||
private AxisDirection targetDirection;
|
private AxisDirection targetDirection;
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
public TrackTargetingBehaviour(SmartTileEntity te) {
|
private CompoundTag migrationData;
|
||||||
|
private EdgePointType<T> edgePointType;
|
||||||
|
private T edgePoint;
|
||||||
|
|
||||||
|
public TrackTargetingBehaviour(SmartTileEntity te, EdgePointType<T> edgePointType) {
|
||||||
super(te);
|
super(te);
|
||||||
|
this.edgePointType = edgePointType;
|
||||||
targetDirection = AxisDirection.POSITIVE;
|
targetDirection = AxisDirection.POSITIVE;
|
||||||
targetTrack = BlockPos.ZERO;
|
targetTrack = BlockPos.ZERO;
|
||||||
|
id = UUID.randomUUID();
|
||||||
|
migrationData = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(CompoundTag nbt, boolean clientPacket) {
|
public void write(CompoundTag nbt, boolean clientPacket) {
|
||||||
|
nbt.putUUID("Id", id);
|
||||||
nbt.put("TargetTrack", NbtUtils.writeBlockPos(targetTrack));
|
nbt.put("TargetTrack", NbtUtils.writeBlockPos(targetTrack));
|
||||||
nbt.putBoolean("TargetDirection", targetDirection == AxisDirection.POSITIVE);
|
nbt.putBoolean("TargetDirection", targetDirection == AxisDirection.POSITIVE);
|
||||||
|
if (migrationData != null && !clientPacket)
|
||||||
|
nbt.put("Migrate", migrationData);
|
||||||
super.write(nbt, clientPacket);
|
super.write(nbt, clientPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(CompoundTag nbt, boolean clientPacket) {
|
public void read(CompoundTag nbt, boolean clientPacket) {
|
||||||
|
UUID prevId = id;
|
||||||
|
id = nbt.getUUID("Id");
|
||||||
targetTrack = NbtUtils.readBlockPos(nbt.getCompound("TargetTrack"));
|
targetTrack = NbtUtils.readBlockPos(nbt.getCompound("TargetTrack"));
|
||||||
targetDirection = nbt.getBoolean("TargetDirection") ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE;
|
targetDirection = nbt.getBoolean("TargetDirection") ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE;
|
||||||
|
if (nbt.contains("Migrate"))
|
||||||
|
migrationData = nbt.getCompound("Migrate");
|
||||||
|
if (clientPacket && !prevId.equals(id))
|
||||||
|
edgePoint = null;
|
||||||
super.read(nbt, clientPacket);
|
super.read(nbt, clientPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public T getEdgePoint() {
|
||||||
|
return edgePoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void invalidateEdgePoint(CompoundTag migrationData) {
|
||||||
|
this.migrationData = migrationData;
|
||||||
|
id = UUID.randomUUID();
|
||||||
|
edgePoint = null;
|
||||||
|
tileEntity.sendData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
if (edgePoint == null)
|
||||||
|
edgePoint = createEdgePoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T createEdgePoint() {
|
||||||
|
for (TrackGraph trackGraph : Create.RAILWAYS.trackNetworks.values()) { // TODO thread breach
|
||||||
|
T point = trackGraph.getPoint(edgePointType, id);
|
||||||
|
if (point == null)
|
||||||
|
continue;
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getWorld().isClientSide)
|
||||||
|
return null;
|
||||||
|
if (!hasValidTrack())
|
||||||
|
return null;
|
||||||
|
GraphLocation loc = determineGraphLocation();
|
||||||
|
if (loc == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
TrackGraph graph = loc.graph;
|
||||||
|
TrackNode node1 = graph.locateNode(loc.edge.getFirst());
|
||||||
|
TrackNode node2 = graph.locateNode(loc.edge.getSecond());
|
||||||
|
TrackEdge edge = graph.getConnectionsFrom(node1)
|
||||||
|
.get(node2);
|
||||||
|
|
||||||
|
boolean front = getTargetDirection() == AxisDirection.POSITIVE;
|
||||||
|
|
||||||
|
if (edge == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
EdgeData signalData = edge.getEdgeData();
|
||||||
|
if (signalData.hasPoints()) {
|
||||||
|
for (EdgePointType<?> otherType : EdgePointType.TYPES.values()) {
|
||||||
|
TrackEdgePoint otherPoint = signalData.get(otherType, node1, node2, edge, loc.position);
|
||||||
|
if (otherPoint == null)
|
||||||
|
continue;
|
||||||
|
if (otherType != edgePointType) {
|
||||||
|
if (!otherPoint.canCoexistWith(edgePointType, front))
|
||||||
|
return null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!otherPoint.canMerge())
|
||||||
|
return null;
|
||||||
|
otherPoint.tileAdded(getPos(), front);
|
||||||
|
id = otherPoint.getId();
|
||||||
|
tileEntity.setChanged();
|
||||||
|
return (T) otherPoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T point = edgePointType.create();
|
||||||
|
point.setId(id);
|
||||||
|
|
||||||
|
if (point instanceof SingleTileEdgePoint step) {
|
||||||
|
point.setLocation(loc.edge, loc.position);
|
||||||
|
if (migrationData != null) {
|
||||||
|
step.read(migrationData, true);
|
||||||
|
migrationData = null;
|
||||||
|
tileEntity.setChanged();
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
point.setLocation(front ? loc.edge : loc.edge.swap(),
|
||||||
|
front ? loc.position : edge.getLength(node1, node2) - loc.position);
|
||||||
|
|
||||||
|
point.tileAdded(getPos(), front);
|
||||||
|
loc.graph.addPoint(edgePointType, point);
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
if (edgePoint != null && !getWorld().isClientSide)
|
||||||
|
edgePoint.tileRemoved(getPos(), getTargetDirection() == AxisDirection.POSITIVE);
|
||||||
|
super.remove();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BehaviourType<?> getType() {
|
public BehaviourType<?> getType() {
|
||||||
return TYPE;
|
return TYPE;
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.management.edgePoint;
|
||||||
|
|
||||||
|
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.management.signal.TrackEdgePoint;
|
||||||
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
|
||||||
|
public class EdgePointManager {
|
||||||
|
|
||||||
|
public static <T extends TrackEdgePoint> void onEdgePointAdded(TrackGraph graph, T point, EdgePointType<T> type) {
|
||||||
|
Couple<TrackNodeLocation> edgeLocation = point.edgeLocation;
|
||||||
|
Couple<TrackNode> startNodes = edgeLocation.map(graph::locateNode);
|
||||||
|
Couple<TrackEdge> startEdges = startNodes.mapWithParams((l1, l2) -> graph.getConnectionsFrom(l1)
|
||||||
|
.get(l2), startNodes.swap());
|
||||||
|
|
||||||
|
for (boolean front : Iterate.trueAndFalse) {
|
||||||
|
TrackNode node1 = startNodes.get(front);
|
||||||
|
TrackNode node2 = startNodes.get(!front);
|
||||||
|
TrackEdge startEdge = startEdges.get(front);
|
||||||
|
startEdge.getEdgeData()
|
||||||
|
.addPoint(node1, node2, startEdge, point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends TrackEdgePoint> void onEdgePointRemoved(TrackGraph graph, T point, EdgePointType<T> type) {
|
||||||
|
point.onRemoved(graph);
|
||||||
|
Couple<TrackNodeLocation> edgeLocation = point.edgeLocation;
|
||||||
|
Couple<TrackNode> startNodes = edgeLocation.map(graph::locateNode);
|
||||||
|
startNodes.forEachWithParams((l1, l2) -> {
|
||||||
|
TrackEdge trackEdge = graph.getConnectionsFrom(l1)
|
||||||
|
.get(l2);
|
||||||
|
trackEdge.getEdgeData()
|
||||||
|
.removePoint(l1, l2, trackEdge, point);
|
||||||
|
}, startNodes.swap());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.management.edgePoint;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.signal.TrackEdgePoint;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
|
||||||
|
public class EdgePointStorage {
|
||||||
|
|
||||||
|
private Map<EdgePointType<?>, Map<UUID, TrackEdgePoint>> pointsByType;
|
||||||
|
|
||||||
|
public EdgePointStorage() {
|
||||||
|
pointsByType = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends TrackEdgePoint> void put(EdgePointType<T> type, TrackEdgePoint point) {
|
||||||
|
getMap(type).put(point.getId(), point);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends TrackEdgePoint> T get(EdgePointType<T> type, UUID id) {
|
||||||
|
return (T) getMap(type).get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends TrackEdgePoint> T remove(EdgePointType<T> type, UUID id) {
|
||||||
|
return (T) getMap(type).remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends TrackEdgePoint> Collection<T> values(EdgePointType<T> type) {
|
||||||
|
return getMap(type).values()
|
||||||
|
.stream()
|
||||||
|
.map(e -> (T) e)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<UUID, TrackEdgePoint> getMap(EdgePointType<? extends TrackEdgePoint> type) {
|
||||||
|
return pointsByType.computeIfAbsent(type, t -> new HashMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick(TrackGraph graph) {
|
||||||
|
pointsByType.values()
|
||||||
|
.forEach(map -> map.values()
|
||||||
|
.forEach(p -> p.tick(graph)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void transferAll(EdgePointStorage other) {
|
||||||
|
pointsByType.forEach((type, map) -> other.getMap(type)
|
||||||
|
.putAll(map));
|
||||||
|
pointsByType.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundTag write() {
|
||||||
|
CompoundTag nbt = new CompoundTag();
|
||||||
|
for (Entry<EdgePointType<?>, Map<UUID, TrackEdgePoint>> entry : pointsByType.entrySet()) {
|
||||||
|
EdgePointType<?> type = entry.getKey();
|
||||||
|
ListTag list = NBTHelper.writeCompoundList(entry.getValue()
|
||||||
|
.values(), edgePoint -> {
|
||||||
|
CompoundTag tag = new CompoundTag();
|
||||||
|
edgePoint.write(tag);
|
||||||
|
return tag;
|
||||||
|
});
|
||||||
|
nbt.put(type.getId()
|
||||||
|
.toString(), list);
|
||||||
|
}
|
||||||
|
return nbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void read(CompoundTag nbt) {
|
||||||
|
for (EdgePointType<?> type : EdgePointType.TYPES.values()) {
|
||||||
|
ListTag list = nbt.getList(type.getId()
|
||||||
|
.toString(), Tag.TAG_COMPOUND);
|
||||||
|
Map<UUID, TrackEdgePoint> map = getMap(type);
|
||||||
|
NBTHelper.iterateCompoundList(list, tag -> {
|
||||||
|
TrackEdgePoint edgePoint = type.create();
|
||||||
|
edgePoint.read(tag);
|
||||||
|
map.put(edgePoint.getId(), edgePoint);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.management.edgePoint;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.signal.TrackEdgePoint;
|
||||||
|
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
public class EdgePointType<T extends TrackEdgePoint> {
|
||||||
|
|
||||||
|
public static final Map<ResourceLocation, EdgePointType<?>> TYPES = new HashMap<>();
|
||||||
|
private ResourceLocation id;
|
||||||
|
private Supplier<T> factory;
|
||||||
|
|
||||||
|
public static final EdgePointType<SignalBoundary> SIGNAL =
|
||||||
|
register(Create.asResource("signal"), SignalBoundary::new);
|
||||||
|
public static final EdgePointType<GlobalStation> STATION =
|
||||||
|
register(Create.asResource("station"), GlobalStation::new);
|
||||||
|
|
||||||
|
public static <T extends TrackEdgePoint> EdgePointType<T> register(ResourceLocation id, Supplier<T> factory) {
|
||||||
|
EdgePointType<T> type = new EdgePointType<>(id, factory);
|
||||||
|
TYPES.put(id, type);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EdgePointType(ResourceLocation id, Supplier<T> factory) {
|
||||||
|
this.id = id;
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T create() {
|
||||||
|
T t = factory.get();
|
||||||
|
t.setType(this);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceLocation getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ public class ScheduledDelay extends TimedWaitCondition {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean tickCompletion(Level level, Train train, CompoundTag context) {
|
public boolean tickCompletion(Level level, Train train, CompoundTag context) {
|
||||||
int time = context.getInt("Time") + 1900;
|
int time = context.getInt("Time");
|
||||||
if (time >= value * timeUnit.ticksPer)
|
if (time >= value * timeUnit.ticksPer)
|
||||||
return true;
|
return true;
|
||||||
context.putInt("Time", time + 1);
|
context.putInt("Time", time + 1);
|
||||||
|
|
|
@ -24,7 +24,7 @@ public class StationPoweredCondition extends ScheduleWaitCondition {
|
||||||
GlobalStation currentStation = train.getCurrentStation();
|
GlobalStation currentStation = train.getCurrentStation();
|
||||||
if (currentStation == null)
|
if (currentStation == null)
|
||||||
return false;
|
return false;
|
||||||
BlockPos stationPos = currentStation.stationPos;
|
BlockPos stationPos = currentStation.getTilePos();
|
||||||
if (!level.isLoaded(stationPos))
|
if (!level.isLoaded(stationPos))
|
||||||
return false;
|
return false;
|
||||||
return level.hasNeighborSignal(stationPos);
|
return level.hasNeighborSignal(stationPos);
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class StationUnloadedCondition extends ScheduleWaitCondition {
|
||||||
if (currentStation == null)
|
if (currentStation == null)
|
||||||
return false;
|
return false;
|
||||||
if (level instanceof ServerLevel serverLevel)
|
if (level instanceof ServerLevel serverLevel)
|
||||||
return !serverLevel.isPositionEntityTicking(currentStation.stationPos);
|
return !serverLevel.isPositionEntityTicking(currentStation.getTilePos());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,109 +1,77 @@
|
||||||
package com.simibubi.create.content.logistics.trains.management.signal;
|
package com.simibubi.create.content.logistics.trains.management.signal;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.content.logistics.trains.TrackEdge;
|
import com.simibubi.create.content.logistics.trains.TrackEdge;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackNode;
|
import com.simibubi.create.content.logistics.trains.TrackNode;
|
||||||
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
||||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
|
|
||||||
public class EdgeData {
|
public class EdgeData {
|
||||||
|
|
||||||
|
public static final UUID passiveGroup = UUID.fromString("00000000-0000-0000-0000-000000000000");
|
||||||
|
|
||||||
public UUID singleSignalGroup;
|
public UUID singleSignalGroup;
|
||||||
private List<SignalBoundary> boundaries;
|
private List<TrackEdgePoint> points;
|
||||||
private List<GlobalStation> stations;
|
|
||||||
|
|
||||||
public EdgeData() {
|
public EdgeData() {
|
||||||
boundaries = new ArrayList<>();
|
points = new ArrayList<>();
|
||||||
stations = new ArrayList<>();
|
singleSignalGroup = passiveGroup;
|
||||||
singleSignalGroup = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasBoundaries() {
|
public boolean hasSignalBoundaries() {
|
||||||
return !boundaries.isEmpty();
|
return singleSignalGroup == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasStations() {
|
public boolean hasPoints() {
|
||||||
return !stations.isEmpty();
|
return !points.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SignalBoundary> getBoundaries() {
|
public List<TrackEdgePoint> getPoints() {
|
||||||
return boundaries;
|
return points;
|
||||||
}
|
|
||||||
|
|
||||||
public List<GlobalStation> getStations() {
|
|
||||||
return stations;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removePoint(TrackNode node1, TrackNode node2, TrackEdge edge, TrackEdgePoint point) {
|
public void removePoint(TrackNode node1, TrackNode node2, TrackEdge edge, TrackEdgePoint point) {
|
||||||
if (point instanceof GlobalStation gs)
|
points.remove(point);
|
||||||
stations.remove(gs);
|
if (point.getType() == EdgePointType.SIGNAL)
|
||||||
if (point instanceof SignalBoundary sb)
|
singleSignalGroup = next(point.getType(), node1, node2, edge, 0) == null ? passiveGroup : null;
|
||||||
boundaries.remove(sb);
|
|
||||||
updateDelegates(node1, node2, edge);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends TrackEdgePoint> void addPoint(TrackNode node1, TrackNode node2, TrackEdge edge, T boundary,
|
public <T extends TrackEdgePoint> void addPoint(TrackNode node1, TrackNode node2, TrackEdge edge,
|
||||||
Class<T> type) {
|
TrackEdgePoint point) {
|
||||||
T next = next(type, node1, node2, edge, boundary.getLocationOn(node1, node2, edge));
|
if (point.getType() == EdgePointType.SIGNAL)
|
||||||
if (boundary instanceof GlobalStation gs)
|
singleSignalGroup = null;
|
||||||
stations.add(next == null ? stations.size() : stations.indexOf(next), gs);
|
double locationOn = point.getLocationOn(node1, node2, edge);
|
||||||
if (boundary instanceof SignalBoundary sb)
|
int i = 0;
|
||||||
boundaries.add(next == null ? boundaries.size() : boundaries.indexOf(next), sb);
|
for (; i < points.size(); i++)
|
||||||
updateDelegates(node1, node2, edge);
|
if (points.get(i)
|
||||||
}
|
.getLocationOn(node1, node2, edge) > locationOn)
|
||||||
|
break;
|
||||||
public void updateDelegates(TrackNode node1, TrackNode node2, TrackEdge edge) {
|
points.add(i, point);
|
||||||
for (GlobalStation globalStation : stations)
|
|
||||||
globalStation.boundary = getBoundary(node1, node2, edge, globalStation.getLocationOn(node1, node2, edge));
|
|
||||||
for (SignalBoundary boundary : boundaries)
|
|
||||||
boundary.station = getStation(node1, node2, edge, boundary.getLocationOn(node1, node2, edge));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public SignalBoundary nextBoundary(TrackNode node1, TrackNode node2, TrackEdge edge, double minPosition) {
|
|
||||||
return next(SignalBoundary.class, node1, node2, edge, minPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public GlobalStation nextStation(TrackNode node1, TrackNode node2, TrackEdge edge, double minPosition) {
|
|
||||||
return next(GlobalStation.class, node1, node2, edge, minPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public SignalBoundary getBoundary(TrackNode node1, TrackNode node2, TrackEdge edge, double exactPosition) {
|
|
||||||
return get(SignalBoundary.class, node1, node2, edge, exactPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public GlobalStation getStation(TrackNode node1, TrackNode node2, TrackEdge edge, double exactPosition) {
|
|
||||||
return get(GlobalStation.class, node1, node2, edge, exactPosition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private <T extends TrackEdgePoint> T next(Class<T> type, TrackNode node1, TrackNode node2, TrackEdge edge,
|
public <T extends TrackEdgePoint> T next(EdgePointType<T> type, TrackNode node1, TrackNode node2, TrackEdge edge,
|
||||||
double minPosition) {
|
double minPosition) {
|
||||||
for (TrackEdgePoint point : type == GlobalStation.class ? stations : boundaries)
|
for (TrackEdgePoint point : points)
|
||||||
if (point.getLocationOn(node1, node2, edge) > minPosition)
|
if (point.getType() == type && point.getLocationOn(node1, node2, edge) > minPosition)
|
||||||
return (T) point;
|
return (T) point;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private <T extends TrackEdgePoint> T get(Class<T> type, TrackNode node1, TrackNode node2, TrackEdge edge,
|
public <T extends TrackEdgePoint> T get(EdgePointType<T> type, TrackNode node1, TrackNode node2, TrackEdge edge,
|
||||||
double exactPosition) {
|
double exactPosition) {
|
||||||
T next = next(type, node1, node2, edge, exactPosition - .5f);
|
T next = next(type, node1, node2, edge, exactPosition - .5f);
|
||||||
if (next != null && Mth.equal(next.getLocationOn(node1, node2, edge), exactPosition))
|
if (next != null && Mth.equal(next.getLocationOn(node1, node2, edge), exactPosition))
|
||||||
|
@ -112,43 +80,42 @@ public class EdgeData {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompoundTag write() {
|
public CompoundTag write() {
|
||||||
CompoundTag signalCompound = new CompoundTag();
|
CompoundTag nbt = new CompoundTag();
|
||||||
if (hasBoundaries()) {
|
if (singleSignalGroup == passiveGroup)
|
||||||
signalCompound.put("Boundaries", NBTHelper.writeCompoundList(boundaries, this::writePoint));
|
NBTHelper.putMarker(nbt, "PassiveGroup");
|
||||||
} else if (singleSignalGroup != null)
|
else if (singleSignalGroup != null)
|
||||||
signalCompound.putUUID("Group", singleSignalGroup);
|
nbt.putUUID("SignalGroup", singleSignalGroup);
|
||||||
if (hasStations())
|
|
||||||
signalCompound.put("Stations", NBTHelper.writeCompoundList(stations, this::writePoint));
|
if (hasPoints())
|
||||||
return signalCompound;
|
nbt.put("Points", NBTHelper.writeCompoundList(points, point -> {
|
||||||
|
CompoundTag tag = new CompoundTag();
|
||||||
|
tag.putUUID("Id", point.id);
|
||||||
|
tag.putString("Type", point.getType()
|
||||||
|
.getId()
|
||||||
|
.toString());
|
||||||
|
return tag;
|
||||||
|
}));
|
||||||
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EdgeData read(CompoundTag tag, TrackGraph graph) {
|
public static EdgeData read(CompoundTag nbt, TrackGraph graph) {
|
||||||
EdgeData signalEdgeData = new EdgeData();
|
EdgeData data = new EdgeData();
|
||||||
if (tag.contains("Group"))
|
if (nbt.contains("SignalGroup"))
|
||||||
signalEdgeData.singleSignalGroup = tag.getUUID("Group");
|
data.singleSignalGroup = nbt.getUUID("Group");
|
||||||
if (tag.contains("Boundaries"))
|
else if (!nbt.contains("PassiveGroup"))
|
||||||
NBTHelper.iterateCompoundList(tag.getList("Boundaries", Tag.TAG_COMPOUND),
|
data.singleSignalGroup = null;
|
||||||
readPoint(graph::getSignal, signalEdgeData.boundaries));
|
|
||||||
if (tag.contains("Stations"))
|
|
||||||
NBTHelper.iterateCompoundList(tag.getList("Stations", Tag.TAG_COMPOUND),
|
|
||||||
readPoint(graph::getStation, signalEdgeData.stations));
|
|
||||||
return signalEdgeData;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T extends TrackEdgePoint> CompoundTag writePoint(T point) {
|
if (nbt.contains("Points"))
|
||||||
CompoundTag compoundTag = new CompoundTag();
|
NBTHelper.iterateCompoundList(nbt.getList("Points", Tag.TAG_COMPOUND), tag -> {
|
||||||
compoundTag.putUUID("Id", point.id);
|
ResourceLocation location = new ResourceLocation(tag.getString("Type"));
|
||||||
return compoundTag;
|
EdgePointType<?> type = EdgePointType.TYPES.get(location);
|
||||||
}
|
if (type == null || !tag.contains("Id"))
|
||||||
|
return;
|
||||||
private static <T extends TrackEdgePoint> Consumer<CompoundTag> readPoint(Function<UUID, T> lookup,
|
TrackEdgePoint point = graph.getPoint(type, tag.getUUID("Id"));
|
||||||
Collection<T> target) {
|
if (point != null)
|
||||||
return tag -> {
|
data.points.add(point);
|
||||||
UUID id = tag.getUUID("Id");
|
});
|
||||||
T signal = lookup.apply(id);
|
return data;
|
||||||
if (signal != null)
|
|
||||||
target.add(signal);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,10 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackNode;
|
import com.simibubi.create.content.logistics.trains.TrackNode;
|
||||||
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
|
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.SignalTileEntity.OverlayState;
|
import com.simibubi.create.content.logistics.trains.management.signal.SignalTileEntity.OverlayState;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.SignalTileEntity.SignalState;
|
import com.simibubi.create.content.logistics.trains.management.signal.SignalTileEntity.SignalState;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
@ -22,6 +19,7 @@ import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtUtils;
|
import net.minecraft.nbt.NbtUtils;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
|
||||||
public class SignalBoundary extends TrackEdgePoint {
|
public class SignalBoundary extends TrackEdgePoint {
|
||||||
|
|
||||||
|
@ -29,16 +27,10 @@ public class SignalBoundary extends TrackEdgePoint {
|
||||||
public Couple<UUID> groups;
|
public Couple<UUID> groups;
|
||||||
public Couple<Boolean> sidesToUpdate;
|
public Couple<Boolean> sidesToUpdate;
|
||||||
|
|
||||||
@Nullable
|
public SignalBoundary() {
|
||||||
public GlobalStation station;
|
|
||||||
|
|
||||||
public SignalBoundary(UUID id, BlockPos tilePosition, boolean front) {
|
|
||||||
super(id);
|
|
||||||
signals = Couple.create(HashSet::new);
|
signals = Couple.create(HashSet::new);
|
||||||
groups = Couple.create(null, null);
|
groups = Couple.create(null, null);
|
||||||
sidesToUpdate = Couple.create(true, true);
|
sidesToUpdate = Couple.create(true, true);
|
||||||
this.signals.get(front)
|
|
||||||
.add(tilePosition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGroup(TrackNode side, UUID groupId) {
|
public void setGroup(TrackNode side, UUID groupId) {
|
||||||
|
@ -47,6 +39,35 @@ public class SignalBoundary extends TrackEdgePoint {
|
||||||
sidesToUpdate.set(primary, false);
|
sidesToUpdate.set(primary, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canMerge() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidate(LevelAccessor level) {
|
||||||
|
signals.forEach(s -> s.forEach(pos -> invalidateAt(level, pos)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tileAdded(BlockPos tilePos, boolean front) {
|
||||||
|
signals.get(front)
|
||||||
|
.add(tilePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tileRemoved(BlockPos tilePos, boolean front) {
|
||||||
|
signals.forEach(s -> s.remove(tilePos));
|
||||||
|
if (signals.both(Set::isEmpty))
|
||||||
|
removeFromAllGraphs();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRemoved(TrackGraph graph) {
|
||||||
|
super.onRemoved(graph);
|
||||||
|
SignalPropagator.onSignalRemoved(graph, this);
|
||||||
|
}
|
||||||
|
|
||||||
public void queueUpdate(TrackNode side) {
|
public void queueUpdate(TrackNode side) {
|
||||||
sidesToUpdate.set(isPrimary(side), true);
|
sidesToUpdate.set(isPrimary(side), true);
|
||||||
}
|
}
|
||||||
|
@ -55,14 +76,13 @@ public class SignalBoundary extends TrackEdgePoint {
|
||||||
return groups.get(isPrimary(side));
|
return groups.get(isPrimary(side));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean canNavigateVia(TrackNode side) {
|
public boolean canNavigateVia(TrackNode side) {
|
||||||
return !signals.get(!isPrimary(side))
|
return !signals.get(isPrimary(side))
|
||||||
.isEmpty();
|
.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public OverlayState getOverlayFor(BlockPos tile) {
|
public OverlayState getOverlayFor(BlockPos tile) {
|
||||||
if (station != null)
|
|
||||||
return OverlayState.SKIP;
|
|
||||||
for (boolean first : Iterate.trueAndFalse) {
|
for (boolean first : Iterate.trueAndFalse) {
|
||||||
Set<BlockPos> set = signals.get(first);
|
Set<BlockPos> set = signals.get(first);
|
||||||
for (BlockPos blockPos : set) {
|
for (BlockPos blockPos : set) {
|
||||||
|
@ -92,7 +112,9 @@ public class SignalBoundary extends TrackEdgePoint {
|
||||||
return SignalState.INVALID;
|
return SignalState.INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void tick(TrackGraph graph) {
|
public void tick(TrackGraph graph) {
|
||||||
|
super.tick(graph);
|
||||||
for (boolean front : Iterate.trueAndFalse) {
|
for (boolean front : Iterate.trueAndFalse) {
|
||||||
if (!sidesToUpdate.get(front))
|
if (!sidesToUpdate.get(front))
|
||||||
continue;
|
continue;
|
||||||
|
@ -101,12 +123,13 @@ public class SignalBoundary extends TrackEdgePoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SignalBoundary(CompoundTag nbt) {
|
@Override
|
||||||
super(nbt);
|
public void read(CompoundTag nbt) {
|
||||||
|
super.read(nbt);
|
||||||
|
|
||||||
|
sidesToUpdate = Couple.create(true, true);
|
||||||
signals = Couple.create(HashSet::new);
|
signals = Couple.create(HashSet::new);
|
||||||
groups = Couple.create(null, null);
|
groups = Couple.create(null, null);
|
||||||
sidesToUpdate = Couple.create(true, true);
|
|
||||||
|
|
||||||
for (int i = 1; i <= 2; i++)
|
for (int i = 1; i <= 2; i++)
|
||||||
if (nbt.contains("Tiles" + i)) {
|
if (nbt.contains("Tiles" + i)) {
|
||||||
|
@ -121,12 +144,9 @@ public class SignalBoundary extends TrackEdgePoint {
|
||||||
sidesToUpdate.set(i == 1, nbt.contains("Update" + i));
|
sidesToUpdate.set(i == 1, nbt.contains("Update" + i));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompoundTag write() {
|
@Override
|
||||||
CompoundTag nbt = new CompoundTag();
|
public void write(CompoundTag nbt) {
|
||||||
nbt.putUUID("Id", id);
|
super.write(nbt);
|
||||||
nbt.putDouble("Position", position);
|
|
||||||
nbt.put("Edge", edgeLocation.serializeEach(loc -> NbtUtils.writeBlockPos(new BlockPos(loc))));
|
|
||||||
|
|
||||||
for (int i = 1; i <= 2; i++)
|
for (int i = 1; i <= 2; i++)
|
||||||
if (!signals.get(i == 1)
|
if (!signals.get(i == 1)
|
||||||
.isEmpty())
|
.isEmpty())
|
||||||
|
@ -137,7 +157,6 @@ public class SignalBoundary extends TrackEdgePoint {
|
||||||
for (int i = 1; i <= 2; i++)
|
for (int i = 1; i <= 2; i++)
|
||||||
if (sidesToUpdate.get(i == 1))
|
if (sidesToUpdate.get(i == 1))
|
||||||
nbt.putBoolean("Update" + i, true);
|
nbt.putBoolean("Update" + i, true);
|
||||||
return nbt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,38 +16,13 @@ import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackNode;
|
import com.simibubi.create.content.logistics.trains.TrackNode;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
|
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
|
||||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
import com.simibubi.create.foundation.utility.Pair;
|
import com.simibubi.create.foundation.utility.Pair;
|
||||||
|
|
||||||
public class SignalPropagator {
|
public class SignalPropagator {
|
||||||
|
|
||||||
public static <T extends TrackEdgePoint> void onEdgePointAdded(TrackGraph graph, T point, Class<T> type) {
|
|
||||||
Couple<TrackNodeLocation> edgeLocation = point.edgeLocation;
|
|
||||||
Couple<TrackNode> startNodes = edgeLocation.map(graph::locateNode);
|
|
||||||
Couple<TrackEdge> startEdges = startNodes.mapWithParams((l1, l2) -> graph.getConnectionsFrom(l1)
|
|
||||||
.get(l2), startNodes.swap());
|
|
||||||
|
|
||||||
for (boolean front : Iterate.trueAndFalse) {
|
|
||||||
TrackNode node1 = startNodes.get(front);
|
|
||||||
TrackNode node2 = startNodes.get(!front);
|
|
||||||
TrackEdge startEdge = startEdges.get(front);
|
|
||||||
startEdge.getEdgeData()
|
|
||||||
.addPoint(node1, node2, startEdge, point, type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends TrackEdgePoint> void onEdgePointRemoved(TrackGraph graph, T point, Class<T> type) {
|
|
||||||
Couple<TrackNodeLocation> edgeLocation = point.edgeLocation;
|
|
||||||
Couple<TrackNode> startNodes = edgeLocation.map(graph::locateNode);
|
|
||||||
startNodes.forEachWithParams((l1, l2) -> {
|
|
||||||
TrackEdge trackEdge = graph.getConnectionsFrom(l1)
|
|
||||||
.get(l2);
|
|
||||||
trackEdge.getEdgeData()
|
|
||||||
.removePoint(l1, l2, trackEdge, point);
|
|
||||||
}, startNodes.swap());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onSignalRemoved(TrackGraph graph, SignalBoundary signal) {
|
public static void onSignalRemoved(TrackGraph graph, SignalBoundary signal) {
|
||||||
signal.sidesToUpdate.map($ -> false);
|
signal.sidesToUpdate.map($ -> false);
|
||||||
for (boolean front : Iterate.trueAndFalse) {
|
for (boolean front : Iterate.trueAndFalse) {
|
||||||
|
@ -61,8 +36,6 @@ public class SignalPropagator {
|
||||||
return false;
|
return false;
|
||||||
}, Predicates.alwaysFalse());
|
}, Predicates.alwaysFalse());
|
||||||
}
|
}
|
||||||
|
|
||||||
onEdgePointRemoved(graph, signal, SignalBoundary.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void notifySignalsOfNewNode(TrackGraph graph, TrackNode node) {
|
public static void notifySignalsOfNewNode(TrackGraph graph, TrackNode node) {
|
||||||
|
@ -118,7 +91,7 @@ public class SignalPropagator {
|
||||||
|
|
||||||
// Check for signal on the same edge
|
// Check for signal on the same edge
|
||||||
SignalBoundary immediateBoundary = startEdge.getEdgeData()
|
SignalBoundary immediateBoundary = startEdge.getEdgeData()
|
||||||
.nextBoundary(node1, node2, startEdge, signal.getLocationOn(node1, node2, startEdge));
|
.next(EdgePointType.SIGNAL, node1, node2, startEdge, signal.getLocationOn(node1, node2, startEdge));
|
||||||
if (immediateBoundary != null) {
|
if (immediateBoundary != null) {
|
||||||
if (boundaryCallback.test(Pair.of(node1, immediateBoundary)))
|
if (boundaryCallback.test(Pair.of(node1, immediateBoundary)))
|
||||||
notifyTrains(graph, startEdge, startEdges.get(!front));
|
notifyTrains(graph, startEdge, startEdges.get(!front));
|
||||||
|
@ -160,14 +133,15 @@ public class SignalPropagator {
|
||||||
EdgeData signalData = currentEdge.getEdgeData();
|
EdgeData signalData = currentEdge.getEdgeData();
|
||||||
|
|
||||||
// no boundary- update group of edge
|
// no boundary- update group of edge
|
||||||
if (!signalData.hasBoundaries()) {
|
if (!signalData.hasSignalBoundaries()) {
|
||||||
if (nonBoundaryCallback.test(signalData))
|
if (nonBoundaryCallback.test(signalData))
|
||||||
notifyTrains(graph, currentEdge);
|
notifyTrains(graph, currentEdge);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// other/own boundary found
|
// other/own boundary found
|
||||||
SignalBoundary nextBoundary = signalData.nextBoundary(currentNode, nextNode, currentEdge, 0);
|
SignalBoundary nextBoundary =
|
||||||
|
signalData.next(EdgePointType.SIGNAL, currentNode, nextNode, currentEdge, 0);
|
||||||
if (boundaryCallback.test(Pair.of(currentNode, nextBoundary)))
|
if (boundaryCallback.test(Pair.of(currentNode, nextBoundary)))
|
||||||
notifyTrains(graph, edge, oppositeEdge);
|
notifyTrains(graph, edge, oppositeEdge);
|
||||||
continue EdgeWalk;
|
continue EdgeWalk;
|
||||||
|
|
|
@ -39,7 +39,7 @@ public class SignalRenderer extends SafeTileEntityRenderer<SignalTileEntity> {
|
||||||
.renderInto(ms, buffer.getBuffer(RenderType.solid()));
|
.renderInto(ms, buffer.getBuffer(RenderType.solid()));
|
||||||
|
|
||||||
BlockPos pos = te.getBlockPos();
|
BlockPos pos = te.getBlockPos();
|
||||||
TrackTargetingBehaviour target = te.getTarget();
|
TrackTargetingBehaviour<SignalBoundary> target = te.edgePoint;
|
||||||
BlockPos targetPosition = target.getGlobalPosition();
|
BlockPos targetPosition = target.getGlobalPosition();
|
||||||
Level level = te.getLevel();
|
Level level = te.getLevel();
|
||||||
BlockState trackState = level.getBlockState(targetPosition);
|
BlockState trackState = level.getBlockState(targetPosition);
|
||||||
|
|
|
@ -1,23 +1,17 @@
|
||||||
package com.simibubi.create.content.logistics.trains.management.signal;
|
package com.simibubi.create.content.logistics.trains.management.signal;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
import javax.annotation.Nullable;
|
||||||
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.management.GraphLocation;
|
|
||||||
import com.simibubi.create.content.logistics.trains.management.TrackTargetingBehaviour;
|
import com.simibubi.create.content.logistics.trains.management.TrackTargetingBehaviour;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
||||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
|
||||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction.AxisDirection;
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.util.Mth;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
@ -42,7 +36,7 @@ public class SignalTileEntity extends SmartTileEntity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID id;
|
public TrackTargetingBehaviour<SignalBoundary> edgePoint;
|
||||||
|
|
||||||
private SignalState state;
|
private SignalState state;
|
||||||
private OverlayState overlay;
|
private OverlayState overlay;
|
||||||
|
@ -50,7 +44,6 @@ public class SignalTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
public SignalTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
public SignalTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||||
super(type, pos, state);
|
super(type, pos, state);
|
||||||
id = UUID.randomUUID();
|
|
||||||
this.state = SignalState.INVALID;
|
this.state = SignalState.INVALID;
|
||||||
this.overlay = OverlayState.SKIP;
|
this.overlay = OverlayState.SKIP;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +51,6 @@ public class SignalTileEntity extends SmartTileEntity {
|
||||||
@Override
|
@Override
|
||||||
protected void write(CompoundTag tag, boolean clientPacket) {
|
protected void write(CompoundTag tag, boolean clientPacket) {
|
||||||
super.write(tag, clientPacket);
|
super.write(tag, clientPacket);
|
||||||
tag.putUUID("Id", id);
|
|
||||||
NBTHelper.writeEnum(tag, "State", state);
|
NBTHelper.writeEnum(tag, "State", state);
|
||||||
NBTHelper.writeEnum(tag, "Overlay", overlay);
|
NBTHelper.writeEnum(tag, "Overlay", overlay);
|
||||||
}
|
}
|
||||||
|
@ -66,12 +58,16 @@ public class SignalTileEntity extends SmartTileEntity {
|
||||||
@Override
|
@Override
|
||||||
protected void read(CompoundTag tag, boolean clientPacket) {
|
protected void read(CompoundTag tag, boolean clientPacket) {
|
||||||
super.read(tag, clientPacket);
|
super.read(tag, clientPacket);
|
||||||
id = tag.getUUID("Id");
|
|
||||||
state = NBTHelper.readEnum(tag, "State", SignalState.class);
|
state = NBTHelper.readEnum(tag, "State", SignalState.class);
|
||||||
overlay = NBTHelper.readEnum(tag, "Overlay", OverlayState.class);
|
overlay = NBTHelper.readEnum(tag, "Overlay", OverlayState.class);
|
||||||
invalidateRenderBoundingBox();
|
invalidateRenderBoundingBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public SignalBoundary getSignal() {
|
||||||
|
return edgePoint.getEdgePoint();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPowered() {
|
public boolean isPowered() {
|
||||||
return state == SignalState.RED;
|
return state == SignalState.RED;
|
||||||
}
|
}
|
||||||
|
@ -89,7 +85,8 @@ public class SignalTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
||||||
behaviours.add(new TrackTargetingBehaviour(this));
|
edgePoint = new TrackTargetingBehaviour<>(this, EdgePointType.SIGNAL);
|
||||||
|
behaviours.add(edgePoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -97,7 +94,7 @@ public class SignalTileEntity extends SmartTileEntity {
|
||||||
super.tick();
|
super.tick();
|
||||||
if (level.isClientSide)
|
if (level.isClientSide)
|
||||||
return;
|
return;
|
||||||
SignalBoundary boundary = getOrCreateSignalBoundary();
|
SignalBoundary boundary = getSignal();
|
||||||
if (boundary == null) {
|
if (boundary == null) {
|
||||||
enterState(SignalState.INVALID);
|
enterState(SignalState.INVALID);
|
||||||
setOverlay(OverlayState.RENDER);
|
setOverlay(OverlayState.RENDER);
|
||||||
|
@ -107,82 +104,6 @@ public class SignalTileEntity extends SmartTileEntity {
|
||||||
setOverlay(boundary.getOverlayFor(worldPosition));
|
setOverlay(boundary.getOverlayFor(worldPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setRemovedNotDueToChunkUnload() {
|
|
||||||
if (!getTarget().hasValidTrack() || level.isClientSide) {
|
|
||||||
super.setRemovedNotDueToChunkUnload();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (TrackGraph trackGraph : Create.RAILWAYS.trackNetworks.values()) {
|
|
||||||
SignalBoundary signal = trackGraph.getSignal(id);
|
|
||||||
if (signal == null)
|
|
||||||
continue;
|
|
||||||
for (boolean front : Iterate.trueAndFalse)
|
|
||||||
signal.signals.get(front)
|
|
||||||
.remove(worldPosition);
|
|
||||||
if (signal.signals.getFirst()
|
|
||||||
.isEmpty()
|
|
||||||
&& signal.signals.getSecond()
|
|
||||||
.isEmpty())
|
|
||||||
trackGraph.removeSignal(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
super.setRemovedNotDueToChunkUnload();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SignalBoundary getOrCreateSignalBoundary() {
|
|
||||||
for (TrackGraph trackGraph : Create.RAILWAYS.trackNetworks.values()) {
|
|
||||||
SignalBoundary signal = trackGraph.getSignal(id);
|
|
||||||
if (signal == null)
|
|
||||||
continue;
|
|
||||||
return signal;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level.isClientSide)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
TrackTargetingBehaviour target = getTarget();
|
|
||||||
if (!target.hasValidTrack())
|
|
||||||
return null;
|
|
||||||
GraphLocation loc = target.determineGraphLocation();
|
|
||||||
if (loc == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
TrackGraph graph = loc.graph;
|
|
||||||
TrackNode node1 = graph.locateNode(loc.edge.getFirst());
|
|
||||||
TrackNode node2 = graph.locateNode(loc.edge.getSecond());
|
|
||||||
TrackEdge edge = graph.getConnectionsFrom(node1)
|
|
||||||
.get(node2);
|
|
||||||
boolean positive = target.getTargetDirection() == AxisDirection.POSITIVE;
|
|
||||||
|
|
||||||
if (edge == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
EdgeData signalData = edge.getEdgeData();
|
|
||||||
if (signalData.hasBoundaries()) {
|
|
||||||
SignalBoundary nextBoundary = signalData.nextBoundary(node1, node2, edge, loc.position - .25f);
|
|
||||||
if (nextBoundary != null && Mth.equal(nextBoundary.getLocationOn(node1, node2, edge), loc.position)) {
|
|
||||||
nextBoundary.signals.get(positive)
|
|
||||||
.add(worldPosition);
|
|
||||||
id = nextBoundary.id;
|
|
||||||
setChanged();
|
|
||||||
return nextBoundary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SignalBoundary signal = new SignalBoundary(id, worldPosition, positive);
|
|
||||||
signal.setLocation(positive ? loc.edge : loc.edge.swap(),
|
|
||||||
positive ? loc.position : edge.getLength(node1, node2) - loc.position);
|
|
||||||
graph.addSignal(signal);
|
|
||||||
setChanged();
|
|
||||||
return signal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TrackTargetingBehaviour getTarget() {
|
|
||||||
return getBehaviour(TrackTargetingBehaviour.TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SignalState getState() {
|
public SignalState getState() {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -213,7 +134,7 @@ public class SignalTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AABB createRenderBoundingBox() {
|
protected AABB createRenderBoundingBox() {
|
||||||
return new AABB(worldPosition, getTarget().getGlobalPosition()).inflate(2);
|
return new AABB(worldPosition, edgePoint.getGlobalPosition()).inflate(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.management.signal;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.NbtUtils;
|
||||||
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
|
||||||
|
public abstract class SingleTileEdgePoint extends TrackEdgePoint {
|
||||||
|
|
||||||
|
public BlockPos tilePos;
|
||||||
|
|
||||||
|
public BlockPos getTilePos() {
|
||||||
|
return tilePos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tileAdded(BlockPos tilePos, boolean front) {
|
||||||
|
this.tilePos = tilePos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tileRemoved(BlockPos tilePos, boolean front) {
|
||||||
|
removeFromAllGraphs();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidate(LevelAccessor level) {
|
||||||
|
invalidateAt(level, tilePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canMerge() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void read(CompoundTag nbt) {
|
||||||
|
read(nbt, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void read(CompoundTag nbt, boolean migration) {
|
||||||
|
if (migration)
|
||||||
|
return;
|
||||||
|
|
||||||
|
super.read(nbt);
|
||||||
|
tilePos = NbtUtils.readBlockPos(nbt.getCompound("TilePos"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(CompoundTag nbt) {
|
||||||
|
super.write(nbt);
|
||||||
|
nbt.put("TilePos", NbtUtils.writeBlockPos(tilePos));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,32 +2,68 @@ package com.simibubi.create.content.logistics.trains.management.signal;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackEdge;
|
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.TrackNode;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
|
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.TrackTargetingBehaviour;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtUtils;
|
import net.minecraft.nbt.NbtUtils;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
|
||||||
public class TrackEdgePoint {
|
public abstract class TrackEdgePoint {
|
||||||
|
|
||||||
public UUID id;
|
public UUID id;
|
||||||
public Couple<TrackNodeLocation> edgeLocation;
|
public Couple<TrackNodeLocation> edgeLocation;
|
||||||
public double position;
|
public double position;
|
||||||
|
private EdgePointType<?> type;
|
||||||
|
|
||||||
public TrackEdgePoint(UUID id) {
|
public void setId(UUID id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TrackEdgePoint(CompoundTag nbt) {
|
public UUID getId() {
|
||||||
id = nbt.getUUID("Id");
|
return id;
|
||||||
position = nbt.getDouble("Position");
|
|
||||||
edgeLocation = Couple.deserializeEach(nbt.getList("Edge", Tag.TAG_COMPOUND),
|
|
||||||
tag -> TrackNodeLocation.fromPackedPos(NbtUtils.readBlockPos(tag)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setType(EdgePointType<?> type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EdgePointType<?> getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract boolean canMerge();
|
||||||
|
|
||||||
|
public boolean canCoexistWith(EdgePointType<?> otherType, boolean front) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void invalidate(LevelAccessor level);
|
||||||
|
|
||||||
|
protected void invalidateAt(LevelAccessor level, BlockPos tilePos) {
|
||||||
|
TrackTargetingBehaviour<?> behaviour = TileEntityBehaviour.get(level, tilePos, TrackTargetingBehaviour.TYPE);
|
||||||
|
if (behaviour == null)
|
||||||
|
return;
|
||||||
|
CompoundTag migrationData = new CompoundTag();
|
||||||
|
write(migrationData);
|
||||||
|
behaviour.invalidateEdgePoint(migrationData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void tileAdded(BlockPos tilePos, boolean front);
|
||||||
|
|
||||||
|
public abstract void tileRemoved(BlockPos tilePos, boolean front);
|
||||||
|
|
||||||
|
public void onRemoved(TrackGraph graph) {}
|
||||||
|
|
||||||
public void setLocation(Couple<TrackNodeLocation> nodes, double position) {
|
public void setLocation(Couple<TrackNodeLocation> nodes, double position) {
|
||||||
this.edgeLocation = nodes;
|
this.edgeLocation = nodes;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
|
@ -37,9 +73,34 @@ public class TrackEdgePoint {
|
||||||
return isPrimary(node1) ? edge.getLength(node1, node2) - position : position;
|
return isPrimary(node1) ? edge.getLength(node1, node2) - position : position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean canNavigateVia(TrackNode side) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPrimary(TrackNode node1) {
|
public boolean isPrimary(TrackNode node1) {
|
||||||
return edgeLocation.getSecond()
|
return edgeLocation.getSecond()
|
||||||
.equals(node1.getLocation());
|
.equals(node1.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void read(CompoundTag nbt) {
|
||||||
|
id = nbt.getUUID("Id");
|
||||||
|
position = nbt.getDouble("Position");
|
||||||
|
edgeLocation = Couple.deserializeEach(nbt.getList("Edge", Tag.TAG_COMPOUND),
|
||||||
|
tag -> TrackNodeLocation.fromPackedPos(NbtUtils.readBlockPos(tag)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(CompoundTag nbt) {
|
||||||
|
nbt.putUUID("Id", id);
|
||||||
|
nbt.putDouble("Position", position);
|
||||||
|
nbt.put("Edge", edgeLocation.serializeEach(loc -> NbtUtils.writeBlockPos(new BlockPos(loc))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick(TrackGraph graph) {}
|
||||||
|
|
||||||
|
protected void removeFromAllGraphs() {
|
||||||
|
for (TrackGraph trackGraph : Create.RAILWAYS.trackNetworks.values())
|
||||||
|
if (trackGraph.removePoint(getType(), id) != null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,8 +348,8 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
public PartialModel prepareAssemblyOverlay(BlockGetter world, BlockPos pos, BlockState state, Direction direction,
|
public PartialModel prepareAssemblyOverlay(BlockGetter world, BlockPos pos, BlockState state, Direction direction,
|
||||||
PoseStack ms) {
|
PoseStack ms) {
|
||||||
TransformStack.cast(ms).rotateCentered(Direction.UP,
|
TransformStack.cast(ms)
|
||||||
AngleHelper.rad(AngleHelper.horizontalAngle(direction)));
|
.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(direction)));
|
||||||
return AllBlockPartials.TRACK_ASSEMBLING_OVERLAY;
|
return AllBlockPartials.TRACK_ASSEMBLING_OVERLAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,11 +365,13 @@ public class TrackBlock extends Block implements EntityBlock, IWrenchable, ITrac
|
||||||
Vec3 normal = getUpNormal(world, pos, state);
|
Vec3 normal = getUpNormal(world, pos, state);
|
||||||
Vec3 angles = TrackRenderer.getModelAngles(normal, directionVec);
|
Vec3 angles = TrackRenderer.getModelAngles(normal, directionVec);
|
||||||
|
|
||||||
TransformStack.cast(ms).centre()
|
TransformStack.cast(ms)
|
||||||
|
.centre()
|
||||||
.rotateYRadians(angles.y)
|
.rotateYRadians(angles.y)
|
||||||
.rotateXRadians(angles.x)
|
.rotateXRadians(angles.x)
|
||||||
.unCentre()
|
.unCentre()
|
||||||
.translate(0, axis.y != 0 ? 7 / 16f : 0, axis.y != 0 ? direction.getStep() * 2.5f / 16f : 0);
|
.translate(0, axis.y != 0 ? 7 / 16f : 0, axis.y != 0 ? direction.getStep() * 2.5f / 16f : 0)
|
||||||
|
.scale(type == RenderedTrackOverlayType.STATION ? 1 + 1 / 512f : 1);
|
||||||
|
|
||||||
return type == RenderedTrackOverlayType.STATION ? AllBlockPartials.TRACK_STATION_OVERLAY
|
return type == RenderedTrackOverlayType.STATION ? AllBlockPartials.TRACK_STATION_OVERLAY
|
||||||
: type == RenderedTrackOverlayType.SIGNAL ? AllBlockPartials.TRACK_SIGNAL_OVERLAY
|
: type == RenderedTrackOverlayType.SIGNAL ? AllBlockPartials.TRACK_SIGNAL_OVERLAY
|
||||||
|
|
|
@ -93,6 +93,7 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE
|
||||||
TrackTileEntity other = (TrackTileEntity) blockEntity;
|
TrackTileEntity other = (TrackTileEntity) blockEntity;
|
||||||
other.removeConnection(bezierConnection.tePositions.getFirst());
|
other.removeConnection(bezierConnection.tePositions.getFirst());
|
||||||
}
|
}
|
||||||
|
AllPackets.channel.send(packetTarget(), new RemoveTileEntityPacket(worldPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -13,6 +13,7 @@ import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||||
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
|
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
|
||||||
import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime;
|
import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime;
|
||||||
import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime.State;
|
import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime.State;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
||||||
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
|
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
|
||||||
|
|
||||||
import net.minecraft.ChatFormatting;
|
import net.minecraft.ChatFormatting;
|
||||||
|
@ -62,11 +63,11 @@ public class DumpRailwaysCommand {
|
||||||
+ graph.getNodes()
|
+ graph.getNodes()
|
||||||
.size()
|
.size()
|
||||||
+ " Nodes", graph.color.getRGB());
|
+ " Nodes", graph.color.getRGB());
|
||||||
Collection<SignalBoundary> signals = graph.getSignals();
|
Collection<SignalBoundary> signals = graph.getPoints(EdgePointType.SIGNAL);
|
||||||
if (!signals.isEmpty())
|
if (!signals.isEmpty())
|
||||||
chat.accept(" -> " + signals.size() + " registered Signals", blue);
|
chat.accept(" -> " + signals.size() + " registered Signals", blue);
|
||||||
for (GlobalStation globalStation : graph.getStations()) {
|
for (GlobalStation globalStation : graph.getPoints(EdgePointType.STATION)) {
|
||||||
BlockPos pos = globalStation.stationPos;
|
BlockPos pos = globalStation.getTilePos();
|
||||||
chat.accept(" -> " + globalStation.name + " (" + globalStation.id.toString()
|
chat.accept(" -> " + globalStation.name + " (" + globalStation.id.toString()
|
||||||
.substring(0, 5) + ") [" + pos.getX() + "," + pos.getY() + "," + pos.getZ() + "]", darkBlue);
|
.substring(0, 5) + ") [" + pos.getX() + "," + pos.getY() + "," + pos.getZ() + "]", darkBlue);
|
||||||
if (globalStation.getPresentTrain() != null) {
|
if (globalStation.getPresentTrain() != null) {
|
||||||
|
|
|
@ -129,12 +129,11 @@ public abstract class SmartTileEntity extends CachedRenderBBTileEntity implement
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setRemovedNotDueToChunkUnload() {
|
protected void setRemovedNotDueToChunkUnload() {
|
||||||
|
forEachBehaviour(TileEntityBehaviour::remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setRemoved() {
|
public void setRemoved() {
|
||||||
forEachBehaviour(TileEntityBehaviour::remove);
|
|
||||||
super.setRemoved();
|
super.setRemoved();
|
||||||
|
|
||||||
if (!unloaded) {
|
if (!unloaded) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import java.util.function.BiConsumer;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@ -62,6 +63,14 @@ public class Couple<T> extends Pair<T, T> implements Iterable<T> {
|
||||||
return Couple.create(function.apply(first, values.first), function.apply(second, values.second));
|
return Couple.create(function.apply(first, values.first), function.apply(second, values.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean both(Predicate<T> test) {
|
||||||
|
return test.test(getFirst()) && test.test(getSecond());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean either(Predicate<T> test) {
|
||||||
|
return test.test(getFirst()) || test.test(getSecond());
|
||||||
|
}
|
||||||
|
|
||||||
public void replace(Function<T, T> function) {
|
public void replace(Function<T, T> function) {
|
||||||
setFirst(function.apply(getFirst()));
|
setFirst(function.apply(getFirst()));
|
||||||
setSecond(function.apply(getSecond()));
|
setSecond(function.apply(getSecond()));
|
||||||
|
|
Loading…
Reference in a new issue