From 31ad3aa671339e7642f1c89118a218ff7c7eec15 Mon Sep 17 00:00:00 2001 From: caelwarner Date: Wed, 8 Mar 2023 18:22:23 -0800 Subject: [PATCH] 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. --- .../peripherals/StationPeripheral.java | 104 ++++++++++++++++- .../logistics/trains/entity/Train.java | 19 ++-- .../logistics/trains/entity/TrainPacket.java | 10 +- .../edgePoint/station/StationEditPacket.java | 100 ++--------------- .../edgePoint/station/StationTileEntity.java | 106 ++++++++++++++++++ 5 files changed, 231 insertions(+), 108 deletions(-) diff --git a/src/main/java/com/simibubi/create/compat/computercraft/peripherals/StationPeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/peripherals/StationPeripheral.java index a9eeb352d..309058f5e 100644 --- a/src/main/java/com/simibubi/create/compat/computercraft/peripherals/StationPeripheral.java +++ b/src/main/java/com/simibubi/create/compat/computercraft/peripherals/StationPeripheral.java @@ -4,24 +4,27 @@ import java.util.ArrayList; import java.util.List; import java.util.function.Supplier; -import org.jetbrains.annotations.NotNull; - 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 { @@ -29,6 +32,101 @@ public class StationPeripheral extends SyncedPeripheral { 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(); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java index a5a371013..8c237ceaf 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java @@ -15,8 +15,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; import java.util.function.Consumer; -import javax.annotation.Nullable; - import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.mutable.MutableObject; @@ -51,7 +49,7 @@ import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.VecHelper; - +import javax.annotation.Nullable; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -67,6 +65,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Explosion.BlockInteraction; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -86,6 +85,7 @@ public class Train { public boolean honk = false; public UUID id; + @Nullable public UUID owner; public TrackGraph graph; public Navigation navigation; @@ -124,7 +124,7 @@ public class Train { public int honkPitch; public float accumulatedSteamRelease; - + int tickOffset; double[] stress; @@ -277,7 +277,7 @@ public class Train { int carriageCount = carriages.size(); boolean stalled = false; double maxStress = 0; - + if (carriageWaitingForChunks != -1) distance = 0; @@ -317,7 +317,7 @@ public class Train { entries++; } } - + if (entries > 0) actual = total / entries; @@ -369,7 +369,7 @@ public class Train { .getLeadingPoint(); double totalStress = derailed ? 0 : leadingStress + trailingStress; - + boolean first = i == 0; boolean last = i == carriageCount - 1; int carriageType = first ? last ? Carriage.BOTH : Carriage.FIRST : last ? Carriage.LAST : Carriage.MIDDLE; @@ -1087,7 +1087,8 @@ public class Train { public CompoundTag write(DimensionPalette dimensions) { CompoundTag tag = new CompoundTag(); tag.putUUID("Id", id); - tag.putUUID("Owner", owner); + if (owner != null) + tag.putUUID("Owner", owner); if (graph != null) tag.putUUID("Graph", graph.id); tag.put("Carriages", NBTHelper.writeCompoundList(carriages, c -> c.write(dimensions))); @@ -1133,7 +1134,7 @@ public class Train { public static Train read(CompoundTag tag, Map trackNetworks, DimensionPalette dimensions) { UUID id = tag.getUUID("Id"); - UUID owner = tag.getUUID("Owner"); + UUID owner = tag.contains("Owner") ? tag.getUUID("Owner") : null; UUID graphId = tag.contains("Graph") ? tag.getUUID("Graph") : null; TrackGraph graph = graphId == null ? null : trackNetworks.get(graphId); List carriages = new ArrayList<>(); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java index 479b2699e..ec43cd9f9 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java @@ -12,7 +12,6 @@ import com.simibubi.create.foundation.networking.SimplePacketBase; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.RegisteredObjects; - import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.world.level.block.Block; @@ -37,7 +36,10 @@ public class TrainPacket extends SimplePacketBase { if (!add) return; - UUID owner = buffer.readUUID(); + UUID owner = null; + if (buffer.readBoolean()) + owner = buffer.readUUID(); + List carriages = new ArrayList<>(); List carriageSpacing = new ArrayList<>(); @@ -73,7 +75,9 @@ public class TrainPacket extends SimplePacketBase { if (!add) return; - buffer.writeUUID(train.owner); + buffer.writeBoolean(train.owner != null); + if (train.owner != null) + buffer.writeUUID(train.owner); buffer.writeVarInt(train.carriages.size()); for (Carriage carriage : train.carriages) { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java index e1ec084c7..2028aca9d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java @@ -1,19 +1,11 @@ package com.simibubi.create.content.logistics.trains.management.edgePoint.station; -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.GraphLocation; -import com.simibubi.create.content.logistics.trains.entity.Train; import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket; -import com.simibubi.create.foundation.utility.VecHelper; - import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; public class StationEditPacket extends TileEntityConfigurationPacket { @@ -92,18 +84,12 @@ public class StationEditPacket extends TileEntityConfigurationPacket station.assembling = true); + GlobalStation station = getStation(); + if (station != null) { + for (Train train : Create.RAILWAYS.sided(level).trains.values()) { + if (train.navigation.destination != station) + continue; + + GlobalStation preferredDestination = train.runtime.startCurrentInstruction(); + train.navigation.startNavigation(preferredDestination != null ? preferredDestination : station, Double.MAX_VALUE, false); + } + } + + return true; + } + + public boolean exitAssemblyMode() { + if (!isAssembling()) + return false; + + cancelAssembly(); + BlockState newState = getBlockState().setValue(StationBlock.ASSEMBLING, false); + level.setBlock(getBlockPos(), newState, 3); + refreshBlockState(); + + return updateStationState(station -> station.assembling = false); + } + + public boolean tryDisassembleTrain(@Nullable ServerPlayer sender) { + GlobalStation station = getStation(); + if (station == null) + return false; + + Train train = station.getPresentTrain(); + if (train == null) + return false; + + BlockPos trackPosition = edgePoint.getGlobalPosition(); + if (!train.disassemble(getAssemblyDirection(), trackPosition.above())) + return false; + + dropSchedule(sender); + return true; + } + public boolean isAssembling() { BlockState state = getBlockState(); return state.hasProperty(StationBlock.ASSEMBLING) && state.getValue(StationBlock.ASSEMBLING); @@ -347,6 +409,42 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable return true; } + public void dropSchedule(@Nullable ServerPlayer sender) { + GlobalStation station = getStation(); + if (station == null) + return; + + Train train = station.getPresentTrain(); + if (train == null) + return; + + ItemStack schedule = train.runtime.returnSchedule(); + if (schedule.isEmpty()) + return; + if (sender != null && sender.getMainHandItem().isEmpty()) { + sender.getInventory() + .placeItemBackInInventory(schedule); + return; + } + + Vec3 v = VecHelper.getCenterOf(getBlockPos()); + ItemEntity itemEntity = new ItemEntity(getLevel(), v.x, v.y, v.z, schedule); + itemEntity.setDeltaMovement(Vec3.ZERO); + getLevel().addFreshEntity(itemEntity); + } + + private boolean updateStationState(Consumer updateState) { + GlobalStation station = getStation(); + GraphLocation graphLocation = edgePoint.determineGraphLocation(); + if (station == null || graphLocation == null) + return false; + + updateState.accept(station); + Create.RAILWAYS.sync.pointAdded(graphLocation.graph, station); + Create.RAILWAYS.markTracksDirty(); + return true; + } + public void refreshAssemblyInfo() { if (!edgePoint.hasValidTrack()) return; @@ -415,6 +513,14 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable map.put(worldPosition, BoundingBox.fromCorners(startPosition, trackEnd)); } + public boolean updateName(String name) { + if (!updateStationState(station -> station.name = name)) + return false; + notifyUpdate(); + + return true; + } + public boolean isValidBogeyOffset(int i) { if ((i < 3 || bogeyCount == 0) && i != 0) return false;