2022-02-01 01:14:21 +01:00
|
|
|
package com.simibubi.create.content.logistics.trains;
|
|
|
|
|
2022-04-25 17:53:45 +02:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.Collections;
|
|
|
|
|
|
|
|
import com.google.common.collect.ImmutableList;
|
2022-03-08 03:51:03 +01:00
|
|
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData;
|
2022-02-01 01:14:21 +01:00
|
|
|
import com.simibubi.create.foundation.utility.VecHelper;
|
|
|
|
|
2022-02-09 21:13:33 +01:00
|
|
|
import net.minecraft.core.BlockPos;
|
2022-04-25 17:53:45 +02:00
|
|
|
import net.minecraft.core.Direction.Axis;
|
2022-02-01 01:14:21 +01:00
|
|
|
import net.minecraft.nbt.CompoundTag;
|
|
|
|
import net.minecraft.util.Mth;
|
2022-04-25 17:53:45 +02:00
|
|
|
import net.minecraft.world.phys.AABB;
|
2022-02-01 01:14:21 +01:00
|
|
|
import net.minecraft.world.phys.Vec3;
|
|
|
|
|
|
|
|
public class TrackEdge {
|
|
|
|
|
2022-04-25 17:53:45 +02:00
|
|
|
public TrackNode node1;
|
|
|
|
public TrackNode node2;
|
2022-02-01 01:14:21 +01:00
|
|
|
BezierConnection turn;
|
2022-02-16 03:14:31 +01:00
|
|
|
EdgeData edgeData;
|
2022-05-15 21:19:02 +02:00
|
|
|
boolean interDimensional;
|
2023-05-09 18:23:47 +02:00
|
|
|
TrackMaterial trackMaterial;
|
2022-02-01 01:14:21 +01:00
|
|
|
|
2023-05-09 18:23:47 +02:00
|
|
|
public TrackEdge(TrackNode node1, TrackNode node2, BezierConnection turn, TrackMaterial trackMaterial) {
|
2022-05-15 21:19:02 +02:00
|
|
|
this.interDimensional = !node1.location.dimension.equals(node2.location.dimension);
|
2022-04-25 17:53:45 +02:00
|
|
|
this.edgeData = new EdgeData(this);
|
|
|
|
this.node1 = node1;
|
|
|
|
this.node2 = node2;
|
2022-02-01 01:14:21 +01:00
|
|
|
this.turn = turn;
|
2023-05-09 18:23:47 +02:00
|
|
|
this.trackMaterial = trackMaterial;
|
|
|
|
}
|
|
|
|
|
|
|
|
public TrackMaterial getTrackMaterial() {
|
|
|
|
return trackMaterial;
|
2022-02-01 01:14:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isTurn() {
|
|
|
|
return turn != null;
|
|
|
|
}
|
|
|
|
|
2022-05-15 21:19:02 +02:00
|
|
|
public boolean isInterDimensional() {
|
|
|
|
return interDimensional;
|
|
|
|
}
|
|
|
|
|
2022-02-16 03:14:31 +01:00
|
|
|
public EdgeData getEdgeData() {
|
|
|
|
return edgeData;
|
|
|
|
}
|
|
|
|
|
2022-02-01 01:14:21 +01:00
|
|
|
public BezierConnection getTurn() {
|
|
|
|
return turn;
|
|
|
|
}
|
|
|
|
|
2022-04-25 17:53:45 +02:00
|
|
|
public Vec3 getDirection(boolean fromFirst) {
|
|
|
|
return getPosition(fromFirst ? 0.25f : 1).subtract(getPosition(fromFirst ? 0 : 0.75f))
|
2022-02-01 01:14:21 +01:00
|
|
|
.normalize();
|
|
|
|
}
|
|
|
|
|
2022-05-18 20:36:58 +02:00
|
|
|
public Vec3 getDirectionAt(double t) {
|
|
|
|
double length = getLength();
|
|
|
|
double step = .5f / length;
|
|
|
|
t /= length;
|
|
|
|
Vec3 ahead = getPosition(Math.min(1, t + step));
|
|
|
|
Vec3 behind = getPosition(Math.max(0, t - step));
|
|
|
|
return ahead.subtract(behind)
|
|
|
|
.normalize();
|
|
|
|
}
|
|
|
|
|
2022-05-15 21:19:02 +02:00
|
|
|
public boolean canTravelTo(TrackEdge other) {
|
|
|
|
if (isInterDimensional() || other.isInterDimensional())
|
|
|
|
return true;
|
|
|
|
Vec3 newDirection = other.getDirection(true);
|
|
|
|
return getDirection(false).dot(newDirection) > 7 / 8f;
|
|
|
|
}
|
|
|
|
|
2022-04-25 17:53:45 +02:00
|
|
|
public double getLength() {
|
2022-05-15 21:19:02 +02:00
|
|
|
return isInterDimensional() ? 0
|
|
|
|
: isTurn() ? turn.getLength()
|
|
|
|
: node1.location.getLocation()
|
|
|
|
.distanceTo(node2.location.getLocation());
|
2022-02-01 01:14:21 +01:00
|
|
|
}
|
|
|
|
|
2022-04-25 17:53:45 +02:00
|
|
|
public double incrementT(double currentT, double distance) {
|
|
|
|
boolean tooFar = Math.abs(distance) > 5;
|
2022-05-15 21:19:02 +02:00
|
|
|
double length = getLength();
|
|
|
|
distance = distance / (length == 0 ? 1 : length);
|
2022-03-17 23:14:53 +01:00
|
|
|
return !tooFar && isTurn() ? turn.incrementT(currentT, distance) : currentT + distance;
|
2022-02-01 01:14:21 +01:00
|
|
|
}
|
|
|
|
|
2022-04-25 17:53:45 +02:00
|
|
|
public Vec3 getPosition(double t) {
|
2022-02-01 01:14:21 +01:00
|
|
|
return isTurn() ? turn.getPosition(Mth.clamp(t, 0, 1))
|
|
|
|
: VecHelper.lerp((float) t, node1.location.getLocation(), node2.location.getLocation());
|
|
|
|
}
|
|
|
|
|
2022-04-25 17:53:45 +02:00
|
|
|
public Collection<double[]> getIntersection(TrackNode node1, TrackNode node2, TrackEdge other, TrackNode other1,
|
|
|
|
TrackNode other2) {
|
|
|
|
Vec3 v1 = node1.location.getLocation();
|
|
|
|
Vec3 v2 = node2.location.getLocation();
|
|
|
|
Vec3 w1 = other1.location.getLocation();
|
|
|
|
Vec3 w2 = other2.location.getLocation();
|
|
|
|
|
2022-05-15 21:19:02 +02:00
|
|
|
if (isInterDimensional() || other.isInterDimensional())
|
|
|
|
return Collections.emptyList();
|
2022-04-25 17:53:45 +02:00
|
|
|
if (v1.y != v2.y || v1.y != w1.y || v1.y != w2.y)
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
|
|
|
if (!isTurn()) {
|
|
|
|
if (!other.isTurn())
|
|
|
|
return ImmutableList.of(VecHelper.intersectRanged(v1, w1, v2, w2, Axis.Y));
|
|
|
|
return other.getIntersection(other1, other2, this, node1, node2)
|
|
|
|
.stream()
|
|
|
|
.map(a -> new double[] { a[1], a[0] })
|
|
|
|
.toList();
|
|
|
|
}
|
|
|
|
|
|
|
|
AABB bb = turn.getBounds();
|
|
|
|
|
|
|
|
if (!other.isTurn()) {
|
|
|
|
if (!bb.intersects(w1, w2))
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
|
|
|
Vec3 seg1 = v1;
|
|
|
|
Vec3 seg2 = null;
|
|
|
|
double t = 0;
|
|
|
|
|
|
|
|
Collection<double[]> intersections = new ArrayList<>();
|
|
|
|
for (int i = 0; i < turn.getSegmentCount(); i++) {
|
|
|
|
double tOffset = t;
|
|
|
|
t += .5;
|
|
|
|
seg2 = getPosition(t / getLength());
|
|
|
|
double[] intersection = VecHelper.intersectRanged(seg1, w1, seg2, w2, Axis.Y);
|
|
|
|
seg1 = seg2;
|
|
|
|
if (intersection == null)
|
|
|
|
continue;
|
|
|
|
intersection[0] += tOffset;
|
|
|
|
intersections.add(intersection);
|
|
|
|
}
|
|
|
|
|
|
|
|
return intersections;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bb.intersects(other.turn.getBounds()))
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
|
|
|
Vec3 seg1 = v1;
|
|
|
|
Vec3 seg2 = null;
|
|
|
|
double t = 0;
|
|
|
|
|
|
|
|
Collection<double[]> intersections = new ArrayList<>();
|
|
|
|
for (int i = 0; i < turn.getSegmentCount(); i++) {
|
|
|
|
double tOffset = t;
|
|
|
|
t += .5;
|
|
|
|
seg2 = getPosition(t / getLength());
|
|
|
|
|
|
|
|
Vec3 otherSeg1 = w1;
|
|
|
|
Vec3 otherSeg2 = null;
|
|
|
|
double u = 0;
|
|
|
|
|
|
|
|
for (int j = 0; j < other.turn.getSegmentCount(); j++) {
|
|
|
|
double uOffset = u;
|
|
|
|
u += .5;
|
|
|
|
otherSeg2 = other.getPosition(u / other.getLength());
|
|
|
|
|
|
|
|
double[] intersection = VecHelper.intersectRanged(seg1, otherSeg1, seg2, otherSeg2, Axis.Y);
|
|
|
|
otherSeg1 = otherSeg2;
|
|
|
|
|
|
|
|
if (intersection == null)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
intersection[0] += tOffset;
|
|
|
|
intersection[1] += uOffset;
|
|
|
|
intersections.add(intersection);
|
|
|
|
}
|
|
|
|
|
|
|
|
seg1 = seg2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return intersections;
|
|
|
|
}
|
|
|
|
|
2022-02-01 01:14:21 +01:00
|
|
|
public Vec3 getNormal(TrackNode node1, TrackNode node2, double t) {
|
|
|
|
return isTurn() ? turn.getNormal(Mth.clamp(t, 0, 1)) : node1.getNormal();
|
|
|
|
}
|
|
|
|
|
2022-05-15 21:19:02 +02:00
|
|
|
public CompoundTag write(DimensionPalette dimensions) {
|
2022-02-16 03:14:31 +01:00
|
|
|
CompoundTag baseCompound = isTurn() ? turn.write(BlockPos.ZERO) : new CompoundTag();
|
2022-05-15 21:19:02 +02:00
|
|
|
baseCompound.put("Signals", edgeData.write(dimensions));
|
2023-05-09 18:23:47 +02:00
|
|
|
baseCompound.putString("Material", getTrackMaterial().id.toString());
|
2022-02-16 03:14:31 +01:00
|
|
|
return baseCompound;
|
2022-02-01 01:14:21 +01:00
|
|
|
}
|
|
|
|
|
2022-05-15 21:19:02 +02:00
|
|
|
public static TrackEdge read(TrackNode node1, TrackNode node2, CompoundTag tag, TrackGraph graph,
|
|
|
|
DimensionPalette dimensions) {
|
2022-02-16 03:14:31 +01:00
|
|
|
TrackEdge trackEdge =
|
2023-05-09 18:23:47 +02:00
|
|
|
new TrackEdge(node1, node2, tag.contains("Positions") ? new BezierConnection(tag, BlockPos.ZERO) : null,
|
|
|
|
TrackMaterial.deserialize(tag.getString("Material")));
|
2022-05-15 21:19:02 +02:00
|
|
|
trackEdge.edgeData = EdgeData.read(tag.getCompound("Signals"), trackEdge, graph, dimensions);
|
2022-02-16 03:14:31 +01:00
|
|
|
return trackEdge;
|
2022-02-01 01:14:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|