mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-02-06 18:34:59 +01:00
Add ComputerCraft integration to Train Signals
- Makes computer-controlled signals unable to be changed by external factors - Emit CC event train_signal_state_change with the new state as parameter whenever the signal changes - Add CC getState() function to get the current signal state - Add CC isForcedRed()/setForcedRed(forced) functions to force the signal to be red, replacing redstone control - Add CC getSignalType()/cycleSignalType() function to change the signal signal type in the same manner as using the wrench - Add CC listBlockingTrainNames() function to list names of trains blocking the track group ahead of the signal
This commit is contained in:
parent
96a325c03b
commit
cbf886e69b
15 changed files with 210 additions and 9 deletions
|
@ -582,8 +582,8 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
|
|||
5616dda664dd106d576848124fc0fc1de18d0fd3 assets/create/blockstates/yellow_valve_handle.json
|
||||
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
|
||||
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
|
||||
3c04d30f0521554ade532f1662cdaf4ae2958ab3 assets/create/lang/en_ud.json
|
||||
6a0df005c7594667d9c7582a877984d25382df7b assets/create/lang/en_us.json
|
||||
82ed4a747f58fc0435f52fff39b7ea1579147d04 assets/create/lang/en_ud.json
|
||||
f8a82ca4b8aee16b3ba754016e1994766251fc56 assets/create/lang/en_us.json
|
||||
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
|
||||
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
|
||||
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
|
||||
|
|
|
@ -2606,6 +2606,7 @@
|
|||
"create.track_signal.cannot_change_mode": "\u05DF\u0250ub\u0131S s\u0131\u0265\u0287 \u025Fo \u01DDpo\u026F \u0265\u0254\u0287\u0131\u028Ds o\u0287 \u01DD\u05DFq\u0250u\u2229",
|
||||
"create.track_signal.mode_change.cross_signal": "\u01DD\u05DFq\u0250s\u0279\u01DD\u028C\u0250\u0279\u0287 \u028E\u05DF\u05DFn\u025F uo\u0131\u0287\u0254\u01DDs \u025F\u0131 \u01DDb\u0250ss\u0250d \u028Do\u05DF\u05DF\u2C6F >-",
|
||||
"create.track_signal.mode_change.entry_signal": "p\u01DD\u0131dn\u0254\u0254oun uo\u0131\u0287\u0254\u01DDs \u025F\u0131 \u01DDb\u0250ss\u0250d \u028Do\u05DF\u05DF\u2C6F >-",
|
||||
"create.track_signal.mode_controlled_by_computer": "\u0279\u01DD\u0287nd\u026Fo\u0254 \u028Eq p\u01DD\u05DF\u05DFo\u0279\u0287uo\u0254 s\u0131 \u01DDpo\u026F \u05DF\u0250ub\u0131S",
|
||||
"create.track_target.clear": "uo\u0131\u0287\u0254\u01DD\u05DF\u01DDs \u029E\u0254\u0250\u0279\u0287 p\u01DD\u0279\u0250\u01DD\u05DF\u0186",
|
||||
"create.track_target.invalid": "\u01DD\u0279\u01DD\u0265 \u029E\u0254\u0250\u0279\u0287 s\u0131\u0265\u0287 \u0287\u01DDb\u0279\u0250\u0287 \u0287ouu\u0250\u0186",
|
||||
"create.track_target.missing": "\u0287s\u0279\u0131\u025F \u029E\u0254\u0250\u0279\u0287 u\u0131\u0250\u0279\u0287 p\u01DD\u0287\u01DDb\u0279\u0250\u0287 \u01DD\u0265\u0287 \u029E\u0254\u0131\u05DF\u0254-\u0287\u0265b\u0131\u1D1A",
|
||||
|
|
|
@ -2606,6 +2606,7 @@
|
|||
"create.track_signal.cannot_change_mode": "Unable to switch mode of this Signal",
|
||||
"create.track_signal.mode_change.cross_signal": "-> Allow passage if section fully traversable",
|
||||
"create.track_signal.mode_change.entry_signal": "-> Allow passage if section unoccupied",
|
||||
"create.track_signal.mode_controlled_by_computer": "Signal mode is controlled by computer",
|
||||
"create.track_target.clear": "Cleared track selection",
|
||||
"create.track_target.invalid": "Cannot target this track here",
|
||||
"create.track_target.missing": "Right-click the targeted train track first",
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package com.simibubi.create.compat.computercraft;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
import com.simibubi.create.compat.computercraft.events.ComputerEvent;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
|
||||
|
@ -49,6 +53,8 @@ public class AbstractComputerBehaviour extends BlockEntityBehaviour {
|
|||
return hasAttachedComputer;
|
||||
}
|
||||
|
||||
public void prepareComputerEvent(@NotNull ComputerEvent event) {}
|
||||
|
||||
@Override
|
||||
public BehaviourType<?> getType() {
|
||||
return TYPE;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
package com.simibubi.create.compat.computercraft.events;
|
||||
|
||||
public interface ComputerEvent {}
|
|
@ -0,0 +1,13 @@
|
|||
package com.simibubi.create.compat.computercraft.events;
|
||||
|
||||
import com.simibubi.create.content.trains.signal.SignalBlockEntity;
|
||||
|
||||
public class SignalStateChangeEvent implements ComputerEvent {
|
||||
|
||||
public SignalBlockEntity.SignalState state;
|
||||
|
||||
public SignalStateChangeEvent(SignalBlockEntity.SignalState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,19 +1,26 @@
|
|||
package com.simibubi.create.compat.computercraft.implementation;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour;
|
||||
import com.simibubi.create.compat.computercraft.events.ComputerEvent;
|
||||
import com.simibubi.create.compat.computercraft.implementation.peripherals.DisplayLinkPeripheral;
|
||||
import com.simibubi.create.compat.computercraft.implementation.peripherals.NixieTubePeripheral;
|
||||
import com.simibubi.create.compat.computercraft.implementation.peripherals.SequencedGearshiftPeripheral;
|
||||
import com.simibubi.create.compat.computercraft.implementation.peripherals.SignalPeripheral;
|
||||
import com.simibubi.create.compat.computercraft.implementation.peripherals.SpeedControllerPeripheral;
|
||||
import com.simibubi.create.compat.computercraft.implementation.peripherals.SpeedGaugePeripheral;
|
||||
import com.simibubi.create.compat.computercraft.implementation.peripherals.StationPeripheral;
|
||||
import com.simibubi.create.compat.computercraft.implementation.peripherals.StressGaugePeripheral;
|
||||
import com.simibubi.create.compat.computercraft.implementation.peripherals.SyncedPeripheral;
|
||||
import com.simibubi.create.content.kinetics.gauge.SpeedGaugeBlockEntity;
|
||||
import com.simibubi.create.content.kinetics.gauge.StressGaugeBlockEntity;
|
||||
import com.simibubi.create.content.kinetics.speedController.SpeedControllerBlockEntity;
|
||||
import com.simibubi.create.content.kinetics.transmission.sequencer.SequencedGearshiftBlockEntity;
|
||||
import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockEntity;
|
||||
import com.simibubi.create.content.redstone.nixieTube.NixieTubeBlockEntity;
|
||||
import com.simibubi.create.content.trains.signal.SignalBlockEntity;
|
||||
import com.simibubi.create.content.trains.station.StationBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
|
||||
|
@ -29,15 +36,15 @@ public class ComputerBehaviour extends AbstractComputerBehaviour {
|
|||
protected static final Capability<IPeripheral> PERIPHERAL_CAPABILITY =
|
||||
CapabilityManager.get(new CapabilityToken<>() {
|
||||
});
|
||||
LazyOptional<IPeripheral> peripheral;
|
||||
NonNullSupplier<IPeripheral> peripheralSupplier;
|
||||
LazyOptional<SyncedPeripheral<?>> peripheral;
|
||||
NonNullSupplier<SyncedPeripheral<?>> peripheralSupplier;
|
||||
|
||||
public ComputerBehaviour(SmartBlockEntity te) {
|
||||
super(te);
|
||||
this.peripheralSupplier = getPeripheralFor(te);
|
||||
}
|
||||
|
||||
public static NonNullSupplier<IPeripheral> getPeripheralFor(SmartBlockEntity be) {
|
||||
public static NonNullSupplier<SyncedPeripheral<?>> getPeripheralFor(SmartBlockEntity be) {
|
||||
if (be instanceof SpeedControllerBlockEntity scbe)
|
||||
return () -> new SpeedControllerPeripheral(scbe, scbe.targetSpeed);
|
||||
if (be instanceof DisplayLinkBlockEntity dlbe)
|
||||
|
@ -46,6 +53,8 @@ public class ComputerBehaviour extends AbstractComputerBehaviour {
|
|||
return () -> new NixieTubePeripheral(ntbe);
|
||||
if (be instanceof SequencedGearshiftBlockEntity sgbe)
|
||||
return () -> new SequencedGearshiftPeripheral(sgbe);
|
||||
if (be instanceof SignalBlockEntity sbe)
|
||||
return () -> new SignalPeripheral(sbe);
|
||||
if (be instanceof SpeedGaugeBlockEntity sgbe)
|
||||
return () -> new SpeedGaugePeripheral(sgbe);
|
||||
if (be instanceof StressGaugeBlockEntity sgbe)
|
||||
|
@ -75,4 +84,10 @@ public class ComputerBehaviour extends AbstractComputerBehaviour {
|
|||
peripheral.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareComputerEvent(@NotNull ComputerEvent event) {
|
||||
if (peripheral != null)
|
||||
peripheral.ifPresent(p -> p.prepareComputerEvent(event));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
package com.simibubi.create.compat.computercraft.implementation.peripherals;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.compat.computercraft.events.ComputerEvent;
|
||||
import com.simibubi.create.compat.computercraft.events.SignalStateChangeEvent;
|
||||
import com.simibubi.create.compat.computercraft.implementation.CreateLuaTable;
|
||||
import com.simibubi.create.content.trains.entity.Train;
|
||||
import com.simibubi.create.content.trains.signal.SignalBlock;
|
||||
import com.simibubi.create.content.trains.signal.SignalBlockEntity;
|
||||
import com.simibubi.create.content.trains.signal.SignalBoundary;
|
||||
import com.simibubi.create.content.trains.signal.SignalEdgeGroup;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.LuaFunction;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
public class SignalPeripheral extends SyncedPeripheral<SignalBlockEntity> {
|
||||
|
||||
public SignalPeripheral(SignalBlockEntity blockEntity) {
|
||||
super(blockEntity);
|
||||
}
|
||||
|
||||
@LuaFunction
|
||||
public final String getState() {
|
||||
return blockEntity.getState().toString();
|
||||
}
|
||||
|
||||
@LuaFunction
|
||||
public final boolean isForcedRed() {
|
||||
return blockEntity.getBlockState().getValue(SignalBlock.POWERED);
|
||||
}
|
||||
|
||||
@LuaFunction(mainThread = true)
|
||||
public final void setForcedRed(boolean powered) {
|
||||
Level level = blockEntity.getLevel();
|
||||
if (level != null)
|
||||
level.setBlock(blockEntity.getBlockPos(),
|
||||
blockEntity.getBlockState().setValue(SignalBlock.POWERED, powered), 2);
|
||||
}
|
||||
|
||||
@LuaFunction
|
||||
public final CreateLuaTable listBlockingTrainNames() throws LuaException {
|
||||
SignalBoundary signal = blockEntity.getSignal();
|
||||
if (signal == null)
|
||||
throw new LuaException("no signal");
|
||||
CreateLuaTable trainList = new CreateLuaTable();
|
||||
int trainCounter = 1;
|
||||
for (boolean current : Iterate.trueAndFalse) {
|
||||
Map<BlockPos, Boolean> set = signal.blockEntities.get(current);
|
||||
if (!set.containsKey(blockEntity.getBlockPos()))
|
||||
continue;
|
||||
UUID group = signal.groups.get(current);
|
||||
Map<UUID, SignalEdgeGroup> signalEdgeGroups = Create.RAILWAYS.signalEdgeGroups;
|
||||
SignalEdgeGroup signalEdgeGroup = signalEdgeGroups.get(group);
|
||||
for (Train train : signalEdgeGroup.trains) {
|
||||
trainList.put(trainCounter, train.name.getString());
|
||||
trainCounter += 1;
|
||||
}
|
||||
}
|
||||
return trainList;
|
||||
}
|
||||
|
||||
@LuaFunction
|
||||
public final String getSignalType() throws LuaException {
|
||||
SignalBoundary signal = blockEntity.getSignal();
|
||||
if (signal != null) {
|
||||
return signal.getTypeFor(blockEntity.getBlockPos()).toString();
|
||||
} else {
|
||||
throw new LuaException("no signal");
|
||||
}
|
||||
}
|
||||
|
||||
@LuaFunction(mainThread = true)
|
||||
public final void cycleSignalType() throws LuaException {
|
||||
SignalBoundary signal = blockEntity.getSignal();
|
||||
if (signal != null) {
|
||||
signal.cycleSignalType(blockEntity.getBlockPos());
|
||||
} else {
|
||||
throw new LuaException("no signal");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareComputerEvent(@NotNull ComputerEvent event) {
|
||||
if (event instanceof SignalStateChangeEvent ssce) {
|
||||
queueEvent("train_signal_state_change", ssce.state.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getType() {
|
||||
return "Create_Signal";
|
||||
}
|
||||
|
||||
}
|
|
@ -63,4 +63,21 @@ public abstract class SyncedPeripheral<T extends SmartBlockEntity> implements IP
|
|||
return this == other;
|
||||
}
|
||||
|
||||
public void prepareComputerEvent(@NotNull ComputerEvent event) {}
|
||||
|
||||
/**
|
||||
* Queue an event to all attached computers. Adds the peripheral attachment name as 1st event argument, followed by
|
||||
* any optional arguments passed to this method.
|
||||
*/
|
||||
protected void queueEvent(@NotNull String event, @Nullable Object... arguments) {
|
||||
Object[] sourceAndArgs = new Object[arguments.length + 1];
|
||||
System.arraycopy(arguments, 0, sourceAndArgs, 1, arguments.length);
|
||||
synchronized (computers) {
|
||||
for (IComputerAccess computer : computers) {
|
||||
sourceAndArgs[0] = computer.getAttachmentName();
|
||||
computer.queueEvent(event, sourceAndArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.simibubi.create.content.trains.signal;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -76,7 +77,12 @@ public class SignalBlock extends Block implements IBE<SignalBlockEntity>, IWrenc
|
|||
if (pLevel.isClientSide)
|
||||
return;
|
||||
boolean powered = pState.getValue(POWERED);
|
||||
if (powered == pLevel.hasNeighborSignal(pPos))
|
||||
Optional<SignalBlockEntity> ste = getBlockEntityOptional(pLevel, pPos);
|
||||
boolean neighborPowered = false;
|
||||
if (ste.isEmpty() || !ste.get().computerBehaviour.hasAttachedComputer()) {
|
||||
powered = pLevel.hasNeighborSignal(pPos);
|
||||
}
|
||||
if (powered == neighborPowered)
|
||||
return;
|
||||
if (powered) {
|
||||
pLevel.scheduleTick(pPos, this, 4);
|
||||
|
@ -87,10 +93,11 @@ public class SignalBlock extends Block implements IBE<SignalBlockEntity>, IWrenc
|
|||
|
||||
@Override
|
||||
public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, Random pRand) {
|
||||
if (pState.getValue(POWERED) && !pLevel.hasNeighborSignal(pPos))
|
||||
Optional<SignalBlockEntity> ste = getBlockEntityOptional(pLevel, pPos);
|
||||
if ((ste.isEmpty() || !ste.get().computerBehaviour.hasAttachedComputer()) && pState.getValue(POWERED) && !pLevel.hasNeighborSignal(pPos))
|
||||
pLevel.setBlock(pPos, pState.cycle(POWERED), 2);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
IBE.onRemove(state, worldIn, pos, newState);
|
||||
|
@ -108,8 +115,13 @@ public class SignalBlock extends Block implements IBE<SignalBlockEntity>, IWrenc
|
|||
if (level.isClientSide)
|
||||
return InteractionResult.SUCCESS;
|
||||
withBlockEntityDo(level, pos, ste -> {
|
||||
SignalBoundary signal = ste.getSignal();
|
||||
Player player = context.getPlayer();
|
||||
if (ste.computerBehaviour.hasAttachedComputer()) {
|
||||
if (player != null)
|
||||
player.displayClientMessage(Lang.translateDirect("track_signal.mode_controlled_by_computer"), true);
|
||||
return;
|
||||
}
|
||||
SignalBoundary signal = ste.getSignal();
|
||||
if (signal != null) {
|
||||
signal.cycleSignalType(pos);
|
||||
if (player != null)
|
||||
|
|
|
@ -3,7 +3,12 @@ package com.simibubi.create.content.trains.signal;
|
|||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour;
|
||||
import com.simibubi.create.compat.computercraft.ComputerCraftProxy;
|
||||
import com.simibubi.create.compat.computercraft.events.SignalStateChangeEvent;
|
||||
import com.simibubi.create.content.contraptions.ITransformableBlockEntity;
|
||||
import com.simibubi.create.content.contraptions.StructureTransform;
|
||||
import com.simibubi.create.content.trains.graph.EdgePointType;
|
||||
|
@ -14,10 +19,13 @@ import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour
|
|||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
public class SignalBlockEntity extends SmartBlockEntity implements ITransformableBlockEntity {
|
||||
|
||||
|
@ -47,6 +55,7 @@ public class SignalBlockEntity extends SmartBlockEntity implements ITransformabl
|
|||
private OverlayState overlay;
|
||||
private int switchToRedAfterTrainEntered;
|
||||
private boolean lastReportedPower;
|
||||
public AbstractComputerBehaviour computerBehaviour;
|
||||
|
||||
public SignalBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
|
@ -85,6 +94,7 @@ public class SignalBlockEntity extends SmartBlockEntity implements ITransformabl
|
|||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||
edgePoint = new TrackTargetingBehaviour<>(this, EdgePointType.SIGNAL);
|
||||
behaviours.add(edgePoint);
|
||||
behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -151,9 +161,24 @@ public class SignalBlockEntity extends SmartBlockEntity implements ITransformabl
|
|||
return;
|
||||
this.state = state;
|
||||
switchToRedAfterTrainEntered = state == SignalState.GREEN || state == SignalState.YELLOW ? 15 : 0;
|
||||
if (computerBehaviour.hasAttachedComputer())
|
||||
computerBehaviour.prepareComputerEvent(new SignalStateChangeEvent(state));
|
||||
notifyUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @NotNull LazyOptional<T> getCapability(@NotNull Capability<T> cap, Direction side) {
|
||||
if (computerBehaviour.isPeripheralCap(cap))
|
||||
return computerBehaviour.getPeripheralCapability();
|
||||
return super.getCapability(cap, side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateCaps() {
|
||||
super.invalidateCaps();
|
||||
computerBehaviour.removePeripheral();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AABB createRenderBoundingBox() {
|
||||
return new AABB(worldPosition, edgePoint.getGlobalPosition()).inflate(2);
|
||||
|
|
|
@ -863,6 +863,7 @@
|
|||
"create.track_signal.cannot_change_mode": "Unable to switch mode of this Signal",
|
||||
"create.track_signal.mode_change.entry_signal": "-> Allow passage if section unoccupied",
|
||||
"create.track_signal.mode_change.cross_signal": "-> Allow passage if section fully traversable",
|
||||
"create.track_signal.mode_controlled_by_computer": "Signal mode is controlled by computer",
|
||||
|
||||
"create.contraption.controls.start_controlling": "Now controlling: %1$s",
|
||||
"create.contraption.controls.stop_controlling": "Stopped controlling contraption",
|
||||
|
|
|
@ -2594,6 +2594,7 @@
|
|||
"create.track_signal.cannot_change_mode": "No se puede cambiar el modo de esta señal",
|
||||
"create.track_signal.mode_change.cross_signal": "-> Permitir entrada si la sección se puede atravesar por completo",
|
||||
"create.track_signal.mode_change.entry_signal": "-> Permitir entrada si la sección está desocupada",
|
||||
"create.track_signal.mode_controlled_by_computer": "El modo de esta señal está siendo controlado por un ordenador",
|
||||
"create.track_target.clear": "Selección de vía borrada",
|
||||
"create.track_target.invalid": "No se puede marcar esta vía como objetivo",
|
||||
"create.track_target.missing": "Primero haz clic derecho en la vía objetivo",
|
||||
|
|
|
@ -2594,6 +2594,7 @@
|
|||
"create.track_signal.cannot_change_mode": "No se puede cambiar el modo de esta señal",
|
||||
"create.track_signal.mode_change.cross_signal": "-> Permitir entrada si la sección se puede atravesar por completo",
|
||||
"create.track_signal.mode_change.entry_signal": "-> Permitir entrada si la sección está desocupada",
|
||||
"create.track_signal.mode_controlled_by_computer": "El modo de esta señal está siendo controlado por un ordenador",
|
||||
"create.track_target.clear": "Selección de vía borrada",
|
||||
"create.track_target.invalid": "No se puede marcar esta vía como objetivo",
|
||||
"create.track_target.missing": "Primero haz clic derecho en la vía objetivo",
|
||||
|
|
|
@ -2594,6 +2594,7 @@
|
|||
"create.track_signal.cannot_change_mode": "Incapable de changer le mode de ce signal",
|
||||
"create.track_signal.mode_change.cross_signal": "-> Autoriser le passage si la section est entièrement traversable",
|
||||
"create.track_signal.mode_change.entry_signal": "-> Autoriser le passage si la section est inoccupée",
|
||||
"create.track_signal.mode_controlled_by_computer": "Le mode de ce signal est contrôlé par un ordinateur",
|
||||
"create.track_target.clear": "Sélection du rail effacée",
|
||||
"create.track_target.invalid": "Ne peut pas cibler ce rail ici",
|
||||
"create.track_target.missing": "Faites clic droit sur le rail ciblé d'abord",
|
||||
|
|
Loading…
Reference in a new issue