mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-14 11:43:49 +01:00
Train Admin
- Clean up /dumpRailways - Trains can now be removed via a command
This commit is contained in:
parent
3806ab04d7
commit
1d1cf8e289
7 changed files with 184 additions and 89 deletions
|
@ -223,13 +223,14 @@ public class GlobalRailwayManager {
|
|||
|
||||
for (Iterator<Train> iterator = waitingTrains.iterator(); iterator.hasNext();) {
|
||||
Train train = iterator.next();
|
||||
|
||||
|
||||
if (train.invalid) {
|
||||
iterator.remove();
|
||||
trains.remove(train.id);
|
||||
AllPackets.channel.send(PacketDistributor.ALL.noArg(), new TrainPacket(train, false));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (train.navigation.waitingForSignal != null)
|
||||
continue;
|
||||
movingTrains.add(train);
|
||||
|
@ -238,20 +239,20 @@ public class GlobalRailwayManager {
|
|||
|
||||
for (Iterator<Train> iterator = movingTrains.iterator(); iterator.hasNext();) {
|
||||
Train train = iterator.next();
|
||||
|
||||
|
||||
if (train.invalid) {
|
||||
iterator.remove();
|
||||
trains.remove(train.id);
|
||||
AllPackets.channel.send(PacketDistributor.ALL.noArg(), new TrainPacket(train, false));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (train.navigation.waitingForSignal == null)
|
||||
continue;
|
||||
waitingTrains.add(train);
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void tickSignalOverlay() {
|
||||
|
|
|
@ -9,6 +9,7 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
@ -465,6 +466,17 @@ public class TrackGraph {
|
|||
return connections.put(node2, edge) == null;
|
||||
}
|
||||
|
||||
public float distanceToLocationSqr(Level level, Vec3 location) {
|
||||
float nearest = Float.MAX_VALUE;
|
||||
for (TrackNodeLocation tnl : nodes.keySet()) {
|
||||
if (!Objects.equals(tnl.dimension, level.dimension()))
|
||||
continue;
|
||||
nearest = Math.min(nearest, (float) tnl.getLocation()
|
||||
.distanceToSqr(location));
|
||||
}
|
||||
return nearest;
|
||||
}
|
||||
|
||||
public void deferIntersectionUpdate(TrackEdge edge) {
|
||||
deferredIntersectionUpdates.add(edge);
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
}
|
||||
|
||||
public boolean isLocalCoordWithin(BlockPos localPos, int min, int max) {
|
||||
if (!(getContraption() instanceof CarriageContraption cc))
|
||||
if (!(getContraption()instanceof CarriageContraption cc))
|
||||
return false;
|
||||
Direction facing = cc.getAssemblyDirection();
|
||||
Axis axis = facing.getClockWise()
|
||||
|
@ -266,6 +266,10 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
|
||||
carriageData.approach(this, carriage, 1f / getType().updateInterval());
|
||||
|
||||
if (!Create.RAILWAYS.sided(null).trains.containsKey(carriage.train.id)) {
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
if (!carriage.train.derailed)
|
||||
carriage.updateContraptionAnchors();
|
||||
|
||||
|
|
|
@ -413,7 +413,7 @@ public class Train {
|
|||
public IEdgePointListener frontSignalListener() {
|
||||
return (distance, couple) -> {
|
||||
|
||||
if (couple.getFirst() instanceof GlobalStation station) {
|
||||
if (couple.getFirst()instanceof GlobalStation station) {
|
||||
if (!station.canApproachFrom(couple.getSecond()
|
||||
.getSecond()) || navigation.destination != station)
|
||||
return false;
|
||||
|
@ -425,12 +425,12 @@ public class Train {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (couple.getFirst() instanceof TrackObserver observer) {
|
||||
if (couple.getFirst()instanceof TrackObserver observer) {
|
||||
occupiedObservers.add(observer.getId());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(couple.getFirst() instanceof SignalBoundary signal))
|
||||
if (!(couple.getFirst()instanceof SignalBoundary signal))
|
||||
return false;
|
||||
if (navigation.waitingForSignal != null && navigation.waitingForSignal.getFirst()
|
||||
.equals(signal.getId())) {
|
||||
|
@ -480,12 +480,12 @@ public class Train {
|
|||
|
||||
public IEdgePointListener backSignalListener() {
|
||||
return (distance, couple) -> {
|
||||
if (couple.getFirst() instanceof TrackObserver observer) {
|
||||
if (couple.getFirst()instanceof TrackObserver observer) {
|
||||
occupiedObservers.remove(observer.getId());
|
||||
cachedObserverFiltering.remove(observer.getId());
|
||||
return false;
|
||||
}
|
||||
if (!(couple.getFirst() instanceof SignalBoundary signal))
|
||||
if (!(couple.getFirst()instanceof SignalBoundary signal))
|
||||
return false;
|
||||
UUID groupId = signal.getGroup(couple.getSecond()
|
||||
.getFirst());
|
||||
|
@ -716,7 +716,7 @@ public class Train {
|
|||
return false;
|
||||
level = entity.level;
|
||||
|
||||
if (entity.getContraption() instanceof CarriageContraption cc)
|
||||
if (entity.getContraption()instanceof CarriageContraption cc)
|
||||
cc.returnStorageForDisassembly(carriage.storage);
|
||||
entity.setPos(Vec3
|
||||
.atLowerCornerOf(pos.relative(assemblyDirection, backwards ? offset + carriage.bogeySpacing : offset)));
|
||||
|
@ -732,7 +732,7 @@ public class Train {
|
|||
if (currentStation != null) {
|
||||
currentStation.cancelReservation(this);
|
||||
BlockPos tilePos = currentStation.getTilePos();
|
||||
if (level.getBlockEntity(tilePos) instanceof StationTileEntity ste)
|
||||
if (level.getBlockEntity(tilePos)instanceof StationTileEntity ste)
|
||||
ste.lastDisassembledTrainName = name.copy();
|
||||
}
|
||||
|
||||
|
@ -982,11 +982,11 @@ public class Train {
|
|||
|
||||
forEachTravellingPointBackwards((tp, d) -> {
|
||||
signalScout.travel(graph, d, signalScout.follow(tp), (distance, couple) -> {
|
||||
if (couple.getFirst() instanceof TrackObserver observer) {
|
||||
if (couple.getFirst()instanceof TrackObserver observer) {
|
||||
occupiedObservers.add(observer.getId());
|
||||
return false;
|
||||
}
|
||||
if (!(couple.getFirst() instanceof SignalBoundary signal))
|
||||
if (!(couple.getFirst()instanceof SignalBoundary signal))
|
||||
return false;
|
||||
couple.getSecond()
|
||||
.map(signal::getGroup)
|
||||
|
@ -1194,7 +1194,7 @@ public class Train {
|
|||
if (dimensional == null)
|
||||
return;
|
||||
CarriageContraptionEntity entity = dimensional.entity.get();
|
||||
if (entity == null || !(entity.getContraption() instanceof CarriageContraption otherCC))
|
||||
if (entity == null || !(entity.getContraption()instanceof CarriageContraption otherCC))
|
||||
break;
|
||||
Pair<Boolean, Integer> first = otherCC.soundQueue.getFirstWhistle(entity);
|
||||
if (first != null) {
|
||||
|
@ -1204,4 +1204,15 @@ public class Train {
|
|||
}
|
||||
}
|
||||
|
||||
public float distanceToLocationSqr(Level level, Vec3 location) {
|
||||
float distance = Float.MAX_VALUE;
|
||||
for (Carriage carriage : carriages) {
|
||||
DimensionalCarriageEntity dce = carriage.getDimensionalIfPresent(level.dimension());
|
||||
if (dce == null || dce.positionAnchor == null)
|
||||
continue;
|
||||
distance = Math.min(distance, (float) dce.positionAnchor.distanceToSqr(location));
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ public class AllCommands {
|
|||
.then(DumpRailwaysCommand.register())
|
||||
.then(FixLightingCommand.register())
|
||||
.then(HighlightCommand.register())
|
||||
.then(KillTrainCommand.register())
|
||||
.then(CouplingCommand.register())
|
||||
.then(ConfigCommand.register())
|
||||
.then(PonderCommand.register())
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package com.simibubi.create.foundation.command;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.simibubi.create.Create;
|
||||
|
@ -14,32 +14,36 @@ import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePoi
|
|||
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBoundary;
|
||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleRuntime;
|
||||
import com.simibubi.create.content.logistics.trains.management.schedule.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.ClickEvent;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.ComponentUtils;
|
||||
import net.minecraft.network.chat.HoverEvent;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class DumpRailwaysCommand {
|
||||
|
||||
static ArgumentBuilder<CommandSourceStack, ?> register() {
|
||||
return Commands.literal("dumpRailways")
|
||||
.requires(cs -> cs.hasPermission(1))
|
||||
.requires(cs -> cs.hasPermission(2))
|
||||
.executes(ctx -> {
|
||||
CommandSourceStack source = ctx.getSource();
|
||||
fillReport(source.getLevel(),
|
||||
(s, f) -> source.sendSuccess(new TextComponent(s).withStyle(st -> st.withColor(f)), false));
|
||||
fillReport(source.getLevel(), source.getPosition(),
|
||||
(s, f) -> source.sendSuccess(new TextComponent(s).withStyle(st -> st.withColor(f)), false),
|
||||
(c) -> source.sendSuccess(c, false));
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
static void fillReport(ServerLevel level, BiConsumer<String, Integer> chat) {
|
||||
static void fillReport(ServerLevel level, Vec3 location, BiConsumer<String, Integer> chat,
|
||||
Consumer<Component> chatRaw) {
|
||||
GlobalRailwayManager railways = Create.RAILWAYS;
|
||||
int white = ChatFormatting.WHITE.getColor();
|
||||
int blue = 0xD3DEDC;
|
||||
|
@ -47,81 +51,103 @@ public class DumpRailwaysCommand {
|
|||
int bright = 0xFFEFEF;
|
||||
int orange = 0xFFAD60;
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
chat.accept("", white);
|
||||
chat.accept("", white);
|
||||
chat.accept("-+------<< Railways Summary: >>------+-", white);
|
||||
chat.accept("Track Networks: " + railways.trackNetworks.size(), blue);
|
||||
int graphCount = railways.trackNetworks.size();
|
||||
chat.accept("Track Networks: " + graphCount, blue);
|
||||
chat.accept("Signal Groups: " + railways.signalEdgeGroups.size(), blue);
|
||||
chat.accept("Trains: " + railways.trains.size(), blue);
|
||||
int trainCount = railways.trains.size();
|
||||
chat.accept("Trains: " + trainCount, 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());
|
||||
Collection<SignalBoundary> signals = graph.getPoints(EdgePointType.SIGNAL);
|
||||
if (!signals.isEmpty())
|
||||
chat.accept(" -> " + signals.size() + " registered Signals", blue);
|
||||
for (GlobalStation globalStation : graph.getPoints(EdgePointType.STATION)) {
|
||||
BlockPos pos = globalStation.getTilePos();
|
||||
if (pos == null)
|
||||
pos = BlockPos.ZERO;
|
||||
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);
|
||||
}
|
||||
}
|
||||
List<TrackGraph> nearest = railways.trackNetworks.values()
|
||||
.stream()
|
||||
.sorted((tg1, tg2) -> Float.compare(tg1.distanceToLocationSqr(level, location),
|
||||
tg2.distanceToLocationSqr(level, location)))
|
||||
.limit(5)
|
||||
.toList();
|
||||
|
||||
if (graphCount > 0) {
|
||||
chat.accept("Nearest Graphs: ", orange);
|
||||
chat.accept("", white);
|
||||
for (TrackGraph graph : nearest) {
|
||||
chat.accept(graph.id.toString()
|
||||
.substring(0, 5) + " with "
|
||||
+ graph.getNodes()
|
||||
.size()
|
||||
+ " Nodes", white);
|
||||
Collection<SignalBoundary> signals = graph.getPoints(EdgePointType.SIGNAL);
|
||||
if (!signals.isEmpty())
|
||||
chat.accept(" -> " + signals.size() + " Signals", blue);
|
||||
Collection<GlobalStation> stations = graph.getPoints(EdgePointType.STATION);
|
||||
if (!stations.isEmpty())
|
||||
chat.accept(" -> " + stations.size() + " Stations", blue);
|
||||
}
|
||||
chat.accept("", white);
|
||||
if (graphCount > 5) {
|
||||
chat.accept("[...]", white);
|
||||
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).instruction
|
||||
.getTitleAs("destination")) {
|
||||
chat.accept(" - " + component.getString(), blue);
|
||||
}
|
||||
}
|
||||
} else
|
||||
chat.accept(" > Idle, No Schedule", darkBlue);
|
||||
List<Train> nearestTrains = railways.trains.values()
|
||||
.stream()
|
||||
.sorted((t1, t2) -> Float.compare(t1.distanceToLocationSqr(level, location),
|
||||
t2.distanceToLocationSqr(level, location)))
|
||||
.limit(5)
|
||||
.toList();
|
||||
|
||||
if (trainCount > 0 && !nearestTrains.isEmpty()) {
|
||||
chat.accept("Nearest Trains: ", orange);
|
||||
chat.accept("", white);
|
||||
for (Train train : nearestTrains) {
|
||||
chat.accept(train.id.toString()
|
||||
.substring(0, 5) + ": " + train.name.getString() + ", " + train.carriages.size() + " Wagons",
|
||||
bright);
|
||||
if (train.derailed)
|
||||
chat.accept(" -> Derailed", orange);
|
||||
else if (train.graph != null)
|
||||
chat.accept(" -> On Track: " + train.graph.id.toString()
|
||||
.substring(0, 5), blue);
|
||||
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);
|
||||
} else
|
||||
chat.accept(" -> Idle, No Schedule", darkBlue);
|
||||
chatRaw.accept(createDeleteButton(train));
|
||||
chat.accept("", white);
|
||||
}
|
||||
if (trainCount > 5) {
|
||||
chat.accept("[...]", white);
|
||||
chat.accept("", white);
|
||||
}
|
||||
}
|
||||
|
||||
chat.accept("-+--------------------------------+-", white);
|
||||
}
|
||||
|
||||
private static Component createDeleteButton(Train train) {
|
||||
return ComponentUtils.wrapInSquareBrackets((new TextComponent("Remove")).withStyle((p_180514_) -> {
|
||||
return p_180514_.withColor(0xFFAD60)
|
||||
.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/c killTrain " + train.id.toString()))
|
||||
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
|
||||
new TextComponent("Click to remove ").append(train.name)))
|
||||
.withInsertion("/c killTrain " + train.id.toString());
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package com.simibubi.create.foundation.command;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.arguments.UuidArgument;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
|
||||
public class KillTrainCommand {
|
||||
|
||||
static ArgumentBuilder<CommandSourceStack, ?> register() {
|
||||
return Commands.literal("killTrain")
|
||||
.requires(cs -> cs.hasPermission(2))
|
||||
.then(Commands.argument("train", UuidArgument.uuid())
|
||||
.executes(ctx -> {
|
||||
CommandSourceStack source = ctx.getSource();
|
||||
run(source, UuidArgument.getUuid(ctx, "train"));
|
||||
return 1;
|
||||
}));
|
||||
}
|
||||
|
||||
private static void run(CommandSourceStack source, UUID argument) {
|
||||
Train train = Create.RAILWAYS.trains.get(argument);
|
||||
if (train == null) {
|
||||
source.sendFailure(new TextComponent("No Train with id " + argument.toString()
|
||||
.substring(0, 5) + "[...] was found"));
|
||||
return;
|
||||
}
|
||||
|
||||
train.invalid = true;
|
||||
source.sendSuccess(new TextComponent("Train '").append(train.name)
|
||||
.append("' removed successfully"), true);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue