CreateMod/src/main/java/com/simibubi/create/compat/computercraft/peripherals/StationPeripheral.java
caelwarner 31ad3aa671
Extended train station peripheral API
- Train station peripherals can now assemble and disassemble trains, check if the station is in assembly mode, set the assembly mode of the station, get and change the station name, check if a train is present at the station and get and change the currently present train name.
- Refactored StationEditPacket. Moved most of the logic that was previously in StationEditPacket to StationTileEntity. This allows us to call this logic without having to send a packet.
- Made Train#owner nullable. This is needed so that computers can assemble trains. All Train#owner is currently used for is to display the train status to the correct play.
2023-03-08 18:22:23 -08:00

230 lines
7.6 KiB
Java

package com.simibubi.create.compat.computercraft.peripherals;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import com.simibubi.create.compat.computercraft.CreateLuaTable;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.TrainEditPacket;
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleEntry;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleInstruction;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.Components;
import com.simibubi.create.foundation.utility.Pair;
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 net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.NotNull;
import net.minecraftforge.network.PacketDistributor;
public class StationPeripheral extends SyncedPeripheral<StationTileEntity> {
public StationPeripheral(StationTileEntity tile) {
super(tile);
}
@LuaFunction(mainThread = true)
public final void assemble() throws LuaException {
if (!tile.isAssembling())
throw new LuaException("station must be in assembly mode");
tile.assemble(null);
if (tile.getStation() == null || tile.getStation().getPresentTrain() == null)
throw new LuaException("failed to assemble train");
if (!tile.exitAssemblyMode())
throw new LuaException("failed to exit assembly mode");
}
@LuaFunction(mainThread = true)
public final void disassemble() throws LuaException {
GlobalStation station = tile.getStation();
if (station == null)
throw new LuaException("train station does not exist");
Train train = station.getPresentTrain();
if (train == null)
throw new LuaException("there is no train present");
if (!tile.enterAssemblyMode(null))
throw new LuaException("could not disassemble train");
}
@LuaFunction(mainThread = true)
public final void setAssemblyMode(boolean assemblyMode) throws LuaException {
if (assemblyMode) {
if (!tile.enterAssemblyMode(null))
throw new LuaException("failed to enter assembly mode");
} else {
if (!tile.exitAssemblyMode())
throw new LuaException("failed to exit assembly mode");
}
}
@LuaFunction
public final boolean inAssemblyMode() {
return tile.isAssembling();
}
@LuaFunction
public final String getStationName() throws LuaException {
GlobalStation station = tile.getStation();
if (station == null)
throw new LuaException("train station does not exist");
return station.name;
}
@LuaFunction(mainThread = true)
public final void setStationName(String name) throws LuaException {
if (!tile.updateName(name))
throw new LuaException("could not set station name");
}
@LuaFunction
public final boolean isTrainPresent() throws LuaException {
GlobalStation station = tile.getStation();
if (station == null)
throw new LuaException("train station does not exist");
return station.getPresentTrain() != null;
}
@LuaFunction
public final String getTrainName() throws LuaException {
GlobalStation station = tile.getStation();
if (station == null)
throw new LuaException("train station does not exist");
Train train = station.getPresentTrain();
if (train == null)
throw new LuaException("there is no train present");
return train.name.getString();
}
@LuaFunction
public final void setTrainName(String name) throws LuaException {
GlobalStation station = tile.getStation();
if (station == null)
throw new LuaException("train station does not exist");
Train train = station.getPresentTrain();
if (train == null)
throw new LuaException("there is no train present");
train.name = Components.literal(name);
AllPackets.channel.send(PacketDistributor.ALL.noArg(), new TrainEditPacket.TrainEditReturnPacket(train.id, name, train.icon.getId()));
}
@LuaFunction(mainThread = true)
public final void setSchedule(IArguments arguments) throws LuaException {
GlobalStation station = tile.getStation();
if (station == null)
throw new LuaException("train station does not exist");
Train train = station.getPresentTrain();
if (train == null)
throw new LuaException("there is no train present");
Schedule schedule = parseSchedule(arguments);
train.runtime.setSchedule(schedule, true);
}
private static Schedule parseSchedule(IArguments arguments) throws LuaException {
CreateLuaTable scheduleTable = new CreateLuaTable(arguments.getTable(0));
Schedule schedule = new Schedule();
schedule.cyclic = scheduleTable.getOptBoolean("cyclic").orElse(true);
CreateLuaTable entriesTable = scheduleTable.getTable("entries");
for (CreateLuaTable entryTable : entriesTable.tableValues()) {
ScheduleEntry entry = new ScheduleEntry();
entry.instruction = getInstruction(entryTable);
// Add conditions
if (entry.instruction.supportsConditions()) {
for (CreateLuaTable conditionsListTable : entryTable.getTable("conditions").tableValues()) {
List<ScheduleWaitCondition> conditionsList = new ArrayList<>();
for (CreateLuaTable conditionTable : conditionsListTable.tableValues()) {
conditionsList.add(getCondition(conditionTable));
}
entry.conditions.add(conditionsList);
}
}
schedule.entries.add(entry);
}
return schedule;
}
private static ScheduleInstruction getInstruction(CreateLuaTable entry) throws LuaException {
ResourceLocation location = new ResourceLocation(entry.getString("instruction"));
for (Pair<ResourceLocation, Supplier<? extends ScheduleInstruction>> pair : Schedule.INSTRUCTION_TYPES)
if (pair.getFirst().equals(location)) {
ScheduleInstruction instruction = pair.getSecond().get();
instruction.setData(getEntryData(entry.getTable("data")));
return instruction;
}
throw new LuaException("instruction " + location + " is not a valid instruction type");
}
private static ScheduleWaitCondition getCondition(CreateLuaTable entry) throws LuaException {
ResourceLocation location = new ResourceLocation(entry.getString("condition"));
for (Pair<ResourceLocation, Supplier<? extends ScheduleWaitCondition>> pair : Schedule.CONDITION_TYPES)
if (pair.getFirst().equals(location)) {
ScheduleWaitCondition condition = pair.getSecond().get();
condition.setData(getEntryData(entry.getTable("data")));
return condition;
}
throw new LuaException("condition " + location + " is not a valid condition type");
}
private static CompoundTag getEntryData(CreateLuaTable data) throws LuaException {
CompoundTag tag = new CompoundTag();
for (String key : data.stringKeySet()) {
String tagKey = StringHelper.snakeCaseToCamelCase(key);
Object value = data.get(key);
if (value instanceof Boolean)
tag.putBoolean(tagKey, (Boolean) value);
else if (value instanceof Number)
tag.putDouble(tagKey, ((Number) value).doubleValue());
else if (value instanceof String)
tag.putString(tagKey, (String) value);
else
throw new LuaException("");
}
return tag;
}
@NotNull
@Override
public String getType() {
return "Create_Station";
}
}