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
This commit is contained in:
Céleste Wouters 2024-08-23 18:58:09 +02:00
parent cbf886e69b
commit a889d16c34
Failed to generate hash of commit
4 changed files with 98 additions and 6 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,15 +1,22 @@
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.schedule.destination.DestinationInstruction;
import com.simibubi.create.content.trains.station.GlobalStation;
import com.simibubi.create.content.trains.station.StationBlockEntity;
import com.simibubi.create.content.trains.station.TrainEditPacket;
@ -19,6 +26,7 @@ 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.minecraft.nbt.ByteTag;
import net.minecraft.nbt.CollectionTag;
import net.minecraft.nbt.CompoundTag;
@ -164,6 +172,33 @@ public class StationPeripheral extends SyncedPeripheral<StationBlockEntity> {
train.runtime.setSchedule(schedule, autoSchedule);
}
@LuaFunction
public MethodResult canTrainReach(String destinationFilter) throws LuaException {
Train train = getTrainOrThrow();
String regex = DestinationInstruction.getFilterForRegex(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) {
if (anyMatch)
return MethodResult.of(false, "cannot-reach");
else
return MethodResult.of(false, "no-target");
}
return MethodResult.of(true, null);
}
private @NotNull Train getTrainOrThrow() throws LuaException {
GlobalStation station = blockEntity.getStation();
if (station == null)
@ -268,6 +303,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

@ -2,6 +2,8 @@ package com.simibubi.create.content.trains.schedule.destination;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.ImmutableList;
@ -46,7 +48,10 @@ public class DestinationInstruction extends TextScheduleInstruction {
}
public String getFilterForRegex() {
String filter = getFilter();
return getFilterForRegex(getFilter());
}
public static String getFilterForRegex(@NotNull String filter) {
if (filter.isBlank())
return filter;
return "\\Q" + filter.replace("*", "\\E.*\\Q") + "\\E";

View file

@ -13,8 +13,6 @@ import java.util.function.Consumer;
import javax.annotation.Nullable;
import com.simibubi.create.content.trains.graph.DiscoveredPath;
import org.jetbrains.annotations.NotNull;
import com.simibubi.create.AllBlocks;
@ -22,6 +20,7 @@ import com.simibubi.create.AllItems;
import com.simibubi.create.AllPackets;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.Create;
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;
@ -38,6 +37,7 @@ import com.simibubi.create.content.trains.entity.CarriageContraption;
import com.simibubi.create.content.trains.entity.Train;
import com.simibubi.create.content.trains.entity.TrainPacket;
import com.simibubi.create.content.trains.entity.TravellingPoint;
import com.simibubi.create.content.trains.graph.DiscoveredPath;
import com.simibubi.create.content.trains.graph.EdgePointType;
import com.simibubi.create.content.trains.graph.TrackEdge;
import com.simibubi.create.content.trains.graph.TrackGraph;
@ -259,6 +259,21 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab
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();