Improve ComputerCraft integration of Train Stations

- Emit CC events train_imminent, train_arrival and train_departure when
  these occur on the station
- Add CC canTrainReach() function to test if the train stopped at the
  station can reach a (schedule-compatible) destination
- Add CC distanceTo() function to get the shortest distance to a
  (schedule-compatible) destination at the moment, using the train
  stopped in the station
This commit is contained in:
Céleste Wouters 2024-08-23 18:58:09 +02:00
parent 7c385510d4
commit 88719133ea
Failed to generate hash of commit
3 changed files with 102 additions and 2 deletions

View file

@ -0,0 +1,30 @@
package com.simibubi.create.compat.computercraft.events;
import org.jetbrains.annotations.NotNull;
import com.simibubi.create.content.trains.entity.Train;
public class StationTrainPresenceEvent implements ComputerEvent {
public enum Type {
IMMINENT("train_imminent"),
ARRIVAL("train_arrival"),
DEPARTURE("train_departure");
public final String name;
Type(String name) {
this.name = name;
}
}
public Type type;
public @NotNull Train train;
public StationTrainPresenceEvent(Type type, @NotNull Train train) {
this.type = type;
this.train = train;
}
}

View file

@ -1,14 +1,19 @@
package com.simibubi.create.compat.computercraft.implementation.peripherals;
import java.util.ArrayList;
import java.util.Map;
import javax.annotation.Nullable;
import java.util.regex.PatternSyntaxException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.simibubi.create.AllPackets;
import com.simibubi.create.compat.computercraft.events.ComputerEvent;
import com.simibubi.create.compat.computercraft.events.StationTrainPresenceEvent;
import com.simibubi.create.compat.computercraft.implementation.CreateLuaTable;
import com.simibubi.create.content.trains.entity.Train;
import com.simibubi.create.content.trains.graph.DiscoveredPath;
import com.simibubi.create.content.trains.graph.EdgePointType;
import com.simibubi.create.content.trains.schedule.Schedule;
import com.simibubi.create.content.trains.station.GlobalStation;
import com.simibubi.create.content.trains.station.StationBlockEntity;
@ -18,6 +23,9 @@ import com.simibubi.create.foundation.utility.StringHelper;
import dan200.computercraft.api.lua.IArguments;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.api.lua.MethodResult;
import net.createmod.catnip.data.Glob;
import net.createmod.catnip.data.Pair;
import net.minecraft.nbt.ByteTag;
import net.minecraft.nbt.CollectionTag;
import net.minecraft.nbt.CompoundTag;
@ -165,6 +173,45 @@ public class StationPeripheral extends SyncedPeripheral<StationBlockEntity> {
train.runtime.setSchedule(schedule, autoSchedule);
}
/**
* @return Path (if available) and boolean indicating if destination exists at all.
*/
private Pair<@Nullable DiscoveredPath, @NotNull Boolean> findPath(String destinationFilter) throws LuaException {
Train train = getTrainOrThrow();
String regex = Glob.toRegexPattern(destinationFilter, "");
boolean anyMatch = false;
ArrayList<GlobalStation> validStations = new ArrayList<>();
try {
for (GlobalStation globalStation : train.graph.getPoints(EdgePointType.STATION)) {
if (!globalStation.name.matches(regex))
continue;
anyMatch = true;
validStations.add(globalStation);
}
} catch (PatternSyntaxException ignored) {}
DiscoveredPath best = train.navigation.findPathTo(validStations, Double.MAX_VALUE);
if (best == null)
return Pair.of(null, anyMatch);
return Pair.of(best, true);
}
@LuaFunction
public MethodResult canTrainReach(String destinationFilter) throws LuaException {
Pair<@Nullable DiscoveredPath, @NotNull Boolean> path = findPath(destinationFilter);
if (path.getFirst() != null)
return MethodResult.of(true, null);
return MethodResult.of(false, path.getSecond() ? "cannot-reach" : "no-target");
}
@LuaFunction
public MethodResult distanceTo(String destinationFilter) throws LuaException {
Pair<@Nullable DiscoveredPath, @NotNull Boolean> path = findPath(destinationFilter);
if (path.getFirst() != null)
return MethodResult.of(path.getFirst().distance, null);
return MethodResult.of(null, path.getSecond() ? "cannot-reach" : "no-target");
}
private @NotNull Train getTrainOrThrow() throws LuaException {
GlobalStation station = blockEntity.getStation();
if (station == null)
@ -269,6 +316,13 @@ public class StationPeripheral extends SyncedPeripheral<StationBlockEntity> {
throw new LuaException("unknown object type " + value.getClass().getName());
}
@Override
public void prepareComputerEvent(@NotNull ComputerEvent event) {
if (event instanceof StationTrainPresenceEvent stpe) {
queueEvent(stpe.type.name, stpe.train.name.getString());
}
}
@NotNull
@Override
public String getType() {

View file

@ -22,6 +22,7 @@ import com.simibubi.create.AllPackets;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.Create;
import com.simibubi.create.api.contraption.transformable.TransformableBlockEntity;
import com.simibubi.create.compat.computercraft.events.StationTrainPresenceEvent;
import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour;
import com.simibubi.create.compat.computercraft.ComputerCraftProxy;
import com.simibubi.create.content.contraptions.AssemblyException;
@ -267,6 +268,21 @@ public class StationBlockEntity extends SmartBlockEntity implements Transformabl
imminentTrain.runtime.displayLinkUpdateRequested = false;
}
if (!level.isClientSide && computerBehaviour.hasAttachedComputer()) {
if (this.imminentTrain == null && imminentTrain != null)
computerBehaviour.prepareComputerEvent(
new StationTrainPresenceEvent(StationTrainPresenceEvent.Type.IMMINENT, imminentTrain));
if (newlyArrived) {
if (trainPresent)
computerBehaviour.prepareComputerEvent(
new StationTrainPresenceEvent(StationTrainPresenceEvent.Type.ARRIVAL, imminentTrain));
else
computerBehaviour.prepareComputerEvent(
new StationTrainPresenceEvent(StationTrainPresenceEvent.Type.DEPARTURE,
Create.RAILWAYS.trains.get(this.imminentTrain)));
}
}
if (newlyArrived)
applyAutoSchedule();