mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-26 06:57:51 +01:00
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.
This commit is contained in:
parent
574cd93a89
commit
31ad3aa671
5 changed files with 231 additions and 108 deletions
|
@ -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<StationTileEntity> {
|
||||
|
||||
|
@ -29,6 +32,101 @@ public class StationPeripheral extends SyncedPeripheral<StationTileEntity> {
|
|||
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();
|
||||
|
|
|
@ -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;
|
||||
|
@ -1087,6 +1087,7 @@ public class Train {
|
|||
public CompoundTag write(DimensionPalette dimensions) {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putUUID("Id", id);
|
||||
if (owner != null)
|
||||
tag.putUUID("Owner", owner);
|
||||
if (graph != null)
|
||||
tag.putUUID("Graph", graph.id);
|
||||
|
@ -1133,7 +1134,7 @@ public class Train {
|
|||
|
||||
public static Train read(CompoundTag tag, Map<UUID, TrackGraph> 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<Carriage> carriages = new ArrayList<>();
|
||||
|
|
|
@ -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<Carriage> carriages = new ArrayList<>();
|
||||
List<Integer> carriageSpacing = new ArrayList<>();
|
||||
|
||||
|
@ -73,6 +75,8 @@ public class TrainPacket extends SimplePacketBase {
|
|||
if (!add)
|
||||
return;
|
||||
|
||||
buffer.writeBoolean(train.owner != null);
|
||||
if (train.owner != null)
|
||||
buffer.writeUUID(train.owner);
|
||||
|
||||
buffer.writeVarInt(train.carriages.size());
|
||||
|
|
|
@ -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<StationTileEntity> {
|
||||
|
||||
|
@ -92,18 +84,12 @@ public class StationEditPacket extends TileEntityConfigurationPacket<StationTile
|
|||
BlockState blockState = level.getBlockState(blockPos);
|
||||
|
||||
if (dropSchedule) {
|
||||
scheduleDropRequested(player, te);
|
||||
te.dropSchedule(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!name.isBlank()) {
|
||||
GlobalStation station = te.getStation();
|
||||
GraphLocation graphLocation = te.edgePoint.determineGraphLocation();
|
||||
if (station != null && graphLocation != null) {
|
||||
station.name = name;
|
||||
Create.RAILWAYS.sync.pointAdded(graphLocation.graph, station);
|
||||
Create.RAILWAYS.markTracksDirty();
|
||||
}
|
||||
te.updateName(name);
|
||||
}
|
||||
|
||||
if (!(blockState.getBlock() instanceof StationBlock))
|
||||
|
@ -120,89 +106,17 @@ public class StationEditPacket extends TileEntityConfigurationPacket<StationTile
|
|||
assemblyComplete = te.getStation() != null && te.getStation()
|
||||
.getPresentTrain() != null;
|
||||
} else {
|
||||
if (disassembleAndEnterMode(player, te))
|
||||
if (te.tryDisassembleTrain(player) && te.tryEnterAssemblyMode())
|
||||
te.refreshAssemblyInfo();
|
||||
}
|
||||
if (!assemblyComplete)
|
||||
return;
|
||||
}
|
||||
if (isAssemblyMode == assemblyMode)
|
||||
return;
|
||||
|
||||
BlockState newState = blockState.cycle(StationBlock.ASSEMBLING);
|
||||
Boolean nowAssembling = newState.getValue(StationBlock.ASSEMBLING);
|
||||
|
||||
if (nowAssembling) {
|
||||
if (!disassembleAndEnterMode(player, te))
|
||||
return;
|
||||
} else {
|
||||
te.cancelAssembly();
|
||||
}
|
||||
|
||||
level.setBlock(blockPos, newState, 3);
|
||||
te.refreshBlockState();
|
||||
|
||||
if (nowAssembling)
|
||||
te.refreshAssemblyInfo();
|
||||
|
||||
GlobalStation station = te.getStation();
|
||||
GraphLocation graphLocation = te.edgePoint.determineGraphLocation();
|
||||
if (station != null && graphLocation != null) {
|
||||
station.assembling = nowAssembling;
|
||||
Create.RAILWAYS.sync.pointAdded(graphLocation.graph, station);
|
||||
Create.RAILWAYS.markTracksDirty();
|
||||
|
||||
if (nowAssembling)
|
||||
for (Train train : Create.RAILWAYS.sided(level).trains.values()) {
|
||||
if (train.navigation.destination != station)
|
||||
continue;
|
||||
GlobalStation preferredDestination = train.runtime.startCurrentInstruction();
|
||||
if (preferredDestination != null)
|
||||
train.navigation.startNavigation(preferredDestination, Double.MAX_VALUE, false);
|
||||
if (assemblyMode)
|
||||
te.enterAssemblyMode(player);
|
||||
else
|
||||
train.navigation.startNavigation(station, Double.MAX_VALUE, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleDropRequested(ServerPlayer sender, StationTileEntity te) {
|
||||
GlobalStation station = te.getStation();
|
||||
if (station == null)
|
||||
return;
|
||||
Train train = station.getPresentTrain();
|
||||
if (train == null)
|
||||
return;
|
||||
ItemStack schedule = train.runtime.returnSchedule();
|
||||
dropSchedule(sender, te, schedule);
|
||||
}
|
||||
|
||||
private boolean disassembleAndEnterMode(ServerPlayer sender, StationTileEntity te) {
|
||||
GlobalStation station = te.getStation();
|
||||
if (station != null) {
|
||||
Train train = station.getPresentTrain();
|
||||
BlockPos trackPosition = te.edgePoint.getGlobalPosition();
|
||||
ItemStack schedule = train == null ? ItemStack.EMPTY : train.runtime.returnSchedule();
|
||||
if (train != null && !train.disassemble(te.getAssemblyDirection(), trackPosition.above()))
|
||||
return false;
|
||||
dropSchedule(sender, te, schedule);
|
||||
}
|
||||
return te.tryEnterAssemblyMode();
|
||||
}
|
||||
|
||||
private void dropSchedule(ServerPlayer sender, StationTileEntity te, ItemStack schedule) {
|
||||
if (schedule.isEmpty())
|
||||
return;
|
||||
if (sender.getMainHandItem()
|
||||
.isEmpty()) {
|
||||
sender.getInventory()
|
||||
.placeItemBackInInventory(schedule);
|
||||
return;
|
||||
}
|
||||
Vec3 v = VecHelper.getCenterOf(te.getBlockPos());
|
||||
ItemEntity itemEntity = new ItemEntity(te.getLevel(), v.x, v.y, v.z, schedule);
|
||||
itemEntity.setDeltaMovement(Vec3.ZERO);
|
||||
te.getLevel()
|
||||
.addFreshEntity(itemEntity);
|
||||
te.exitAssemblyMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,6 +9,7 @@ import java.util.Map;
|
|||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
@ -25,6 +26,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.ITr
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
|
||||
import com.simibubi.create.content.logistics.block.depot.DepotBehaviour;
|
||||
import com.simibubi.create.content.logistics.block.display.DisplayLinkBlock;
|
||||
import com.simibubi.create.content.logistics.trains.GraphLocation;
|
||||
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
||||
import com.simibubi.create.content.logistics.trains.ITrackBlock;
|
||||
import com.simibubi.create.content.logistics.trains.TrackEdge;
|
||||
|
@ -51,6 +53,7 @@ import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
|||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
import com.simibubi.create.foundation.utility.WorldAttached;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
|
||||
|
@ -64,9 +67,11 @@ import net.minecraft.core.particles.ParticleTypes;
|
|||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
|
@ -320,6 +325,63 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean enterAssemblyMode(@Nullable ServerPlayer sender) {
|
||||
if (isAssembling())
|
||||
return false;
|
||||
|
||||
tryDisassembleTrain(sender);
|
||||
if (!tryEnterAssemblyMode())
|
||||
return false;
|
||||
|
||||
BlockState newState = getBlockState().setValue(StationBlock.ASSEMBLING, true);
|
||||
level.setBlock(getBlockPos(), newState, 3);
|
||||
refreshBlockState();
|
||||
refreshAssemblyInfo();
|
||||
|
||||
updateStationState(station -> 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<GlobalStation> 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;
|
||||
|
|
Loading…
Reference in a new issue