From 88719133ea20255e4d19075b103537dea34f49f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9leste=20Wouters?= Date: Fri, 23 Aug 2024 18:58:09 +0200 Subject: [PATCH] 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 --- .../events/StationTrainPresenceEvent.java | 30 ++++++++++ .../peripherals/StationPeripheral.java | 58 ++++++++++++++++++- .../trains/station/StationBlockEntity.java | 16 +++++ 3 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/events/StationTrainPresenceEvent.java diff --git a/src/main/java/com/simibubi/create/compat/computercraft/events/StationTrainPresenceEvent.java b/src/main/java/com/simibubi/create/compat/computercraft/events/StationTrainPresenceEvent.java new file mode 100644 index 0000000000..badb160362 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/events/StationTrainPresenceEvent.java @@ -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; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java index 3f40a9f210..ea157ea882 100644 --- a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java @@ -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 { 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 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 { 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() { diff --git a/src/main/java/com/simibubi/create/content/trains/station/StationBlockEntity.java b/src/main/java/com/simibubi/create/content/trains/station/StationBlockEntity.java index eae80b1e4b..fca1f74915 100644 --- a/src/main/java/com/simibubi/create/content/trains/station/StationBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/trains/station/StationBlockEntity.java @@ -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();