CreateMod/src/main/java/com/simibubi/create/content/trains/entity/TrainMigration.java
2023-05-24 07:59:45 -07:00

121 lines
3.9 KiB
Java

package com.simibubi.create.content.trains.entity;
import java.util.Map.Entry;
import com.simibubi.create.content.trains.graph.DimensionPalette;
import com.simibubi.create.content.trains.graph.TrackEdge;
import com.simibubi.create.content.trains.graph.TrackGraph;
import com.simibubi.create.content.trains.graph.TrackGraphLocation;
import com.simibubi.create.content.trains.graph.TrackNode;
import com.simibubi.create.content.trains.graph.TrackNodeLocation;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
public class TrainMigration {
Couple<TrackNodeLocation> locations;
double positionOnOldEdge;
boolean curve;
Vec3 fallback;
public TrainMigration() {}
public TrainMigration(TravellingPoint point) {
double t = point.position / point.edge.getLength();
fallback = point.edge.getPosition(null, t);
curve = point.edge.isTurn();
positionOnOldEdge = point.position;
locations = Couple.create(point.node1.getLocation(), point.node2.getLocation());
}
public TrackGraphLocation tryMigratingTo(TrackGraph graph) {
TrackNode node1 = graph.locateNode(locations.getFirst());
TrackNode node2 = graph.locateNode(locations.getSecond());
if (node1 != null && node2 != null) {
TrackEdge edge = graph.getConnectionsFrom(node1)
.get(node2);
if (edge != null) {
TrackGraphLocation graphLocation = new TrackGraphLocation();
graphLocation.graph = graph;
graphLocation.edge = locations;
graphLocation.position = positionOnOldEdge;
return graphLocation;
}
}
if (curve)
return null;
Vec3 prevDirection = locations.getSecond()
.getLocation()
.subtract(locations.getFirst()
.getLocation())
.normalize();
for (TrackNodeLocation loc : graph.getNodes()) {
Vec3 nodeVec = loc.getLocation();
if (nodeVec.distanceToSqr(fallback) > 32 * 32)
continue;
TrackNode newNode1 = graph.locateNode(loc);
for (Entry<TrackNode, TrackEdge> entry : graph.getConnectionsFrom(newNode1)
.entrySet()) {
TrackEdge edge = entry.getValue();
if (edge.isTurn())
continue;
TrackNode newNode2 = entry.getKey();
float radius = 1 / 64f;
Vec3 direction = edge.getDirection(true);
if (!Mth.equal(direction.dot(prevDirection), 1))
continue;
Vec3 intersectSphere = VecHelper.intersectSphere(nodeVec, direction, fallback, radius);
if (intersectSphere == null)
continue;
if (!Mth.equal(direction.dot(intersectSphere.subtract(nodeVec)
.normalize()), 1))
continue;
double edgeLength = edge.getLength();
double position = intersectSphere.distanceTo(nodeVec) - radius;
if (Double.isNaN(position))
continue;
if (position < 0)
continue;
if (position > edgeLength)
continue;
TrackGraphLocation graphLocation = new TrackGraphLocation();
graphLocation.graph = graph;
graphLocation.edge = Couple.create(loc, newNode2.getLocation());
graphLocation.position = position;
return graphLocation;
}
}
return null;
}
public CompoundTag write(DimensionPalette dimensions) {
CompoundTag tag = new CompoundTag();
tag.putBoolean("Curve", curve);
tag.put("Fallback", VecHelper.writeNBT(fallback));
tag.putDouble("Position", positionOnOldEdge);
tag.put("Nodes", locations.serializeEach(l -> l.write(dimensions)));
return tag;
}
public static TrainMigration read(CompoundTag tag, DimensionPalette dimensions) {
TrainMigration trainMigration = new TrainMigration();
trainMigration.curve = tag.getBoolean("Curve");
trainMigration.fallback = VecHelper.readNBT(tag.getList("Fallback", Tag.TAG_DOUBLE));
trainMigration.positionOnOldEdge = tag.getDouble("Position");
trainMigration.locations =
Couple.deserializeEach(tag.getList("Nodes", Tag.TAG_COMPOUND), c -> TrackNodeLocation.read(c, dimensions));
return trainMigration;
}
}