mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-15 01:53:49 +01:00
Graph hopping, Part II
- added "/create dumpRailways" command - trains now react to changes of the graph beneath them - trains now notify owner of unexpected issues - filtered navigation wildcard works now - navigation now smarter I guess - navigation cancelled when track path gets disconnected - stations and trains no longer disassociate when graph is edited - schedule no longer skips entry when navigation gets interrupted - trains can now be in a "de-railed" state
This commit is contained in:
parent
c6278dbd24
commit
c3e1e9df3f
24 changed files with 733 additions and 150 deletions
|
@ -41,7 +41,7 @@ public class AllEntityTypes {
|
||||||
GantryContraptionEntity::new, () -> ContraptionEntityRenderer::new, 10, 40, false);
|
GantryContraptionEntity::new, () -> ContraptionEntityRenderer::new, 10, 40, false);
|
||||||
public static final EntityEntry<CarriageContraptionEntity> CARRIAGE_CONTRAPTION =
|
public static final EntityEntry<CarriageContraptionEntity> CARRIAGE_CONTRAPTION =
|
||||||
contraption("carriage_contraption", CarriageContraptionEntity::new,
|
contraption("carriage_contraption", CarriageContraptionEntity::new,
|
||||||
() -> CarriageContraptionEntityRenderer::new, 5, 100, true);
|
() -> CarriageContraptionEntityRenderer::new, 5, 3, true);
|
||||||
|
|
||||||
public static final EntityEntry<SuperGlueEntity> SUPER_GLUE =
|
public static final EntityEntry<SuperGlueEntity> SUPER_GLUE =
|
||||||
register("super_glue", SuperGlueEntity::new, () -> SuperGlueRenderer::new, MobCategory.MISC, 10,
|
register("super_glue", SuperGlueEntity::new, () -> SuperGlueRenderer::new, MobCategory.MISC, 10,
|
||||||
|
|
|
@ -19,10 +19,10 @@ import javax.annotation.Nullable;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.CreateClient;
|
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.management.GlobalStation;
|
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
|
||||||
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.Couple;
|
||||||
import com.simibubi.create.foundation.utility.Debug;
|
|
||||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ public class TrackGraph {
|
||||||
|
|
||||||
public static final AtomicInteger netIdGenerator = new AtomicInteger();
|
public static final AtomicInteger netIdGenerator = new AtomicInteger();
|
||||||
|
|
||||||
UUID id;
|
public UUID id;
|
||||||
Color color;
|
public Color color;
|
||||||
|
|
||||||
Map<TrackNodeLocation, TrackNode> nodes;
|
Map<TrackNodeLocation, TrackNode> nodes;
|
||||||
Map<Integer, TrackNode> nodesById;
|
Map<Integer, TrackNode> nodesById;
|
||||||
|
@ -58,7 +58,7 @@ public class TrackGraph {
|
||||||
nodes = new HashMap<>();
|
nodes = new HashMap<>();
|
||||||
nodesById = new HashMap<>();
|
nodesById = new HashMap<>();
|
||||||
connectionsByNode = new IdentityHashMap<>();
|
connectionsByNode = new IdentityHashMap<>();
|
||||||
color = Color.rainbowColor(new Random().nextInt());
|
color = Color.rainbowColor(new Random(graphID.getLeastSignificantBits()).nextInt());
|
||||||
stations = new HashMap<>();
|
stations = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +85,10 @@ public class TrackGraph {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
public Set<TrackNodeLocation> getNodes() {
|
||||||
|
return nodes.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
public TrackNode locateNode(Vec3 position) {
|
public TrackNode locateNode(Vec3 position) {
|
||||||
return locateNode(new TrackNodeLocation(position));
|
return locateNode(new TrackNodeLocation(position));
|
||||||
}
|
}
|
||||||
|
@ -122,17 +126,32 @@ public class TrackGraph {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (level != null) {
|
if (level != null) {
|
||||||
for (Iterator<UUID> iterator = stations.keySet().iterator(); iterator.hasNext();) {
|
for (Iterator<UUID> iterator = stations.keySet()
|
||||||
|
.iterator(); iterator.hasNext();) {
|
||||||
UUID uuid = iterator.next();
|
UUID uuid = iterator.next();
|
||||||
GlobalStation globalStation = stations.get(uuid);
|
GlobalStation globalStation = stations.get(uuid);
|
||||||
Couple<TrackNodeLocation> loc = globalStation.edgeLocation;
|
Couple<TrackNodeLocation> loc = globalStation.edgeLocation;
|
||||||
if (loc.getFirst().equals(location) || loc.getSecond().equals(location)) {
|
if (loc.getFirst()
|
||||||
|
.equals(location)
|
||||||
|
|| loc.getSecond()
|
||||||
|
.equals(location)) {
|
||||||
globalStation.migrate(level);
|
globalStation.migrate(level);
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<UUID, Train> trains = Create.RAILWAYS.trains;
|
||||||
|
for (Iterator<UUID> iterator = trains.keySet()
|
||||||
|
.iterator(); iterator.hasNext();) {
|
||||||
|
UUID uuid = iterator.next();
|
||||||
|
Train train = trains.get(uuid);
|
||||||
|
if (train.graph != this)
|
||||||
|
continue;
|
||||||
|
if (train.isTravellingOn(removed))
|
||||||
|
train.detachFromTracks();
|
||||||
|
}
|
||||||
|
|
||||||
nodesById.remove(removed.netId);
|
nodesById.remove(removed.netId);
|
||||||
if (!connectionsByNode.containsKey(removed))
|
if (!connectionsByNode.containsKey(removed))
|
||||||
return true;
|
return true;
|
||||||
|
@ -165,6 +184,16 @@ public class TrackGraph {
|
||||||
nodes.clear();
|
nodes.clear();
|
||||||
nodesById.clear();
|
nodesById.clear();
|
||||||
connectionsByNode.clear();
|
connectionsByNode.clear();
|
||||||
|
|
||||||
|
Map<UUID, Train> trains = Create.RAILWAYS.trains;
|
||||||
|
for (Iterator<UUID> iterator = trains.keySet()
|
||||||
|
.iterator(); iterator.hasNext();) {
|
||||||
|
UUID uuid = iterator.next();
|
||||||
|
Train train = trains.get(uuid);
|
||||||
|
if (train.graph != this)
|
||||||
|
continue;
|
||||||
|
train.graph = toOther;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<TrackGraph> findDisconnectedGraphs(@Nullable Map<Integer, UUID> preAssignedIds) {
|
public Set<TrackGraph> findDisconnectedGraphs(@Nullable Map<Integer, UUID> preAssignedIds) {
|
||||||
|
@ -214,12 +243,15 @@ public class TrackGraph {
|
||||||
if (!connections.isEmpty()) {
|
if (!connections.isEmpty()) {
|
||||||
target.connectionsByNode.put(node, connections);
|
target.connectionsByNode.put(node, connections);
|
||||||
for (TrackNode entry : connections.keySet()) {
|
for (TrackNode entry : connections.keySet()) {
|
||||||
for (Iterator<UUID> iterator = stations.keySet().iterator(); iterator.hasNext();) {
|
for (Iterator<UUID> iterator = stations.keySet()
|
||||||
|
.iterator(); iterator.hasNext();) {
|
||||||
UUID uuid = iterator.next();
|
UUID uuid = iterator.next();
|
||||||
GlobalStation globalStation = stations.get(uuid);
|
GlobalStation globalStation = stations.get(uuid);
|
||||||
Couple<TrackNodeLocation> loc = globalStation.edgeLocation;
|
Couple<TrackNodeLocation> loc = globalStation.edgeLocation;
|
||||||
if (loc.getFirst().equals(location1) && loc.getSecond().equals(entry.getLocation())) {
|
if (loc.getFirst()
|
||||||
Debug.debugChat("Station " + globalStation.name + " migrated directly due to graph split");
|
.equals(location1)
|
||||||
|
&& loc.getSecond()
|
||||||
|
.equals(entry.getLocation())) {
|
||||||
target.addStation(globalStation);
|
target.addStation(globalStation);
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
|
@ -227,6 +259,18 @@ public class TrackGraph {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<UUID, Train> trains = Create.RAILWAYS.trains;
|
||||||
|
for (Iterator<UUID> iterator = trains.keySet()
|
||||||
|
.iterator(); iterator.hasNext();) {
|
||||||
|
UUID uuid = iterator.next();
|
||||||
|
Train train = trains.get(uuid);
|
||||||
|
if (train.graph != this)
|
||||||
|
continue;
|
||||||
|
if (!train.isTravellingOn(node))
|
||||||
|
continue;
|
||||||
|
train.graph = target;
|
||||||
|
}
|
||||||
|
|
||||||
nodes.remove(location1);
|
nodes.remove(location1);
|
||||||
nodesById.remove(node.getNetId());
|
nodesById.remove(node.getNetId());
|
||||||
connectionsByNode.remove(node);
|
connectionsByNode.remove(node);
|
||||||
|
|
|
@ -9,8 +9,10 @@ import javax.annotation.Nullable;
|
||||||
import org.apache.commons.lang3.mutable.MutableDouble;
|
import org.apache.commons.lang3.mutable.MutableDouble;
|
||||||
import org.apache.commons.lang3.mutable.MutableObject;
|
import org.apache.commons.lang3.mutable.MutableObject;
|
||||||
|
|
||||||
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.entity.MovingPoint.ITrackSelector;
|
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||||
|
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector;
|
||||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
@ -31,6 +33,7 @@ public class Carriage {
|
||||||
public CarriageContraption contraption;
|
public CarriageContraption contraption;
|
||||||
public int bogeySpacing;
|
public int bogeySpacing;
|
||||||
public int id;
|
public int id;
|
||||||
|
public boolean blocked;
|
||||||
|
|
||||||
WeakReference<CarriageContraptionEntity> entity;
|
WeakReference<CarriageContraptionEntity> entity;
|
||||||
Couple<CarriageBogey> bogeys;
|
Couple<CarriageBogey> bogeys;
|
||||||
|
@ -40,6 +43,10 @@ public class Carriage {
|
||||||
this.bogeys = Couple.create(bogey1, bogey2);
|
this.bogeys = Couple.create(bogey1, bogey2);
|
||||||
this.entity = new WeakReference<>(null);
|
this.entity = new WeakReference<>(null);
|
||||||
this.id = netIdGenerator.incrementAndGet();
|
this.id = netIdGenerator.incrementAndGet();
|
||||||
|
|
||||||
|
bogey1.carriage = this;
|
||||||
|
if (bogey2 != null)
|
||||||
|
bogey2.carriage = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTrain(Train train) {
|
public void setTrain(Train train) {
|
||||||
|
@ -51,11 +58,13 @@ public class Carriage {
|
||||||
contraption.setCarriage(this);
|
contraption.setCarriage(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double travel(Level level, double distance, @Nullable Function<MovingPoint, ITrackSelector> control) {
|
public double travel(Level level, TrackGraph graph, double distance,
|
||||||
|
@Nullable Function<TravellingPoint, ITrackSelector> control) {
|
||||||
Vec3 leadingAnchor = leadingBogey().anchorPosition;
|
Vec3 leadingAnchor = leadingBogey().anchorPosition;
|
||||||
Vec3 trailingAnchor = trailingBogey().anchorPosition;
|
Vec3 trailingAnchor = trailingBogey().anchorPosition;
|
||||||
boolean onTwoBogeys = isOnTwoBogeys();
|
boolean onTwoBogeys = isOnTwoBogeys();
|
||||||
double stress = onTwoBogeys ? bogeySpacing - leadingAnchor.distanceTo(trailingAnchor) : 0;
|
double stress = onTwoBogeys ? bogeySpacing - leadingAnchor.distanceTo(trailingAnchor) : 0;
|
||||||
|
blocked = false;
|
||||||
|
|
||||||
// positive stress: points should move apart
|
// positive stress: points should move apart
|
||||||
// negative stress: points should move closer
|
// negative stress: points should move closer
|
||||||
|
@ -65,7 +74,7 @@ public class Carriage {
|
||||||
double leadingPointModifier = 0.5d;
|
double leadingPointModifier = 0.5d;
|
||||||
double trailingPointModifier = -0.5d;
|
double trailingPointModifier = -0.5d;
|
||||||
|
|
||||||
MutableObject<MovingPoint> previous = new MutableObject<>();
|
MutableObject<TravellingPoint> previous = new MutableObject<>();
|
||||||
MutableDouble distanceMoved = new MutableDouble(distance);
|
MutableDouble distanceMoved = new MutableDouble(distance);
|
||||||
|
|
||||||
bogeys.forEachWithContext((bogey, firstBogey) -> {
|
bogeys.forEachWithContext((bogey, firstBogey) -> {
|
||||||
|
@ -76,15 +85,16 @@ public class Carriage {
|
||||||
double bogeyStress = bogey.getStress();
|
double bogeyStress = bogey.getStress();
|
||||||
|
|
||||||
bogey.points.forEachWithContext((point, first) -> {
|
bogey.points.forEachWithContext((point, first) -> {
|
||||||
MovingPoint prevPoint = previous.getValue();
|
TravellingPoint prevPoint = previous.getValue();
|
||||||
ITrackSelector trackSelector =
|
ITrackSelector trackSelector =
|
||||||
prevPoint == null ? control == null ? point.random() : control.apply(point)
|
prevPoint == null ? control == null ? point.random() : control.apply(point)
|
||||||
: point.follow(prevPoint);
|
: point.follow(prevPoint);
|
||||||
|
|
||||||
double correction = bogeyStress * (first ? leadingPointModifier : trailingPointModifier);
|
double correction = bogeyStress * (first ? leadingPointModifier : trailingPointModifier);
|
||||||
double toMove = distanceMoved.getValue();
|
double toMove = distanceMoved.getValue();
|
||||||
double moved = point.travel(toMove, trackSelector);
|
double moved = point.travel(graph, toMove, trackSelector);
|
||||||
point.travel(correction + bogeyCorrection, trackSelector);
|
point.travel(graph, correction + bogeyCorrection, trackSelector);
|
||||||
|
blocked |= point.blocked;
|
||||||
|
|
||||||
distanceMoved.setValue(moved);
|
distanceMoved.setValue(moved);
|
||||||
previous.setValue(point);
|
previous.setValue(point);
|
||||||
|
@ -158,11 +168,11 @@ public class Carriage {
|
||||||
entity.discard();
|
entity.discard();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MovingPoint getLeadingPoint() {
|
public TravellingPoint getLeadingPoint() {
|
||||||
return leadingBogey().leading();
|
return leadingBogey().leading();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MovingPoint getTrailingPoint() {
|
public TravellingPoint getTrailingPoint() {
|
||||||
return trailingBogey().trailing();
|
return trailingBogey().trailing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,8 +190,9 @@ public class Carriage {
|
||||||
|
|
||||||
public static class CarriageBogey {
|
public static class CarriageBogey {
|
||||||
|
|
||||||
|
Carriage carriage;
|
||||||
IBogeyBlock type;
|
IBogeyBlock type;
|
||||||
Couple<MovingPoint> points;
|
Couple<TravellingPoint> points;
|
||||||
Vec3 anchorPosition;
|
Vec3 anchorPosition;
|
||||||
|
|
||||||
LerpedFloat wheelAngle;
|
LerpedFloat wheelAngle;
|
||||||
|
@ -191,13 +202,16 @@ public class Carriage {
|
||||||
public Vec3 leadingCouplingAnchor;
|
public Vec3 leadingCouplingAnchor;
|
||||||
public Vec3 trailingCouplingAnchor;
|
public Vec3 trailingCouplingAnchor;
|
||||||
|
|
||||||
public CarriageBogey(IBogeyBlock type, MovingPoint point, MovingPoint point2) {
|
int derailAngle;
|
||||||
|
|
||||||
|
public CarriageBogey(IBogeyBlock type, TravellingPoint point, TravellingPoint point2) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
points = Couple.create(point, point2);
|
points = Couple.create(point, point2);
|
||||||
wheelAngle = LerpedFloat.angular();
|
wheelAngle = LerpedFloat.angular();
|
||||||
yaw = LerpedFloat.angular();
|
yaw = LerpedFloat.angular();
|
||||||
pitch = LerpedFloat.angular();
|
pitch = LerpedFloat.angular();
|
||||||
updateAnchorPosition();
|
updateAnchorPosition();
|
||||||
|
derailAngle = Create.RANDOM.nextInt(90) - 45;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateAngles(double distanceMoved) {
|
public void updateAngles(double distanceMoved) {
|
||||||
|
@ -209,16 +223,20 @@ public class Carriage {
|
||||||
double diffZ = positionVec.z - coupledVec.z;
|
double diffZ = positionVec.z - coupledVec.z;
|
||||||
float yRot = AngleHelper.deg(Mth.atan2(diffZ, diffX)) + 90;
|
float yRot = AngleHelper.deg(Mth.atan2(diffZ, diffX)) + 90;
|
||||||
float xRot = AngleHelper.deg(Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ)));
|
float xRot = AngleHelper.deg(Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ)));
|
||||||
|
|
||||||
|
if (carriage.train.derailed)
|
||||||
|
yRot += derailAngle;
|
||||||
|
|
||||||
wheelAngle.setValue((wheelAngle.getValue() - angleDiff) % 360);
|
wheelAngle.setValue((wheelAngle.getValue() - angleDiff) % 360);
|
||||||
pitch.setValue(xRot);
|
pitch.setValue(xRot);
|
||||||
yaw.setValue(-yRot);
|
yaw.setValue(-yRot);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MovingPoint leading() {
|
public TravellingPoint leading() {
|
||||||
return points.getFirst();
|
return points.getFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MovingPoint trailing() {
|
public TravellingPoint trailing() {
|
||||||
return points.getSecond();
|
return points.getSecond();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,16 +258,6 @@ public class Carriage {
|
||||||
Vec3 thisOffset = type.getConnectorAnchorOffset();
|
Vec3 thisOffset = type.getConnectorAnchorOffset();
|
||||||
thisOffset = thisOffset.multiply(1, 1, leading ? -1 : 1);
|
thisOffset = thisOffset.multiply(1, 1, leading ? -1 : 1);
|
||||||
|
|
||||||
// msr.rotateY(viewYRot + 90)
|
|
||||||
// .rotateX(-viewXRot)
|
|
||||||
// .rotateY(180)
|
|
||||||
// .translate(0, 0, first ? 0 : -bogeySpacing)
|
|
||||||
// .rotateY(-180)
|
|
||||||
// .rotateX(viewXRot)
|
|
||||||
// .rotateY(-viewYRot - 90)
|
|
||||||
// .rotateY(bogey.yaw.getValue(partialTicks))
|
|
||||||
// .rotateX(bogey.pitch.getValue(partialTicks))
|
|
||||||
|
|
||||||
thisOffset = VecHelper.rotate(thisOffset, pitch.getValue(partialTicks), Axis.X);
|
thisOffset = VecHelper.rotate(thisOffset, pitch.getValue(partialTicks), Axis.X);
|
||||||
thisOffset = VecHelper.rotate(thisOffset, yaw.getValue(partialTicks), Axis.Y);
|
thisOffset = VecHelper.rotate(thisOffset, yaw.getValue(partialTicks), Axis.Y);
|
||||||
thisOffset = VecHelper.rotate(thisOffset, -entityYRot - 90, Axis.Y);
|
thisOffset = VecHelper.rotate(thisOffset, -entityYRot - 90, Axis.Y);
|
||||||
|
|
|
@ -3,7 +3,9 @@ package com.simibubi.create.content.logistics.trains.entity;
|
||||||
import com.simibubi.create.AllEntityTypes;
|
import com.simibubi.create.AllEntityTypes;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
import net.minecraft.core.particles.ParticleTypes;
|
||||||
import net.minecraft.world.entity.EntityType;
|
import net.minecraft.world.entity.EntityType;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
@ -44,13 +46,29 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
||||||
xo = getX();
|
xo = getX();
|
||||||
yo = getY();
|
yo = getY();
|
||||||
zo = getZ();
|
zo = getZ();
|
||||||
|
|
||||||
carriage.moveEntity(this);
|
carriage.moveEntity(this);
|
||||||
|
|
||||||
double distanceTo = position().distanceTo(new Vec3(xo, yo, zo));
|
double distanceTo = position().distanceTo(new Vec3(xo, yo, zo));
|
||||||
carriage.bogeys.getFirst()
|
carriage.bogeys.getFirst()
|
||||||
.updateAngles(distanceTo);
|
.updateAngles(distanceTo);
|
||||||
if (carriage.isOnTwoBogeys())
|
if (carriage.isOnTwoBogeys())
|
||||||
carriage.bogeys.getSecond()
|
carriage.bogeys.getSecond()
|
||||||
.updateAngles(distanceTo);
|
.updateAngles(distanceTo);
|
||||||
|
|
||||||
|
if (carriage.train.derailed)
|
||||||
|
spawnDerailParticles(carriage);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3 derailParticleOffset = VecHelper.offsetRandomly(Vec3.ZERO, Create.RANDOM, 1.5f)
|
||||||
|
.multiply(1, .25f, 1);
|
||||||
|
|
||||||
|
private void spawnDerailParticles(Carriage carriage) {
|
||||||
|
if (random.nextFloat() < 1 / 20f) {
|
||||||
|
Vec3 v = position().add(derailParticleOffset);
|
||||||
|
level.addParticle(ParticleTypes.CAMPFIRE_COSY_SMOKE, v.x, v.y, v.z, 0, .04, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -13,7 +13,7 @@ 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.TrackNodeLocation;
|
||||||
import com.simibubi.create.content.logistics.trains.entity.MovingPoint.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.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
import com.simibubi.create.foundation.utility.Pair;
|
import com.simibubi.create.foundation.utility.Pair;
|
||||||
|
@ -24,18 +24,14 @@ import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
public class Navigation {
|
public class Navigation {
|
||||||
|
|
||||||
TrackGraph graph;
|
|
||||||
Train train;
|
Train train;
|
||||||
|
|
||||||
public GlobalStation destination;
|
public GlobalStation destination;
|
||||||
public double distanceToDestination;
|
public double distanceToDestination;
|
||||||
|
List<TrackEdge> currentPath;
|
||||||
List<TrackEdge> path;
|
|
||||||
|
|
||||||
public Navigation(Train train, TrackGraph graph) {
|
public Navigation(Train train, TrackGraph graph) {
|
||||||
this.train = train;
|
this.train = train;
|
||||||
this.graph = graph;
|
currentPath = new ArrayList<>();
|
||||||
path = new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tick(Level level) {
|
public void tick(Level level) {
|
||||||
|
@ -47,7 +43,7 @@ public class Navigation {
|
||||||
if (distanceToDestination < 1 / 32f) {
|
if (distanceToDestination < 1 / 32f) {
|
||||||
distanceToDestination = 0;
|
distanceToDestination = 0;
|
||||||
train.speed = 0;
|
train.speed = 0;
|
||||||
path.clear();
|
currentPath.clear();
|
||||||
train.arriveAt(destination);
|
train.arriveAt(destination);
|
||||||
destination = null;
|
destination = null;
|
||||||
return;
|
return;
|
||||||
|
@ -83,13 +79,13 @@ public class Navigation {
|
||||||
return destination != null;
|
return destination != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITrackSelector control(MovingPoint mp) {
|
public ITrackSelector control(TravellingPoint mp) {
|
||||||
return list -> {
|
return (graph, list) -> {
|
||||||
if (!path.isEmpty()) {
|
if (!currentPath.isEmpty()) {
|
||||||
TrackEdge target = path.get(0);
|
TrackEdge target = currentPath.get(0);
|
||||||
for (Entry<TrackNode, TrackEdge> entry : list) {
|
for (Entry<TrackNode, TrackEdge> entry : list) {
|
||||||
if (entry.getValue() == target) {
|
if (entry.getValue() == target) {
|
||||||
path.remove(0);
|
currentPath.remove(0);
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,30 +96,50 @@ public class Navigation {
|
||||||
|
|
||||||
public void cancelNavigation() {
|
public void cancelNavigation() {
|
||||||
distanceToDestination = 0;
|
distanceToDestination = 0;
|
||||||
path.clear();
|
currentPath.clear();
|
||||||
if (destination == null)
|
if (destination == null)
|
||||||
return;
|
return;
|
||||||
destination.cancelReservation(train);
|
destination.cancelReservation(train);
|
||||||
|
destination = null;
|
||||||
|
train.runtime.transitInterrupted();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDestination(GlobalStation destination) {
|
public double startNavigation(GlobalStation destination, boolean simulate) {
|
||||||
findPathTo(destination);
|
Pair<Double, List<TrackEdge>> pathTo = findPathTo(destination);
|
||||||
if (distanceToDestination == 0)
|
|
||||||
return;
|
if (simulate)
|
||||||
|
return pathTo.getFirst();
|
||||||
|
|
||||||
|
distanceToDestination = pathTo.getFirst();
|
||||||
|
currentPath = pathTo.getSecond();
|
||||||
|
if (distanceToDestination == -1) {
|
||||||
|
distanceToDestination = 0;
|
||||||
|
if (this.destination != null)
|
||||||
|
cancelNavigation();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.destination == destination)
|
if (this.destination == destination)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
train.leave();
|
train.leave();
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
|
return distanceToDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void findPathTo(GlobalStation destination) {
|
private Pair<Double, List<TrackEdge>> findPathTo(GlobalStation destination) {
|
||||||
path.clear();
|
TrackGraph graph = train.graph;
|
||||||
this.distanceToDestination = 0;
|
List<TrackEdge> path = new ArrayList<>();
|
||||||
|
double distanceToDestination = 0;
|
||||||
|
|
||||||
|
if (graph == null)
|
||||||
|
return Pair.of(-1d, path);
|
||||||
|
|
||||||
Couple<TrackNodeLocation> target = destination.edgeLocation;
|
Couple<TrackNodeLocation> target = destination.edgeLocation;
|
||||||
PriorityQueue<Pair<Double, Pair<Couple<TrackNode>, TrackEdge>>> frontier =
|
PriorityQueue<Pair<Double, Pair<Couple<TrackNode>, TrackEdge>>> frontier =
|
||||||
new PriorityQueue<>((p1, p2) -> Double.compare(p1.getFirst(), p2.getFirst()));
|
new PriorityQueue<>((p1, p2) -> Double.compare(p1.getFirst(), p2.getFirst()));
|
||||||
|
|
||||||
MovingPoint leadingPoint = train.carriages.get(0)
|
TravellingPoint leadingPoint = train.carriages.get(0)
|
||||||
.getLeadingPoint();
|
.getLeadingPoint();
|
||||||
Set<TrackEdge> visited = new HashSet<>();
|
Set<TrackEdge> visited = new HashSet<>();
|
||||||
Map<TrackEdge, Pair<Boolean, TrackEdge>> reachedVia = new IdentityHashMap<>();
|
Map<TrackEdge, Pair<Boolean, TrackEdge>> reachedVia = new IdentityHashMap<>();
|
||||||
|
@ -167,7 +183,7 @@ public class Navigation {
|
||||||
else
|
else
|
||||||
distanceToDestination += train.getTotalLength() + 2;
|
distanceToDestination += train.getTotalLength() + 2;
|
||||||
distanceToDestination -= position;
|
distanceToDestination -= position;
|
||||||
return;
|
return Pair.of(distanceToDestination, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Entry<TrackNode, TrackEdge> entry : graph.getConnectionsFrom(node2)
|
for (Entry<TrackNode, TrackEdge> entry : graph.getConnectionsFrom(node2)
|
||||||
|
@ -194,6 +210,8 @@ public class Navigation {
|
||||||
Pair.of(Couple.create(node2, newNode), newEdge)));
|
Pair.of(Couple.create(node2, newNode), newEdge)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Pair.of(-1d, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,37 @@
|
||||||
package com.simibubi.create.content.logistics.trains.entity;
|
package com.simibubi.create.content.logistics.trains.entity;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.CreateClient;
|
import com.simibubi.create.CreateClient;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||||
import com.simibubi.create.content.logistics.trains.entity.MovingPoint.ITrackSelector;
|
import com.simibubi.create.content.logistics.trains.TrackNode;
|
||||||
|
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.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.foundation.utility.Lang;
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
|
@ -28,28 +44,37 @@ public class Train {
|
||||||
public double targetSpeed = 0;
|
public double targetSpeed = 0;
|
||||||
|
|
||||||
public UUID id;
|
public UUID id;
|
||||||
|
public UUID owner;
|
||||||
public TrackGraph graph;
|
public TrackGraph graph;
|
||||||
public Navigation navigation;
|
public Navigation navigation;
|
||||||
public GlobalStation currentStation;
|
|
||||||
public ScheduleRuntime runtime;
|
public ScheduleRuntime runtime;
|
||||||
public TrainIconType icon;
|
public TrainIconType icon;
|
||||||
public Component name;
|
public Component name;
|
||||||
|
public TrainStatus status;
|
||||||
|
|
||||||
|
public UUID currentStation;
|
||||||
|
|
||||||
public boolean heldForAssembly;
|
public boolean heldForAssembly;
|
||||||
public boolean doubleEnded;
|
public boolean doubleEnded;
|
||||||
public List<Carriage> carriages;
|
public List<Carriage> carriages;
|
||||||
public List<Integer> carriageSpacing;
|
public List<Integer> carriageSpacing;
|
||||||
|
|
||||||
|
List<TrainMigration> migratingPoints;
|
||||||
|
public int migrationCooldown;
|
||||||
|
public boolean derailed;
|
||||||
|
|
||||||
double[] stress;
|
double[] stress;
|
||||||
|
|
||||||
public Train(UUID id, TrackGraph graph, List<Carriage> carriages, List<Integer> carriageSpacing) {
|
public Train(UUID id, UUID owner, TrackGraph graph, List<Carriage> carriages, List<Integer> carriageSpacing) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.owner = owner;
|
||||||
this.graph = graph;
|
this.graph = graph;
|
||||||
this.carriages = carriages;
|
this.carriages = carriages;
|
||||||
this.carriageSpacing = carriageSpacing;
|
this.carriageSpacing = carriageSpacing;
|
||||||
this.icon = TrainIconType.getDefault();
|
this.icon = TrainIconType.getDefault();
|
||||||
this.stress = new double[carriageSpacing.size()];
|
this.stress = new double[carriageSpacing.size()];
|
||||||
this.name = Lang.translate("train.unnamed");
|
this.name = Lang.translate("train.unnamed");
|
||||||
|
this.status = new TrainStatus(this);
|
||||||
|
|
||||||
carriages.forEach(c -> {
|
carriages.forEach(c -> {
|
||||||
c.setTrain(this);
|
c.setTrain(this);
|
||||||
|
@ -60,12 +85,28 @@ public class Train {
|
||||||
navigation = new Navigation(this, graph);
|
navigation = new Navigation(this, graph);
|
||||||
runtime = new ScheduleRuntime(this);
|
runtime = new ScheduleRuntime(this);
|
||||||
heldForAssembly = true;
|
heldForAssembly = true;
|
||||||
|
migratingPoints = new ArrayList<>();
|
||||||
|
currentStation = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tick(Level level) {
|
public void tick(Level level) {
|
||||||
|
status.tick(level);
|
||||||
|
|
||||||
|
if (graph == null) {
|
||||||
|
if (!migratingPoints.isEmpty())
|
||||||
|
reattachToTracks(level);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
runtime.tick(level);
|
runtime.tick(level);
|
||||||
navigation.tick(level);
|
navigation.tick(level);
|
||||||
|
|
||||||
|
if (navigation.destination == null && speed > 0) {
|
||||||
|
speed -= acceleration;
|
||||||
|
if (speed <= 0)
|
||||||
|
speed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
double distance = speed;
|
double distance = speed;
|
||||||
Carriage previousCarriage = null;
|
Carriage previousCarriage = null;
|
||||||
|
|
||||||
|
@ -88,27 +129,38 @@ public class Train {
|
||||||
double leadingModifier = approachingStation ? -0.75d : -0.5d;
|
double leadingModifier = approachingStation ? -0.75d : -0.5d;
|
||||||
double trailingModifier = approachingStation ? 0d : 0.125d;
|
double trailingModifier = approachingStation ? 0d : 0.125d;
|
||||||
|
|
||||||
MovingPoint previous = null;
|
TravellingPoint previous = null;
|
||||||
|
boolean blocked = false;
|
||||||
|
|
||||||
for (int i = 0; i < carriages.size(); i++) {
|
for (int i = 0; i < carriages.size(); i++) {
|
||||||
double leadingStress = i == 0 ? 0 : stress[i - 1] * leadingModifier;
|
double leadingStress = i == 0 ? 0 : stress[i - 1] * leadingModifier;
|
||||||
double trailingStress = i == stress.length ? 0 : stress[i] * trailingModifier;
|
double trailingStress = i == stress.length ? 0 : stress[i] * trailingModifier;
|
||||||
|
|
||||||
Carriage carriage = carriages.get(i);
|
Carriage carriage = carriages.get(i);
|
||||||
MovingPoint toFollow = previous;
|
TravellingPoint toFollow = previous;
|
||||||
Function<MovingPoint, ITrackSelector> control =
|
Function<TravellingPoint, ITrackSelector> control =
|
||||||
previous == null ? navigation::control : mp -> mp.follow(toFollow);
|
previous == null ? navigation::control : mp -> mp.follow(toFollow);
|
||||||
double actualDistance = carriage.travel(level, distance + leadingStress + trailingStress, control);
|
double actualDistance = carriage.travel(level, graph, distance + leadingStress + trailingStress, control);
|
||||||
|
blocked |= carriage.blocked;
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
distance = actualDistance;
|
distance = actualDistance;
|
||||||
previous = carriage.getTrailingPoint();
|
previous = carriage.getTrailingPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (blocked) {
|
||||||
|
speed = 0;
|
||||||
|
navigation.cancelNavigation();
|
||||||
|
runtime.tick(level);
|
||||||
|
status.endOfTrack();
|
||||||
|
} else if (speed > 0)
|
||||||
|
status.trackOK();
|
||||||
|
|
||||||
if (navigation.destination != null) {
|
if (navigation.destination != null) {
|
||||||
boolean recalculate = navigation.distanceToDestination > 20;
|
boolean recalculate = navigation.distanceToDestination % 100 > 20;
|
||||||
navigation.distanceToDestination -= distance;
|
navigation.distanceToDestination -= distance;
|
||||||
if (recalculate && navigation.distanceToDestination <= 20)
|
if (recalculate && navigation.distanceToDestination % 100 <= 20)
|
||||||
navigation.setDestination(navigation.destination);
|
navigation.startNavigation(navigation.destination, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,14 +193,87 @@ public class Train {
|
||||||
offset += carriageSpacing.get(i);
|
offset += carriageSpacing.get(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GlobalStation currentStation = getCurrentStation();
|
||||||
if (currentStation != null)
|
if (currentStation != null)
|
||||||
currentStation.cancelReservation(this);
|
currentStation.cancelReservation(this);
|
||||||
|
|
||||||
Create.RAILWAYS.trains.remove(id);
|
Create.RAILWAYS.trains.remove(id);
|
||||||
CreateClient.RAILWAYS.trains.remove(id);
|
CreateClient.RAILWAYS.trains.remove(id); // TODO Thread breach
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTravellingOn(TrackNode node) {
|
||||||
|
MutableBoolean affected = new MutableBoolean(false);
|
||||||
|
forEachTravellingPoint(tp -> {
|
||||||
|
if (tp.node1 == node || tp.node2 == node)
|
||||||
|
affected.setTrue();
|
||||||
|
});
|
||||||
|
return affected.booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void detachFromTracks() {
|
||||||
|
migratingPoints.clear();
|
||||||
|
navigation.cancelNavigation();
|
||||||
|
forEachTravellingPoint(tp -> migratingPoints.add(new TrainMigration(tp)));
|
||||||
|
graph = null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void forEachTravellingPoint(Consumer<TravellingPoint> callback) {
|
||||||
|
for (Carriage c : carriages) {
|
||||||
|
c.leadingBogey().points.forEach(callback::accept);
|
||||||
|
if (c.isOnTwoBogeys())
|
||||||
|
c.trailingBogey().points.forEach(callback::accept);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reattachToTracks(Level level) {
|
||||||
|
if (migrationCooldown > 0) {
|
||||||
|
migrationCooldown--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Entry<UUID, TrackGraph>> entrySet = new HashSet<>(Create.RAILWAYS.trackNetworks.entrySet());
|
||||||
|
Map<UUID, List<GraphLocation>> successfulMigrations = new HashMap<>();
|
||||||
|
for (TrainMigration md : migratingPoints) {
|
||||||
|
for (Iterator<Entry<UUID, TrackGraph>> iterator = entrySet.iterator(); iterator.hasNext();) {
|
||||||
|
Entry<UUID, TrackGraph> entry = iterator.next();
|
||||||
|
GraphLocation gl = md.tryMigratingTo(entry.getValue());
|
||||||
|
if (gl == null) {
|
||||||
|
iterator.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
successfulMigrations.computeIfAbsent(entry.getKey(), uuid -> new ArrayList<>())
|
||||||
|
.add(gl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entrySet.isEmpty()) {
|
||||||
|
migrationCooldown = 40;
|
||||||
|
status.failedMigration();
|
||||||
|
derailed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Entry<UUID, TrackGraph> entry : entrySet) {
|
||||||
|
graph = entry.getValue();
|
||||||
|
List<GraphLocation> locations = successfulMigrations.get(entry.getKey());
|
||||||
|
forEachTravellingPoint(tp -> tp.migrateTo(locations));
|
||||||
|
migratingPoints.clear();
|
||||||
|
if (derailed)
|
||||||
|
status.successfulMigration();
|
||||||
|
derailed = false;
|
||||||
|
if (runtime.getSchedule() != null) {
|
||||||
|
if (runtime.state == State.IN_TRANSIT)
|
||||||
|
runtime.state = State.PRE_TRANSIT;
|
||||||
|
}
|
||||||
|
GlobalStation currentStation = getCurrentStation();
|
||||||
|
if (currentStation != null)
|
||||||
|
currentStation.reserveFor(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int getTotalLength() {
|
public int getTotalLength() {
|
||||||
int length = 0;
|
int length = 0;
|
||||||
for (int i = 0; i < carriages.size(); i++) {
|
for (int i = 0; i < carriages.size(); i++) {
|
||||||
|
@ -160,13 +285,38 @@ public class Train {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void leave() {
|
public void leave() {
|
||||||
|
GlobalStation currentStation = getCurrentStation();
|
||||||
|
if (currentStation == null)
|
||||||
|
return;
|
||||||
currentStation.trainDeparted(this);
|
currentStation.trainDeparted(this);
|
||||||
currentStation = null;
|
this.currentStation = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void arriveAt(GlobalStation station) {
|
public void arriveAt(GlobalStation station) {
|
||||||
currentStation = station;
|
setCurrentStation(station);
|
||||||
runtime.destinationReached();
|
runtime.destinationReached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCurrentStation(GlobalStation station) {
|
||||||
|
currentStation = station.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlobalStation getCurrentStation() {
|
||||||
|
if (currentStation == null)
|
||||||
|
return null;
|
||||||
|
if (graph == null)
|
||||||
|
return null;
|
||||||
|
return graph.getStation(currentStation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public LivingEntity getOwner(Level level) {
|
||||||
|
try {
|
||||||
|
UUID uuid = owner;
|
||||||
|
return uuid == null ? null : level.getPlayerByUUID(uuid);
|
||||||
|
} catch (IllegalArgumentException illegalargumentexception) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.entity;
|
||||||
|
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
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.GraphLocation;
|
||||||
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
|
class TrainMigration {
|
||||||
|
Couple<TrackNodeLocation> locations;
|
||||||
|
double positionOnOldEdge;
|
||||||
|
boolean curve;
|
||||||
|
Vec3 fallback;
|
||||||
|
|
||||||
|
public TrainMigration(TravellingPoint point) {
|
||||||
|
double t = point.position / point.edge.getLength(point.node1, point.node2);
|
||||||
|
fallback = point.edge.getPosition(point.node1, point.node2, t);
|
||||||
|
curve = point.edge.isTurn();
|
||||||
|
positionOnOldEdge = point.position;
|
||||||
|
locations = Couple.create(point.node1.getLocation(), point.node2.getLocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
public GraphLocation 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) {
|
||||||
|
GraphLocation graphLocation = new GraphLocation();
|
||||||
|
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(newNode1, newNode2, 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(newNode1, newNode2);
|
||||||
|
double position = intersectSphere.distanceTo(nodeVec) - radius;
|
||||||
|
if (Double.isNaN(position))
|
||||||
|
continue;
|
||||||
|
if (position < 0)
|
||||||
|
continue;
|
||||||
|
if (position > edgeLength)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
GraphLocation graphLocation = new GraphLocation();
|
||||||
|
graphLocation.graph = graph;
|
||||||
|
graphLocation.edge = Couple.create(loc, newNode2.getLocation());
|
||||||
|
graphLocation.position = position;
|
||||||
|
return graphLocation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.entity;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
|
public class TrainStatus {
|
||||||
|
|
||||||
|
Train train;
|
||||||
|
|
||||||
|
boolean navigation;
|
||||||
|
boolean track;
|
||||||
|
|
||||||
|
List<Component> queued = new ArrayList<>();
|
||||||
|
|
||||||
|
public TrainStatus(Train train) {
|
||||||
|
this.train = train;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void failedNavigation() {
|
||||||
|
if (navigation)
|
||||||
|
return;
|
||||||
|
displayInformation("Unable to find Path to next Scheduled destination", false);
|
||||||
|
navigation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void successfulNavigation() {
|
||||||
|
if (!navigation)
|
||||||
|
return;
|
||||||
|
displayInformation("Navigation succeeded", true);
|
||||||
|
navigation = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void failedMigration() {
|
||||||
|
if (track)
|
||||||
|
return;
|
||||||
|
displayInformation("Tracks are missing beneath the Train", false);
|
||||||
|
track = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endOfTrack() {
|
||||||
|
if (track)
|
||||||
|
return;
|
||||||
|
displayInformation("A Carriage has reached the end of its Track.", false);
|
||||||
|
track = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void successfulMigration() {
|
||||||
|
if (!track)
|
||||||
|
return;
|
||||||
|
displayInformation("Train is back on Track", true);
|
||||||
|
track = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void trackOK() {
|
||||||
|
track = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick(Level level) {
|
||||||
|
if (queued.isEmpty())
|
||||||
|
return;
|
||||||
|
LivingEntity owner = train.getOwner(level);
|
||||||
|
if (owner == null)
|
||||||
|
return;
|
||||||
|
if (owner instanceof Player player) {
|
||||||
|
// TODO change to Lang.translate
|
||||||
|
player.displayClientMessage(new TextComponent("<i> Information about Train: ").append(train.name)
|
||||||
|
.withStyle(ChatFormatting.GOLD), false);
|
||||||
|
queued.forEach(c -> player.displayClientMessage(c, false));
|
||||||
|
}
|
||||||
|
queued.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void displayInformation(String key, boolean itsAGoodThing, Object... args) {
|
||||||
|
queued.add(new TextComponent(" - ").withStyle(ChatFormatting.GRAY)
|
||||||
|
.append(new TextComponent(key).withStyle(st -> st.withColor(itsAGoodThing ? 0xD5ECC2 : 0xFFD3B4))));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,21 +6,22 @@ import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.util.function.Function;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
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.management.GraphLocation;
|
||||||
|
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
public class MovingPoint {
|
public class TravellingPoint {
|
||||||
|
|
||||||
TrackGraph graph;
|
|
||||||
TrackNode node1, node2;
|
TrackNode node1, node2;
|
||||||
TrackEdge edge;
|
TrackEdge edge;
|
||||||
double position;
|
double position;
|
||||||
|
boolean blocked;
|
||||||
|
|
||||||
public static enum SteerDirection {
|
public static enum SteerDirection {
|
||||||
NONE(0), LEFT(-1), RIGHT(1);
|
NONE(0), LEFT(-1), RIGHT(1);
|
||||||
|
@ -33,11 +34,10 @@ public class MovingPoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface ITrackSelector
|
public static interface ITrackSelector
|
||||||
extends Function<List<Entry<TrackNode, TrackEdge>>, Entry<TrackNode, TrackEdge>> {
|
extends BiFunction<TrackGraph, List<Entry<TrackNode, TrackEdge>>, Entry<TrackNode, TrackEdge>> {
|
||||||
};
|
};
|
||||||
|
|
||||||
public MovingPoint(TrackGraph graph, TrackNode node1, TrackNode node2, TrackEdge edge, double position) {
|
public TravellingPoint(TrackNode node1, TrackNode node2, TrackEdge edge, double position) {
|
||||||
this.graph = graph;
|
|
||||||
this.node1 = node1;
|
this.node1 = node1;
|
||||||
this.node2 = node2;
|
this.node2 = node2;
|
||||||
this.edge = edge;
|
this.edge = edge;
|
||||||
|
@ -45,11 +45,11 @@ public class MovingPoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITrackSelector random() {
|
public ITrackSelector random() {
|
||||||
return validTargets -> validTargets.get(Create.RANDOM.nextInt(validTargets.size()));
|
return (graph, validTargets) -> validTargets.get(Create.RANDOM.nextInt(validTargets.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITrackSelector follow(MovingPoint other) {
|
public ITrackSelector follow(TravellingPoint other) {
|
||||||
return validTargets -> {
|
return (graph, validTargets) -> {
|
||||||
TrackNode target = other.node1;
|
TrackNode target = other.node1;
|
||||||
|
|
||||||
for (Entry<TrackNode, TrackEdge> entry : validTargets)
|
for (Entry<TrackNode, TrackEdge> entry : validTargets)
|
||||||
|
@ -99,7 +99,7 @@ public class MovingPoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITrackSelector steer(SteerDirection direction, Vec3 upNormal) {
|
public ITrackSelector steer(SteerDirection direction, Vec3 upNormal) {
|
||||||
return validTargets -> {
|
return (graph, validTargets) -> {
|
||||||
double closest = Double.MAX_VALUE;
|
double closest = Double.MAX_VALUE;
|
||||||
Entry<TrackNode, TrackEdge> best = null;
|
Entry<TrackNode, TrackEdge> best = null;
|
||||||
|
|
||||||
|
@ -126,13 +126,13 @@ public class MovingPoint {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public double travel(double distance, ITrackSelector trackSelector) {
|
public double travel(TrackGraph graph, double distance, ITrackSelector trackSelector) {
|
||||||
|
blocked = false;
|
||||||
double edgeLength = edge.getLength(node1, node2);
|
double edgeLength = edge.getLength(node1, node2);
|
||||||
if (distance == 0)
|
if (distance == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
double traveled = distance;
|
double traveled = distance;
|
||||||
|
|
||||||
double currentT = position / edgeLength;
|
double currentT = position / edgeLength;
|
||||||
double incrementT = edge.incrementT(node1, node2, currentT, distance);
|
double incrementT = edge.incrementT(node1, node2, currentT, distance);
|
||||||
position = incrementT * edgeLength;
|
position = incrementT * edgeLength;
|
||||||
|
@ -159,11 +159,12 @@ public class MovingPoint {
|
||||||
if (validTargets.isEmpty()) {
|
if (validTargets.isEmpty()) {
|
||||||
traveled -= position - edgeLength;
|
traveled -= position - edgeLength;
|
||||||
position = edgeLength;
|
position = edgeLength;
|
||||||
|
blocked = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry<TrackNode, TrackEdge> entry =
|
Entry<TrackNode, TrackEdge> entry =
|
||||||
validTargets.size() == 1 ? validTargets.get(0) : trackSelector.apply(validTargets);
|
validTargets.size() == 1 ? validTargets.get(0) : trackSelector.apply(graph, validTargets);
|
||||||
|
|
||||||
node1 = node2;
|
node1 = node2;
|
||||||
node2 = entry.getKey();
|
node2 = entry.getKey();
|
||||||
|
@ -175,7 +176,7 @@ public class MovingPoint {
|
||||||
return traveled;
|
return traveled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reverse() {
|
public void reverse(TrackGraph graph) {
|
||||||
TrackNode n = node1;
|
TrackNode n = node1;
|
||||||
node1 = node2;
|
node1 = node2;
|
||||||
node2 = n;
|
node2 = n;
|
||||||
|
@ -191,4 +192,14 @@ public class MovingPoint {
|
||||||
.scale(1));
|
.scale(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void migrateTo(List<GraphLocation> locations) {
|
||||||
|
GraphLocation location = locations.remove(0);
|
||||||
|
TrackGraph graph = location.graph;
|
||||||
|
node1 = graph.locateNode(location.edge.getFirst());
|
||||||
|
node2 = graph.locateNode(location.edge.getSecond());
|
||||||
|
position = location.position;
|
||||||
|
edge = graph.getConnectionsFrom(node1)
|
||||||
|
.get(node2);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -5,12 +5,9 @@ import java.util.UUID;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
|
||||||
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.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
import com.simibubi.create.foundation.utility.Debug;
|
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
@ -49,21 +46,18 @@ public class GlobalStation {
|
||||||
public void migrate(LevelAccessor level) {
|
public void migrate(LevelAccessor level) {
|
||||||
BlockEntity blockEntity = level.getBlockEntity(stationPos);
|
BlockEntity blockEntity = level.getBlockEntity(stationPos);
|
||||||
if (blockEntity instanceof StationTileEntity station) {
|
if (blockEntity instanceof StationTileEntity station) {
|
||||||
Debug.debugChat("Migrating Station " + name);
|
|
||||||
station.migrate(this);
|
station.migrate(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Create.LOGGER
|
|
||||||
.warn("Couldn't migrate Station: " + name + " to changed Graph because associated Tile wasn't loaded.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLocation(Couple<TrackNode> nodes, double position) {
|
public void setLocation(Couple<TrackNodeLocation> nodes, double position) {
|
||||||
this.edgeLocation = nodes.map(TrackNode::getLocation);
|
this.edgeLocation = nodes;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reserveFor(Train train) {
|
public void reserveFor(Train train) {
|
||||||
Train nearestTrain = this.nearestTrain.get();
|
Train nearestTrain = getNearestTrain();
|
||||||
if (nearestTrain == null
|
if (nearestTrain == null
|
||||||
|| nearestTrain.navigation.distanceToDestination > train.navigation.distanceToDestination)
|
|| nearestTrain.navigation.distanceToDestination > train.navigation.distanceToDestination)
|
||||||
this.nearestTrain = new WeakReference<>(train);
|
this.nearestTrain = new WeakReference<>(train);
|
||||||
|
@ -80,18 +74,18 @@ public class GlobalStation {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Train getPresentTrain() {
|
public Train getPresentTrain() {
|
||||||
Train nearestTrain = this.nearestTrain.get();
|
Train nearestTrain = getNearestTrain();
|
||||||
if (nearestTrain == null || nearestTrain.currentStation != this)
|
if (nearestTrain == null || nearestTrain.getCurrentStation() != this)
|
||||||
return null;
|
return null;
|
||||||
return nearestTrain;
|
return nearestTrain;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Train getImminentTrain() {
|
public Train getImminentTrain() {
|
||||||
Train nearestTrain = this.nearestTrain.get();
|
Train nearestTrain = getNearestTrain();
|
||||||
if (nearestTrain == null)
|
if (nearestTrain == null)
|
||||||
return nearestTrain;
|
return nearestTrain;
|
||||||
if (nearestTrain.currentStation == this)
|
if (nearestTrain.getCurrentStation() == this)
|
||||||
return nearestTrain;
|
return nearestTrain;
|
||||||
if (!nearestTrain.navigation.isActive())
|
if (!nearestTrain.navigation.isActive())
|
||||||
return null;
|
return null;
|
||||||
|
@ -100,6 +94,11 @@ public class GlobalStation {
|
||||||
return nearestTrain;
|
return nearestTrain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Train getNearestTrain() {
|
||||||
|
return this.nearestTrain.get();
|
||||||
|
}
|
||||||
|
|
||||||
public CompoundTag write() {
|
public CompoundTag write() {
|
||||||
CompoundTag nbt = new CompoundTag();
|
CompoundTag nbt = new CompoundTag();
|
||||||
nbt.putUUID("Id", id);
|
nbt.putUUID("Id", id);
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.management;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||||
|
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
|
||||||
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
|
||||||
|
public class GraphLocation {
|
||||||
|
|
||||||
|
public TrackGraph graph;
|
||||||
|
public Couple<TrackNodeLocation> edge;
|
||||||
|
public double position;
|
||||||
|
|
||||||
|
}
|
|
@ -15,17 +15,17 @@ import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
public class ScheduleRuntime {
|
public class ScheduleRuntime {
|
||||||
|
|
||||||
enum State {
|
public enum State {
|
||||||
PRE_TRANSIT, IN_TRANSIT, POST_TRANSIT
|
PRE_TRANSIT, IN_TRANSIT, POST_TRANSIT
|
||||||
}
|
}
|
||||||
|
|
||||||
Train train;
|
Train train;
|
||||||
Schedule schedule;
|
Schedule schedule;
|
||||||
|
|
||||||
boolean paused;
|
|
||||||
boolean isAutoSchedule;
|
boolean isAutoSchedule;
|
||||||
int currentEntry;
|
public boolean paused;
|
||||||
State state;
|
public int currentEntry;
|
||||||
|
public State state;
|
||||||
|
|
||||||
static final int INTERVAL = 40;
|
static final int INTERVAL = 40;
|
||||||
int cooldown;
|
int cooldown;
|
||||||
|
@ -51,6 +51,13 @@ public class ScheduleRuntime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void transitInterrupted() {
|
||||||
|
if (schedule == null || state != State.IN_TRANSIT)
|
||||||
|
return;
|
||||||
|
state = State.PRE_TRANSIT;
|
||||||
|
cooldown = 0;
|
||||||
|
}
|
||||||
|
|
||||||
public void tick(Level level) {
|
public void tick(Level level) {
|
||||||
if (schedule == null)
|
if (schedule == null)
|
||||||
return;
|
return;
|
||||||
|
@ -76,17 +83,18 @@ public class ScheduleRuntime {
|
||||||
|
|
||||||
GlobalStation nextStation = findNextStation();
|
GlobalStation nextStation = findNextStation();
|
||||||
if (nextStation == null) {
|
if (nextStation == null) {
|
||||||
|
train.status.failedNavigation();
|
||||||
cooldown = INTERVAL;
|
cooldown = INTERVAL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (nextStation == train.currentStation) {
|
train.status.successfulNavigation();
|
||||||
|
if (nextStation == train.getCurrentStation()) {
|
||||||
state = State.IN_TRANSIT;
|
state = State.IN_TRANSIT;
|
||||||
destinationReached();
|
destinationReached();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (train.navigation.startNavigation(nextStation, false) != -1)
|
||||||
train.navigation.setDestination(nextStation);
|
state = State.IN_TRANSIT;
|
||||||
state = State.IN_TRANSIT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tickConditions(Level level) {
|
public void tickConditions(Level level) {
|
||||||
|
@ -113,12 +121,25 @@ public class ScheduleRuntime {
|
||||||
public GlobalStation findNextStation() {
|
public GlobalStation findNextStation() {
|
||||||
ScheduleEntry entry = schedule.entries.get(currentEntry);
|
ScheduleEntry entry = schedule.entries.get(currentEntry);
|
||||||
ScheduleDestination destination = entry.destination;
|
ScheduleDestination destination = entry.destination;
|
||||||
|
|
||||||
if (destination instanceof FilteredDestination filtered) {
|
if (destination instanceof FilteredDestination filtered) {
|
||||||
|
String regex = filtered.nameFilter.replace("*", ".*");
|
||||||
|
GlobalStation best = null;
|
||||||
|
double bestCost = Double.MAX_VALUE;
|
||||||
for (GlobalStation globalStation : train.graph.getStations()) {
|
for (GlobalStation globalStation : train.graph.getStations()) {
|
||||||
if (globalStation.name.equals(filtered.nameFilter))
|
if (!globalStation.name.matches(regex))
|
||||||
return globalStation;
|
continue;
|
||||||
|
double cost = train.navigation.startNavigation(globalStation, true);
|
||||||
|
if (cost < 0)
|
||||||
|
continue;
|
||||||
|
if (cost > bestCost)
|
||||||
|
continue;
|
||||||
|
best = globalStation;
|
||||||
|
bestCost = cost;
|
||||||
}
|
}
|
||||||
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ public class StationEditPacket extends TileEntityConfigurationPacket<StationTile
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void applySettings(StationTileEntity te) {
|
protected void applySettings(ServerPlayer player, StationTileEntity te) {
|
||||||
Level level = te.getLevel();
|
Level level = te.getLevel();
|
||||||
BlockPos blockPos = te.getBlockPos();
|
BlockPos blockPos = te.getBlockPos();
|
||||||
BlockState blockState = level.getBlockState(blockPos);
|
BlockState blockState = level.getBlockState(blockPos);
|
||||||
|
@ -85,7 +86,7 @@ public class StationEditPacket extends TileEntityConfigurationPacket<StationTile
|
||||||
if (!isAssemblyMode)
|
if (!isAssemblyMode)
|
||||||
return;
|
return;
|
||||||
if (tryAssemble)
|
if (tryAssemble)
|
||||||
te.assemble();
|
te.assemble(player.getUUID());
|
||||||
else {
|
else {
|
||||||
if (disassembleAndEnterMode(te))
|
if (disassembleAndEnterMode(te))
|
||||||
te.refreshAssemblyInfo();
|
te.refreshAssemblyInfo();
|
||||||
|
@ -123,4 +124,7 @@ public class StationEditPacket extends TileEntityConfigurationPacket<StationTile
|
||||||
return te.tryEnterAssemblyMode();
|
return te.tryEnterAssemblyMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void applySettings(StationTileEntity te) {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ public class StationRenderer extends SafeTileEntityRenderer<StationTileEntity> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getViewDistance() {
|
public int getViewDistance() {
|
||||||
return 96;
|
return 96 * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,12 +167,12 @@ public class StationScreen extends AbstractStationScreen {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (train.navigation.destination != station && train.currentStation != station) {
|
if (train.navigation.destination != station && train.getCurrentStation() != station) {
|
||||||
leavingAnimation = 80;
|
leavingAnimation = 80;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
disassembleTrainButton.active = train.currentStation == station; // TODO te.canAssemble
|
disassembleTrainButton.active = train.getCurrentStation() == station; // TODO te.canAssemble
|
||||||
openScheduleButton.active = train.runtime.schedule != null;
|
openScheduleButton.active = train.runtime.schedule != null;
|
||||||
|
|
||||||
float f = (float) (train.navigation.distanceToDestination / 30f);
|
float f = (float) (train.navigation.distanceToDestination / 30f);
|
||||||
|
|
|
@ -20,12 +20,10 @@ import com.simibubi.create.content.logistics.trains.TrackPropagator;
|
||||||
import com.simibubi.create.content.logistics.trains.entity.Carriage;
|
import com.simibubi.create.content.logistics.trains.entity.Carriage;
|
||||||
import com.simibubi.create.content.logistics.trains.entity.Carriage.CarriageBogey;
|
import com.simibubi.create.content.logistics.trains.entity.Carriage.CarriageBogey;
|
||||||
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.MovingPoint;
|
|
||||||
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.TrackTargetingBehaviour.GraphLocation;
|
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint;
|
||||||
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.Debug;
|
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
import com.simibubi.create.foundation.utility.Lang;
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
import com.simibubi.create.foundation.utility.Pair;
|
import com.simibubi.create.foundation.utility.Pair;
|
||||||
|
@ -107,9 +105,6 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
toMigrate != null ? new GlobalStation(toMigrate) : new GlobalStation(id, worldPosition);
|
toMigrate != null ? new GlobalStation(toMigrate) : new GlobalStation(id, worldPosition);
|
||||||
globalStation.setLocation(loc.edge, loc.position);
|
globalStation.setLocation(loc.edge, loc.position);
|
||||||
loc.graph.addStation(globalStation);
|
loc.graph.addStation(globalStation);
|
||||||
|
|
||||||
if (toMigrate != null)
|
|
||||||
Debug.debugChat("Migrated Station " + globalStation.name);
|
|
||||||
toMigrate = null;
|
toMigrate = null;
|
||||||
setChanged();
|
setChanged();
|
||||||
|
|
||||||
|
@ -124,6 +119,7 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
super.read(tag, clientPacket);
|
super.read(tag, clientPacket);
|
||||||
if (tag.contains("ToMigrate"))
|
if (tag.contains("ToMigrate"))
|
||||||
toMigrate = tag.getCompound("ToMigrate");
|
toMigrate = tag.getCompound("ToMigrate");
|
||||||
|
renderBounds = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -312,7 +308,7 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
super.setRemovedNotDueToChunkUnload();
|
super.setRemovedNotDueToChunkUnload();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assemble() {
|
public void assemble(UUID playerUUID) {
|
||||||
refreshAssemblyInfo();
|
refreshAssemblyInfo();
|
||||||
|
|
||||||
if (bogeyLocations[0] != 0) {
|
if (bogeyLocations[0] != 0) {
|
||||||
|
@ -349,7 +345,7 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
pointOffsets.add(Double.valueOf(loc + .5 + bogeySize / 2));
|
pointOffsets.add(Double.valueOf(loc + .5 + bogeySize / 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MovingPoint> points = new ArrayList<>();
|
List<TravellingPoint> points = new ArrayList<>();
|
||||||
Vec3 directionVec = Vec3.atLowerCornerOf(assemblyDirection.getNormal());
|
Vec3 directionVec = Vec3.atLowerCornerOf(assemblyDirection.getNormal());
|
||||||
TrackGraph graph = null;
|
TrackGraph graph = null;
|
||||||
TrackNode secondNode = null;
|
TrackNode secondNode = null;
|
||||||
|
@ -402,7 +398,7 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
points.add(new MovingPoint(graph, node, secondNode, edge, positionOnEdge));
|
points.add(new TravellingPoint(node, secondNode, edge, positionOnEdge));
|
||||||
}
|
}
|
||||||
|
|
||||||
secondNode = node;
|
secondNode = node;
|
||||||
|
@ -483,9 +479,9 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
.forEach(Carriage::discardEntity);
|
.forEach(Carriage::discardEntity);
|
||||||
Create.RAILWAYS.carriageById.clear();
|
Create.RAILWAYS.carriageById.clear();
|
||||||
|
|
||||||
Train train = new Train(UUID.randomUUID(), graph, carriages, spacing);
|
Train train = new Train(UUID.randomUUID(), playerUUID, graph, carriages, spacing);
|
||||||
GlobalStation station = getOrCreateGlobalStation();
|
GlobalStation station = getOrCreateGlobalStation();
|
||||||
train.currentStation = station;
|
train.setCurrentStation(station);
|
||||||
station.reserveFor(train);
|
station.reserveFor(train);
|
||||||
|
|
||||||
Create.RAILWAYS.trains.put(train.id, train);
|
Create.RAILWAYS.trains.put(train.id, train);
|
||||||
|
@ -518,7 +514,7 @@ public class StationTileEntity extends SmartTileEntity {
|
||||||
if (isAssembling())
|
if (isAssembling())
|
||||||
return INFINITE_EXTENT_AABB;
|
return INFINITE_EXTENT_AABB;
|
||||||
if (renderBounds == null)
|
if (renderBounds == null)
|
||||||
renderBounds = new AABB(worldPosition, getTarget().getGlobalPosition());
|
renderBounds = new AABB(worldPosition, getTarget().getGlobalPosition()).inflate(2);
|
||||||
return renderBounds;
|
return renderBounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,12 +84,6 @@ public class TrackTargetingBehaviour extends TileEntityBehaviour {
|
||||||
return targetDirection;
|
return targetDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class GraphLocation {
|
|
||||||
public TrackGraph graph;
|
|
||||||
public Couple<TrackNode> edge;
|
|
||||||
public double position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GraphLocation determineGraphLocation() {
|
public GraphLocation determineGraphLocation() {
|
||||||
Level level = getWorld();
|
Level level = getWorld();
|
||||||
BlockPos pos = getGlobalPosition();
|
BlockPos pos = getGlobalPosition();
|
||||||
|
@ -152,7 +146,7 @@ public class TrackTargetingBehaviour extends TileEntityBehaviour {
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
GraphLocation graphLocation = new GraphLocation();
|
GraphLocation graphLocation = new GraphLocation();
|
||||||
graphLocation.edge = Couple.create(backNode, frontNode);
|
graphLocation.edge = Couple.create(backNode.getLocation(), frontNode.getLocation());
|
||||||
graphLocation.position = position;
|
graphLocation.position = position;
|
||||||
graphLocation.graph = graph;
|
graphLocation.graph = graph;
|
||||||
return graphLocation;
|
return graphLocation;
|
||||||
|
|
|
@ -3,6 +3,8 @@ package com.simibubi.create.content.logistics.trains.management.schedule;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
|
@ -76,6 +78,7 @@ public class FilteredDestination extends ScheduleDestination {
|
||||||
editBox.setBordered(false);
|
editBox.setBordered(false);
|
||||||
editBox.setTextColor(0xFFFFFF);
|
editBox.setTextColor(0xFFFFFF);
|
||||||
editBox.setValue(nameFilter);
|
editBox.setValue(nameFilter);
|
||||||
|
editBox.setFilter(s -> StringUtils.countMatches(s, '*') <= 3);
|
||||||
editBox.changeFocus(false);
|
editBox.changeFocus(false);
|
||||||
editBox.mouseClicked(0, 0, 0);
|
editBox.mouseClicked(0, 0, 0);
|
||||||
editorSubWidgets
|
editorSubWidgets
|
||||||
|
|
|
@ -21,7 +21,7 @@ public class StationPoweredCondition extends ScheduleWaitCondition {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean tickCompletion(Level level, Train train, CompoundTag context) {
|
public boolean tickCompletion(Level level, Train train, CompoundTag context) {
|
||||||
GlobalStation currentStation = train.currentStation;
|
GlobalStation currentStation = train.getCurrentStation();
|
||||||
if (currentStation == null)
|
if (currentStation == null)
|
||||||
return false;
|
return false;
|
||||||
BlockPos stationPos = currentStation.stationPos;
|
BlockPos stationPos = currentStation.stationPos;
|
||||||
|
|
|
@ -21,7 +21,7 @@ public class StationUnloadedCondition extends ScheduleWaitCondition {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean tickCompletion(Level level, Train train, CompoundTag context) {
|
public boolean tickCompletion(Level level, Train train, CompoundTag context) {
|
||||||
GlobalStation currentStation = train.currentStation;
|
GlobalStation currentStation = train.getCurrentStation();
|
||||||
if (currentStation == null)
|
if (currentStation == null)
|
||||||
return false;
|
return false;
|
||||||
if (level instanceof ServerLevel serverLevel)
|
if (level instanceof ServerLevel serverLevel)
|
||||||
|
|
|
@ -168,7 +168,7 @@ public class TrackRenderer extends SafeTileEntityRenderer<TrackTileEntity> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getViewDistance() {
|
public int getViewDistance() {
|
||||||
return 96;
|
return 96 * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ public class AllCommands {
|
||||||
.then(new ToggleDebugCommand().register())
|
.then(new ToggleDebugCommand().register())
|
||||||
.then(FabulousWarningCommand.register())
|
.then(FabulousWarningCommand.register())
|
||||||
.then(OverlayConfigCommand.register())
|
.then(OverlayConfigCommand.register())
|
||||||
|
.then(DumpRailwaysCommand.register())
|
||||||
.then(FixLightingCommand.register())
|
.then(FixLightingCommand.register())
|
||||||
.then(HighlightCommand.register())
|
.then(HighlightCommand.register())
|
||||||
.then(CouplingCommand.register())
|
.then(CouplingCommand.register())
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
package com.simibubi.create.foundation.command;
|
||||||
|
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||||
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.content.logistics.trains.GlobalRailwayManager;
|
||||||
|
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||||
|
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.ScheduleRuntime;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime.State;
|
||||||
|
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
import net.minecraft.commands.Commands;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
|
||||||
|
public class DumpRailwaysCommand {
|
||||||
|
|
||||||
|
static ArgumentBuilder<CommandSourceStack, ?> register() {
|
||||||
|
return Commands.literal("dumpRailways")
|
||||||
|
.requires(cs -> cs.hasPermission(1))
|
||||||
|
.executes(ctx -> {
|
||||||
|
CommandSourceStack source = ctx.getSource();
|
||||||
|
fillReport(source.getLevel(),
|
||||||
|
(s, f) -> source.sendSuccess(new TextComponent(s).withStyle(st -> st.withColor(f)), false));
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fillReport(ServerLevel level, BiConsumer<String, Integer> chat) {
|
||||||
|
GlobalRailwayManager railways = Create.RAILWAYS;
|
||||||
|
int white = ChatFormatting.WHITE.getColor();
|
||||||
|
int blue = 0xD3DEDC;
|
||||||
|
int darkBlue = 0x92A9BD;
|
||||||
|
int bright = 0xFFEFEF;
|
||||||
|
int orange = 0xFFAD60;
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
chat.accept("", white);
|
||||||
|
chat.accept("-+------<< Railways Summary: >>------+-", white);
|
||||||
|
chat.accept("Track Networks: " + railways.trackNetworks.size(), blue);
|
||||||
|
chat.accept("Trains: " + railways.trains.size(), blue);
|
||||||
|
chat.accept("", white);
|
||||||
|
|
||||||
|
for (Entry<UUID, TrackGraph> entry : railways.trackNetworks.entrySet()) {
|
||||||
|
TrackGraph graph = entry.getValue();
|
||||||
|
UUID id = entry.getKey();
|
||||||
|
chat.accept(id.toString()
|
||||||
|
.substring(0, 5) + ": Track Graph, "
|
||||||
|
+ graph.getNodes()
|
||||||
|
.size()
|
||||||
|
+ " Nodes", graph.color.getRGB());
|
||||||
|
for (GlobalStation globalStation : graph.getStations()) {
|
||||||
|
BlockPos pos = globalStation.stationPos;
|
||||||
|
chat.accept(" -> " + globalStation.name + " (" + globalStation.id.toString()
|
||||||
|
.substring(0, 5) + ") [" + pos.getX() + "," + pos.getY() + "," + pos.getZ() + "]", darkBlue);
|
||||||
|
if (globalStation.getPresentTrain() != null) {
|
||||||
|
chat.accept(" > Currently Occupied by " + globalStation.getPresentTrain().name.getString(), blue);
|
||||||
|
} else {
|
||||||
|
Train imminentTrain = globalStation.getImminentTrain();
|
||||||
|
if (imminentTrain != null) {
|
||||||
|
chat.accept(" > Reserved by " + imminentTrain.name.getString() + " ("
|
||||||
|
+ Mth.floor(imminentTrain.navigation.distanceToDestination) + "m away)", blue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chat.accept("", white);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Train train : railways.trains.values()) {
|
||||||
|
chat.accept(train.id.toString()
|
||||||
|
.substring(0, 5) + ": " + train.name.getString() + ", " + train.carriages.size() + " Wagons", bright);
|
||||||
|
if (train.graph != null)
|
||||||
|
chat.accept(" -> On Track: " + train.graph.id.toString()
|
||||||
|
.substring(0, 5), train.graph.color.getRGB());
|
||||||
|
if (train.derailed)
|
||||||
|
chat.accept(" -> Derailed", orange);
|
||||||
|
LivingEntity owner = train.getOwner(level);
|
||||||
|
if (owner != null)
|
||||||
|
chat.accept(" > Owned by " + owner.getName()
|
||||||
|
.getString(), blue);
|
||||||
|
GlobalStation currentStation = train.getCurrentStation();
|
||||||
|
if (currentStation != null) {
|
||||||
|
chat.accept(" > Waiting at: " + currentStation.name, blue);
|
||||||
|
} else if (train.navigation.destination != null) {
|
||||||
|
chat.accept(" > Travelling to " + train.navigation.destination.name + " ("
|
||||||
|
+ Mth.floor(train.navigation.distanceToDestination) + "m away)", darkBlue);
|
||||||
|
}
|
||||||
|
ScheduleRuntime runtime = train.runtime;
|
||||||
|
if (runtime.getSchedule() != null) {
|
||||||
|
chat.accept(" > Schedule, Entry " + runtime.currentEntry + ", "
|
||||||
|
+ (runtime.paused ? "Paused"
|
||||||
|
: runtime.state.name()
|
||||||
|
.replaceAll("_", " ")),
|
||||||
|
runtime.paused ? darkBlue : blue);
|
||||||
|
if (!runtime.paused && runtime.state != State.POST_TRANSIT) {
|
||||||
|
for (Component component : runtime.getSchedule().entries.get(runtime.currentEntry).destination
|
||||||
|
.getTitleAs("destination")) {
|
||||||
|
chat.accept(" - " + component.getString(), blue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
chat.accept(" > Idle, No Schedule", darkBlue);
|
||||||
|
chat.accept("", white);
|
||||||
|
}
|
||||||
|
chat.accept("-+--------------------------------+-", white);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -46,7 +46,7 @@ public abstract class TileEntityConfigurationPacket<TE extends SyncedTileEntity>
|
||||||
return;
|
return;
|
||||||
BlockEntity tileEntity = world.getBlockEntity(pos);
|
BlockEntity tileEntity = world.getBlockEntity(pos);
|
||||||
if (tileEntity instanceof SyncedTileEntity) {
|
if (tileEntity instanceof SyncedTileEntity) {
|
||||||
applySettings((TE) tileEntity);
|
applySettings(player, (TE) tileEntity);
|
||||||
((SyncedTileEntity) tileEntity).sendData();
|
((SyncedTileEntity) tileEntity).sendData();
|
||||||
tileEntity.setChanged();
|
tileEntity.setChanged();
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,10 @@ public abstract class TileEntityConfigurationPacket<TE extends SyncedTileEntity>
|
||||||
|
|
||||||
protected abstract void readSettings(FriendlyByteBuf buffer);
|
protected abstract void readSettings(FriendlyByteBuf buffer);
|
||||||
|
|
||||||
|
protected void applySettings(ServerPlayer player, TE te) {
|
||||||
|
applySettings(te);
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract void applySettings(TE te);
|
protected abstract void applySettings(TE te);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue