Don't open sesame

- Added door controls to elevator contact and train station UI
This commit is contained in:
simibubi 2023-02-25 14:15:31 +01:00
parent a3e7dd5ced
commit 68eccd1d51
19 changed files with 366 additions and 41 deletions

View file

@ -566,7 +566,7 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
3054a5519fbf91481b0c9c8160a20679fa9530da assets/create/lang/en_ud.json
8db7da2dab7745aa409e536d7a36cbe9fcce21a4 assets/create/lang/en_us.json
093dfa9846e481071cd27239b4d66760848b160e 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

View file

@ -1654,6 +1654,20 @@
"create.contraption.controls.actor_toggle.on": "On",
"create.contraption.controls.actor_toggle.off": "Off",
"create.contraption.controls.floor_unreachable": "Unreachable",
"create.contraption.door_control": "Onboard Door Control",
"create.contraption.door_control.all": "Open All Doors",
"create.contraption.door_control.all.short": "Open All",
"create.contraption.door_control.north": "North Side Only",
"create.contraption.door_control.north.short": "North",
"create.contraption.door_control.east": "East Side Only",
"create.contraption.door_control.east.short": "East",
"create.contraption.door_control.south": "South Side Only",
"create.contraption.door_control.south.short": "South",
"create.contraption.door_control.west": "West Side Only",
"create.contraption.door_control.west.short": "West",
"create.contraption.door_control.none": "Keep Doors Closed",
"create.contraption.door_control.none.short": "None",
"create.contraption.door_control.player_facing": "You are facing: %1$s",
"create.display_link.set": "Targeted position selected",
"create.display_link.success": "Successfully bound to targeted position",

View file

@ -0,0 +1,76 @@
package com.simibubi.create.content.contraptions.components.actors;
import java.util.Arrays;
import java.util.function.Consumer;
import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.gui.widget.SelectionScrollInput;
import com.simibubi.create.foundation.utility.Components;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.client.Minecraft;
import net.minecraft.core.Direction;
import net.minecraft.world.entity.Entity;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public enum DoorControl {
ALL, NORTH, EAST, SOUTH, WEST, NONE;
private static String[] valuesAsString() {
DoorControl[] values = values();
return Arrays.stream(values)
.map(dc -> Lang.asId(dc.name()))
.toList()
.toArray(new String[values.length]);
}
public boolean matches(Direction doorDirection) {
return switch (this) {
case ALL -> true;
case NORTH -> doorDirection == Direction.NORTH;
case EAST -> doorDirection == Direction.EAST;
case SOUTH -> doorDirection == Direction.SOUTH;
case WEST -> doorDirection == Direction.WEST;
default -> false;
};
}
@OnlyIn(Dist.CLIENT)
public static Pair<ScrollInput, Label> createWidget(int x, int y, Consumer<DoorControl> callback,
DoorControl initial) {
DoorControl playerFacing = NONE;
Entity cameraEntity = Minecraft.getInstance().cameraEntity;
if (cameraEntity != null) {
Direction direction = cameraEntity.getDirection();
if (direction == Direction.EAST)
playerFacing = EAST;
if (direction == Direction.WEST)
playerFacing = WEST;
if (direction == Direction.NORTH)
playerFacing = NORTH;
if (direction == Direction.SOUTH)
playerFacing = SOUTH;
}
Label label = new Label(x + 4, y + 6, Components.empty()).withShadow();
ScrollInput input = new SelectionScrollInput(x, y, 53, 16)
.forOptions(Lang.translatedOptions("contraption.door_control", valuesAsString()))
.titled(Lang.translateDirect("contraption.door_control"))
.calling(s -> {
DoorControl mode = values()[s];
label.text = Lang.translateDirect("contraption.door_control." + Lang.asId(mode.name()) + ".short");
callback.accept(mode);
})
.addHint(Lang.translateDirect("contraption.door_control.player_facing",
Lang.translateDirect("contraption.door_control." + Lang.asId(playerFacing.name()) + ".short")))
.setState(initial.ordinal());
input.onChanged();
return Pair.of(input, label);
}
}

View file

@ -0,0 +1,45 @@
package com.simibubi.create.content.contraptions.components.actors;
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType;
import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.nbt.CompoundTag;
public class DoorControlBehaviour extends BlockEntityBehaviour {
public static final BehaviourType<DoorControlBehaviour> TYPE = new BehaviourType<>();
public DoorControl mode;
public DoorControlBehaviour(SmartBlockEntity be) {
super(be);
mode = DoorControl.ALL;
}
public void set(DoorControl mode) {
if (this.mode == mode)
return;
this.mode = mode;
blockEntity.notifyUpdate();
}
@Override
public void write(CompoundTag nbt, boolean clientPacket) {
NBTHelper.writeEnum(nbt, "DoorControl", mode);
super.write(nbt, clientPacket);
}
@Override
public void read(CompoundTag nbt, boolean clientPacket) {
mode = NBTHelper.readEnum(nbt, "DoorControl", DoorControl.class);
super.read(nbt, clientPacket);
}
@Override
public BehaviourType<?> getType() {
return TYPE;
}
}

View file

@ -212,7 +212,8 @@ public class ElevatorContactBlock extends WrenchableDirectionalBlock
@OnlyIn(value = Dist.CLIENT)
protected void displayScreen(ElevatorContactBlockEntity be, Player player) {
if (player instanceof LocalPlayer)
ScreenOpener.open(new ElevatorContactScreen(be.getBlockPos(), be.shortName, be.longName));
ScreenOpener
.open(new ElevatorContactScreen(be.getBlockPos(), be.shortName, be.longName, be.doorControls.mode));
}
public static int getLight(BlockState state) {

View file

@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.el
import java.util.List;
import com.simibubi.create.content.contraptions.components.actors.DoorControlBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.elevator.ElevatorColumn.ColumnCoords;
import com.simibubi.create.content.logistics.block.display.DisplayLinkBlock;
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
@ -16,6 +17,7 @@ import net.minecraft.world.level.block.state.BlockState;
public class ElevatorContactBlockEntity extends SmartBlockEntity {
public DoorControlBehaviour doorControls;
public ColumnCoords columnCoords;
public boolean activateBlock;
@ -35,7 +37,9 @@ public class ElevatorContactBlockEntity extends SmartBlockEntity {
}
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {}
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(doorControls = new DoorControlBehaviour(this));
}
@Override
protected void write(CompoundTag tag, boolean clientPacket) {

View file

@ -1,40 +1,47 @@
package com.simibubi.create.content.contraptions.components.structureMovement.elevator;
import com.simibubi.create.content.contraptions.components.actors.DoorControl;
import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.Mth;
public class ElevatorContactEditPacket extends BlockEntityConfigurationPacket<ElevatorContactBlockEntity> {
private String shortName;
private String longName;
private DoorControl doorControl;
public ElevatorContactEditPacket(BlockPos pos, String shortName, String longName) {
public ElevatorContactEditPacket(BlockPos pos, String shortName, String longName, DoorControl doorControl) {
super(pos);
this.shortName = shortName;
this.longName = longName;
this.doorControl = doorControl;
}
public ElevatorContactEditPacket(FriendlyByteBuf buffer) {
super(buffer);
}
@Override
protected void writeSettings(FriendlyByteBuf buffer) {
buffer.writeUtf(shortName, 4);
buffer.writeUtf(longName, 30);
buffer.writeVarInt(doorControl.ordinal());
}
@Override
protected void readSettings(FriendlyByteBuf buffer) {
shortName = buffer.readUtf(4);
longName = buffer.readUtf(30);
doorControl = DoorControl.values()[Mth.clamp(buffer.readVarInt(), 0, DoorControl.values().length)];
}
@Override
protected void applySettings(ElevatorContactBlockEntity be) {
be.updateName(shortName, longName);
be.doorControls.set(doorControl);
}
}

View file

@ -5,15 +5,19 @@ import org.lwjgl.glfw.GLFW;
import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.actors.DoorControl;
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.element.GuiGameElement;
import com.simibubi.create.foundation.gui.widget.IconButton;
import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.gui.widget.TooltipArea;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.Components;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.EditBox;
@ -31,12 +35,14 @@ public class ElevatorContactScreen extends AbstractSimiScreen {
private String shortName;
private String longName;
private DoorControl doorControl;
private BlockPos pos;
public ElevatorContactScreen(BlockPos pos, String prevShortName, String prevLongName) {
public ElevatorContactScreen(BlockPos pos, String prevShortName, String prevLongName, DoorControl prevDoorControl) {
super(Lang.translateDirect("elevator_contact.title"));
this.pos = pos;
this.doorControl = prevDoorControl;
background = AllGuiTextures.ELEVATOR_CONTACT;
this.shortName = prevShortName;
this.longName = prevLongName;
@ -88,6 +94,10 @@ public class ElevatorContactScreen extends AbstractSimiScreen {
.component(),
rmbToEdit)));
Pair<ScrollInput, Label> doorControlWidgets =
DoorControl.createWidget(x + 58, y + 57, mode -> doorControl = mode, doorControl);
addRenderableWidget(doorControlWidgets.getFirst());
addRenderableWidget(doorControlWidgets.getSecond());
}
private int centerInput(int x) {
@ -122,6 +132,7 @@ public class ElevatorContactScreen extends AbstractSimiScreen {
.scale(5)
.render(ms);
itemRenderer.renderGuiItem(AllBlocks.TRAIN_DOOR.asStack(), x + 37, y + 58);
}
@Override
@ -164,7 +175,8 @@ public class ElevatorContactScreen extends AbstractSimiScreen {
}
private void confirm() {
AllPackets.getChannel().sendToServer(new ElevatorContactEditPacket(pos, shortName, longName));
AllPackets.getChannel()
.sendToServer(new ElevatorContactEditPacket(pos, shortName, longName, doorControl));
onClose();
}

View file

@ -1,23 +1,37 @@
package com.simibubi.create.content.curiosities.deco;
import java.lang.ref.WeakReference;
import java.util.Map;
import com.simibubi.create.content.contraptions.components.actors.DoorControl;
import com.simibubi.create.content.contraptions.components.actors.DoorControlBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.elevator.ElevatorColumn;
import com.simibubi.create.content.contraptions.components.structureMovement.elevator.ElevatorColumn.ColumnCoords;
import com.simibubi.create.content.contraptions.components.structureMovement.elevator.ElevatorContraption;
import com.simibubi.create.content.logistics.trains.entity.Carriage;
import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity;
import com.simibubi.create.content.logistics.trains.entity.CarriageSyncData;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.DoorBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
import net.minecraft.world.phys.Vec3;
public class SlidingDoorMovementBehaviour implements MovementBehaviour {
@ -25,12 +39,12 @@ public class SlidingDoorMovementBehaviour implements MovementBehaviour {
public boolean renderAsNormalBlockEntity() {
return true;
}
@Override
public boolean mustTickWhileDisabled() {
return true;
}
@Override
public void tick(MovementContext context) {
StructureBlockInfo structureBlockInfo = context.contraption.getBlocks()
@ -43,7 +57,7 @@ public class SlidingDoorMovementBehaviour implements MovementBehaviour {
tickOpen(context, open);
Map<BlockPos, BlockEntity> tes = context.contraption.presentBlockEntities;
if (!(tes.get(context.localPos) instanceof SlidingDoorBlockEntity doorTE))
if (!(tes.get(context.localPos)instanceof SlidingDoorBlockEntity doorTE))
return;
boolean wasSettled = doorTE.animation.settled();
doorTE.animation.chase(open ? 1 : 0, .15f, Chaser.LINEAR);
@ -105,14 +119,90 @@ public class SlidingDoorMovementBehaviour implements MovementBehaviour {
protected boolean shouldOpen(MovementContext context) {
if (context.disabled)
return false;
if (context.contraption instanceof ElevatorContraption ec && ec.arrived)
return true;
if (context.contraption.entity instanceof CarriageContraptionEntity cce) {
CarriageSyncData carriageData = cce.getCarriageData();
if (Math.abs(carriageData.distanceToDestination) > 1)
return false;
Contraption contraption = context.contraption;
boolean canOpen = context.motion.length() < 1 / 128f && !contraption.entity.isStalled()
|| contraption instanceof ElevatorContraption ec && ec.arrived;
if (!canOpen) {
context.temporaryData = null;
return false;
}
return context.motion.length() < 1 / 128f && !context.contraption.entity.isStalled();
if (context.temporaryData instanceof WeakReference<?> wr && wr.get()instanceof DoorControlBehaviour dcb)
if (dcb.blockEntity != null && !dcb.blockEntity.isRemoved())
return shouldOpenAt(dcb, context);
context.temporaryData = null;
DoorControlBehaviour doorControls = null;
if (contraption instanceof ElevatorContraption ec)
doorControls = getElevatorDoorControl(ec, context);
if (context.contraption.entity instanceof CarriageContraptionEntity cce)
doorControls = getTrainStationDoorControl(cce, context);
if (doorControls == null)
return false;
context.temporaryData = new WeakReference<>(doorControls);
return shouldOpenAt(doorControls, context);
}
protected boolean shouldOpenAt(DoorControlBehaviour controller, MovementContext context) {
if (controller.mode == DoorControl.ALL)
return true;
if (controller.mode == DoorControl.NONE)
return false;
return controller.mode.matches(getDoorFacing(context));
}
protected DoorControlBehaviour getElevatorDoorControl(ElevatorContraption ec, MovementContext context) {
Integer currentTargetY = ec.getCurrentTargetY(context.world);
if (currentTargetY == null)
return null;
ColumnCoords columnCoords = ec.getGlobalColumn();
if (columnCoords == null)
return null;
ElevatorColumn elevatorColumn = ElevatorColumn.get(context.world, columnCoords);
if (elevatorColumn == null)
return null;
return BlockEntityBehaviour.get(context.world, elevatorColumn.contactAt(currentTargetY),
DoorControlBehaviour.TYPE);
}
protected DoorControlBehaviour getTrainStationDoorControl(CarriageContraptionEntity cce, MovementContext context) {
Carriage carriage = cce.getCarriage();
if (carriage == null || carriage.train == null)
return null;
GlobalStation currentStation = carriage.train.getCurrentStation();
if (currentStation == null)
return null;
BlockPos stationPos = currentStation.getBlockEntityPos();
ResourceKey<Level> stationDim = currentStation.getBlockEntityDimension();
MinecraftServer server = context.world.getServer();
if (server == null)
return null;
ServerLevel stationLevel = server.getLevel(stationDim);
if (stationLevel == null || !stationLevel.isLoaded(stationPos))
return null;
return BlockEntityBehaviour.get(stationLevel, stationPos, DoorControlBehaviour.TYPE);
}
protected Direction getDoorFacing(MovementContext context) {
Direction stateFacing = context.state.getValue(DoorBlock.FACING);
Direction originalFacing = Direction.get(AxisDirection.POSITIVE, stateFacing.getAxis());
Vec3 centerOfContraption = context.contraption.bounds.getCenter();
Vec3 diff = Vec3.atCenterOf(context.localPos)
.add(Vec3.atLowerCornerOf(stateFacing.getNormal())
.scale(-.45f))
.subtract(centerOfContraption);
if (originalFacing.getAxis()
.choose(diff.x, diff.y, diff.z) < 0)
originalFacing = originalFacing.getOpposite();
Vec3 directionVec = Vec3.atLowerCornerOf(originalFacing.getNormal());
directionVec = context.rotation.apply(directionVec);
return Direction.getNearest(directionVec.x, directionVec.y, directionVec.z);
}
}

View file

@ -65,14 +65,16 @@ public class AssemblyScreen extends AbstractStationScreen {
toggleAssemblyButton.active = false;
toggleAssemblyButton.setToolTip(Lang.translateDirect("station.assemble_train"));
toggleAssemblyButton.withCallback(() -> {
AllPackets.getChannel().sendToServer(StationEditPacket.tryAssemble(blockEntity.getBlockPos()));
AllPackets.getChannel()
.sendToServer(StationEditPacket.tryAssemble(blockEntity.getBlockPos()));
});
quitAssembly = new IconButton(x + 73, by, AllIcons.I_DISABLE);
quitAssembly.active = true;
quitAssembly.setToolTip(Lang.translateDirect("station.cancel"));
quitAssembly.withCallback(() -> {
AllPackets.getChannel().sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name));
AllPackets.getChannel()
.sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name, null));
minecraft.setScreen(new StationScreen(blockEntity, station));
});
@ -90,7 +92,8 @@ public class AssemblyScreen extends AbstractStationScreen {
toggleAssemblyButton.active = blockEntity.bogeyCount > 0 || train != null;
if (train != null) {
AllPackets.getChannel().sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name));
AllPackets.getChannel()
.sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name, null));
minecraft.setScreen(new StationScreen(blockEntity, station));
for (Carriage carriage : train.carriages)
carriage.updateConductors();
@ -105,10 +108,12 @@ public class AssemblyScreen extends AbstractStationScreen {
toggleAssemblyButton.setToolTip(Lang.translateDirect("station.assemble_train"));
toggleAssemblyButton.setIcon(AllGuiTextures.I_ASSEMBLE_TRAIN);
toggleAssemblyButton.withCallback(() -> {
AllPackets.getChannel().sendToServer(StationEditPacket.tryAssemble(blockEntity.getBlockPos()));
AllPackets.getChannel()
.sendToServer(StationEditPacket.tryAssemble(blockEntity.getBlockPos()));
});
} else {
AllPackets.getChannel().sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name));
AllPackets.getChannel()
.sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name, null));
minecraft.setScreen(new StationScreen(blockEntity, station));
}
}
@ -128,8 +133,8 @@ public class AssemblyScreen extends AbstractStationScreen {
font.draw(ms, text, x + 97 - font.width(text) / 2, y + 47, 0x775B5B);
int offset = 0;
if (blockEntity.failedCarriageIndex != -1) {
font.draw(ms, Lang.translateDirect("station.carriage_number", blockEntity.failedCarriageIndex), x + 30, y + 67,
0x7A7A7A);
font.draw(ms, Lang.translateDirect("station.carriage_number", blockEntity.failedCarriageIndex), x + 30,
y + 67, 0x7A7A7A);
offset += 10;
}
font.drawWordWrap(lastAssemblyException.component, x + 30, y + 67 + offset, 134, 0x775B5B);
@ -158,7 +163,8 @@ public class AssemblyScreen extends AbstractStationScreen {
if (train != null) {
ResourceLocation iconId = iconTypes.get(iconTypeScroll.getState());
train.icon = TrainIconType.byId(iconId);
AllPackets.getChannel().sendToServer(new TrainEditPacket(train.id, "", iconId));
AllPackets.getChannel()
.sendToServer(new TrainEditPacket(train.id, "", iconId));
}
}

View file

@ -16,6 +16,7 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.actors.DoorControlBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlockEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
@ -80,6 +81,7 @@ import net.minecraftforge.network.PacketDistributor;
public class StationBlockEntity extends SmartBlockEntity implements ITransformableBlockEntity {
public TrackTargetingBehaviour<GlobalStation> edgePoint;
public DoorControlBehaviour doorControls;
public LerpedFloat flag;
protected int failedCarriageIndex;
@ -111,6 +113,7 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(edgePoint = new TrackTargetingBehaviour<>(this, EdgePointType.STATION));
behaviours.add(doorControls = new DoorControlBehaviour(this));
behaviours.add(depotBehaviour = new DepotBehaviour(this).onlyAccepts(AllItems.SCHEDULE::isIn)
.withCallback(s -> applyAutoSchedule()));
depotBehaviour.addSubBehaviours(behaviours);

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.actors.DoorControl;
import com.simibubi.create.content.logistics.trains.GraphLocation;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket;
@ -9,6 +10,7 @@ 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.util.Mth;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
@ -20,6 +22,7 @@ public class StationEditPacket extends BlockEntityConfigurationPacket<StationBlo
boolean dropSchedule;
boolean assemblyMode;
Boolean tryAssemble;
DoorControl doorControl;
String name;
public static StationEditPacket dropSchedule(BlockPos pos) {
@ -40,11 +43,12 @@ public class StationEditPacket extends BlockEntityConfigurationPacket<StationBlo
return packet;
}
public static StationEditPacket configure(BlockPos pos, boolean assemble, String name) {
public static StationEditPacket configure(BlockPos pos, boolean assemble, String name, DoorControl doorControl) {
StationEditPacket packet = new StationEditPacket(pos);
packet.assemblyMode = assemble;
packet.tryAssemble = null;
packet.name = name;
packet.doorControl = doorControl;
return packet;
}
@ -61,6 +65,9 @@ public class StationEditPacket extends BlockEntityConfigurationPacket<StationBlo
buffer.writeBoolean(dropSchedule);
if (dropSchedule)
return;
buffer.writeBoolean(doorControl != null);
if (doorControl != null)
buffer.writeVarInt(doorControl.ordinal());
buffer.writeBoolean(tryAssemble != null);
if (tryAssemble != null) {
buffer.writeBoolean(tryAssemble);
@ -76,6 +83,8 @@ public class StationEditPacket extends BlockEntityConfigurationPacket<StationBlo
dropSchedule = true;
return;
}
if (buffer.readBoolean())
doorControl = DoorControl.values()[Mth.clamp(buffer.readVarInt(), 0, DoorControl.values().length)];
name = "";
if (buffer.readBoolean()) {
tryAssemble = buffer.readBoolean();
@ -95,6 +104,9 @@ public class StationEditPacket extends BlockEntityConfigurationPacket<StationBlo
scheduleDropRequested(player, be);
return;
}
if (doorControl != null)
be.doorControls.set(doorControl);
if (!name.isBlank()) {
GlobalStation station = be.getStation();

View file

@ -8,7 +8,9 @@ import com.jozufozu.flywheel.core.PartialModel;
import com.mojang.blaze3d.platform.InputConstants;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.content.contraptions.components.actors.DoorControl;
import com.simibubi.create.content.logistics.trains.entity.Carriage;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.entity.TrainIconType;
@ -16,9 +18,12 @@ import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.gui.widget.IconButton;
import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.Components;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import net.minecraft.ChatFormatting;
@ -37,6 +42,7 @@ public class StationScreen extends AbstractStationScreen {
private int leavingAnimation;
private LerpedFloat trainPosition;
private DoorControl doorControl;
private boolean switchingToAssemblyMode;
@ -47,6 +53,7 @@ public class StationScreen extends AbstractStationScreen {
trainPosition = LerpedFloat.linear()
.startWithValue(0);
switchingToAssemblyMode = false;
doorControl = be.doorControls.mode;
}
@Override
@ -88,8 +95,8 @@ public class StationScreen extends AbstractStationScreen {
dropScheduleButton = new IconButton(x + 73, y + 65, AllIcons.I_VIEW_SCHEDULE);
dropScheduleButton.active = false;
dropScheduleButton.visible = false;
dropScheduleButton
.withCallback(() -> AllPackets.getChannel().sendToServer(StationEditPacket.dropSchedule(blockEntity.getBlockPos())));
dropScheduleButton.withCallback(() -> AllPackets.getChannel()
.sendToServer(StationEditPacket.dropSchedule(blockEntity.getBlockPos())));
addRenderableWidget(dropScheduleButton);
onTextChanged = s -> trainNameBox.x = nameBoxX(s, trainNameBox);
@ -103,6 +110,11 @@ public class StationScreen extends AbstractStationScreen {
trainNameBox.active = false;
tickTrainDisplay();
Pair<ScrollInput, Label> doorControlWidgets =
DoorControl.createWidget(x + 35, y + 102, mode -> doorControl = mode, doorControl);
addRenderableWidget(doorControlWidgets.getFirst());
addRenderableWidget(doorControlWidgets.getSecond());
}
@Override
@ -192,12 +204,13 @@ public class StationScreen extends AbstractStationScreen {
}
boolean trainAtStation = trainPresent();
disassembleTrainButton.active = trainAtStation && blockEntity.trainCanDisassemble && blockEntity.edgePoint.isOrthogonal();
disassembleTrainButton.active =
trainAtStation && blockEntity.trainCanDisassemble && blockEntity.edgePoint.isOrthogonal();
dropScheduleButton.active = blockEntity.trainHasSchedule;
if (blockEntity.trainHasSchedule)
dropScheduleButton.setToolTip(
Lang.translateDirect(blockEntity.trainHasAutoSchedule ? "station.remove_auto_schedule" : "station.remove_schedule"));
dropScheduleButton.setToolTip(Lang.translateDirect(
blockEntity.trainHasAutoSchedule ? "station.remove_auto_schedule" : "station.remove_schedule"));
else
dropScheduleButton.getToolTip()
.clear();
@ -237,6 +250,8 @@ public class StationScreen extends AbstractStationScreen {
if (!nameBox.isFocused())
AllGuiTextures.STATION_EDIT_NAME.render(ms, nameBoxX(text, nameBox) + font.width(text) + 5, y + 1);
itemRenderer.renderGuiItem(AllBlocks.TRAIN_DOOR.asStack(), x + 14, y + 103);
Train train = displayedTrain.get();
if (train == null) {
MutableComponent header = Lang.translateDirect("station.idle");
@ -333,32 +348,38 @@ public class StationScreen extends AbstractStationScreen {
Train train = displayedTrain.get();
if (train != null && !trainNameBox.getValue()
.equals(train.name.getString()))
AllPackets.getChannel().sendToServer(new TrainEditPacket(train.id, trainNameBox.getValue(), train.icon.getId()));
AllPackets.getChannel()
.sendToServer(new TrainEditPacket(train.id, trainNameBox.getValue(), train.icon.getId()));
}
private void syncStationName() {
if (!nameBox.getValue()
.equals(station.name))
AllPackets.getChannel().sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, nameBox.getValue()));
AllPackets.getChannel()
.sendToServer(
StationEditPacket.configure(blockEntity.getBlockPos(), false, nameBox.getValue(), doorControl));
}
@Override
public void removed() {
super.removed();
AllPackets.getChannel()
.sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), switchingToAssemblyMode, nameBox.getValue()));
.sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), switchingToAssemblyMode,
nameBox.getValue(), doorControl));
Train train = displayedTrain.get();
if (train == null)
return;
if (!switchingToAssemblyMode)
AllPackets.getChannel().sendToServer(new TrainEditPacket(train.id, trainNameBox.getValue(), train.icon.getId()));
AllPackets.getChannel()
.sendToServer(new TrainEditPacket(train.id, trainNameBox.getValue(), train.icon.getId()));
else
blockEntity.imminentTrain = null;
}
@Override
protected PartialModel getFlag(float partialTicks) {
return blockEntity.flag.getValue(partialTicks) > 0.75f ? AllPartialModels.STATION_ON : AllPartialModels.STATION_OFF;
return blockEntity.flag.getValue(partialTicks) > 0.75f ? AllPartialModels.STATION_ON
: AllPartialModels.STATION_OFF;
}
}

View file

@ -17,6 +17,7 @@ import net.minecraft.network.chat.Component;
public abstract class AbstractSimiWidget extends AbstractWidget implements TickableGuiEventListener {
public static final int HEADER_RGB = 0x5391E1;
public static final int HINT_RGB = 0x96B7E0;
protected float z;
protected boolean wasHovered = false;

View file

@ -22,6 +22,7 @@ public class ScrollInput extends AbstractSimiWidget {
protected Component title = Lang.translateDirect("gui.scrollInput.defaultTitle");
protected final Component scrollToModify = Lang.translateDirect("gui.scrollInput.scrollToModify");
protected final Component shiftScrollsFaster = Lang.translateDirect("gui.scrollInput.shiftScrollsFaster");
protected Component hint = null;
protected Label displayLabel;
protected boolean inverted;
protected Function<Integer, Component> formatter;
@ -76,6 +77,12 @@ public class ScrollInput extends AbstractSimiWidget {
return this;
}
public ScrollInput addHint(MutableComponent hint) {
this.hint = hint;
updateTooltip();
return this;
}
public ScrollInput withStepFunction(Function<StepContext, Integer> step) {
this.step = step;
return this;
@ -128,7 +135,10 @@ public class ScrollInput extends AbstractSimiWidget {
clampState();
if (priorState != state) {
Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(AllSoundEvents.SCROLL_VALUE.getMainEvent(), 1.5f + 0.1f * (state-min)/(max-min)));
Minecraft.getInstance()
.getSoundManager()
.play(SimpleSoundInstance.forUI(AllSoundEvents.SCROLL_VALUE.getMainEvent(),
1.5f + 0.1f * (state - min) / (max - min)));
onChanged();
}
@ -160,6 +170,9 @@ public class ScrollInput extends AbstractSimiWidget {
return;
toolTip.add(title.plainCopy()
.withStyle(s -> s.withColor(HEADER_RGB)));
if (hint != null)
toolTip.add(hint.plainCopy()
.withStyle(s -> s.withColor(HINT_RGB)));
toolTip.add(scrollToModify.plainCopy()
.withStyle(ChatFormatting.ITALIC, ChatFormatting.DARK_GRAY));
toolTip.add(shiftScrollsFaster.plainCopy()

View file

@ -43,7 +43,8 @@ public class SelectionScrollInput extends ScrollInput {
if (this.min + 1 == min)
min--;
if (min > this.min)
toolTip.add(Components.literal("> ...").withStyle(ChatFormatting.GRAY));
toolTip.add(Components.literal("> ...")
.withStyle(ChatFormatting.GRAY));
if (this.max - 1 == max)
max++;
for (int i = min; i < max; i++) {
@ -59,8 +60,12 @@ public class SelectionScrollInput extends ScrollInput {
.withStyle(ChatFormatting.GRAY));
}
if (max < this.max)
toolTip.add(Components.literal("> ...").withStyle(ChatFormatting.GRAY));
toolTip.add(Components.literal("> ...")
.withStyle(ChatFormatting.GRAY));
if (hint != null)
toolTip.add(hint.plainCopy()
.withStyle(s -> s.withColor(HINT_RGB)));
toolTip.add(scrollToSelect.plainCopy()
.withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC));
}

View file

@ -814,6 +814,21 @@
"create.contraption.controls.actor_toggle.on": "On",
"create.contraption.controls.actor_toggle.off": "Off",
"create.contraption.controls.floor_unreachable": "Unreachable",
"create.contraption.door_control": "Onboard Door Control",
"create.contraption.door_control.all": "Open All Doors",
"create.contraption.door_control.all.short": "Open All",
"create.contraption.door_control.north": "North Side Only",
"create.contraption.door_control.north.short": "North",
"create.contraption.door_control.east": "East Side Only",
"create.contraption.door_control.east.short": "East",
"create.contraption.door_control.south": "South Side Only",
"create.contraption.door_control.south.short": "South",
"create.contraption.door_control.west": "West Side Only",
"create.contraption.door_control.west.short": "West",
"create.contraption.door_control.none": "Keep Doors Closed",
"create.contraption.door_control.none.short": "None",
"create.contraption.door_control.player_facing": "You are facing: %1$s",
"create.display_link.set": "Targeted position selected",
"create.display_link.success": "Successfully bound to targeted position",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB