diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java index 14df715c9..a112055e6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java @@ -6,8 +6,11 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import java.util.UUID; +import javax.annotation.Nullable; + import org.apache.commons.lang3.mutable.MutableInt; import org.apache.commons.lang3.tuple.MutablePair; @@ -21,6 +24,7 @@ import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.components.actors.SeatBlock; import com.simibubi.create.content.contraptions.components.actors.SeatEntity; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsStopControllingPacket; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption; import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionSeatMappingPacket; import com.simibubi.create.foundation.collision.Matrix3d; @@ -39,6 +43,7 @@ import net.minecraft.network.protocol.Packet; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; @@ -63,6 +68,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit private static final EntityDataAccessor STALLED = SynchedEntityData.defineId(AbstractContraptionEntity.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor> CONTROLLED_BY = + SynchedEntityData.defineId(AbstractContraptionEntity.class, EntityDataSerializers.OPTIONAL_UUID); public final Map collidingEntities; @@ -178,6 +185,14 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit return getName(); } + public Optional getControllingPlayer() { + return entityData.get(CONTROLLED_BY); + } + + public void setControllingPlayer(@Nullable UUID playerId) { + entityData.set(CONTROLLED_BY, Optional.ofNullable(playerId)); + } + public boolean startControlling(BlockPos controlsLocalPos, Player player) { return false; } @@ -186,7 +201,13 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit return true; } - public void stopControlling(BlockPos controlsLocalPos) {} + public void stopControlling(BlockPos controlsLocalPos) { + getControllingPlayer().map(level::getPlayerByUUID) + .map(p -> (p instanceof ServerPlayer) ? ((ServerPlayer) p) : null) + .ifPresent(p -> AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> p), + new ControlsStopControllingPacket())); + setControllingPlayer(null); + } public boolean handlePlayerInteraction(Player player, BlockPos localPos, Direction side, InteractionHand interactionHand) { @@ -403,6 +424,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit @Override protected void defineSynchedData() { this.entityData.define(STALLED, false); + this.entityData.define(CONTROLLED_BY, Optional.empty()); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java index 6373f76e1..e8eac8883 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java @@ -113,8 +113,7 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { } public float getInitialYaw() { - return (isInitialOrientationPresent() ? entityData.get(INITIAL_ORIENTATION) : Direction.SOUTH) - .toYRot(); + return (isInitialOrientationPresent() ? entityData.get(INITIAL_ORIENTATION) : Direction.SOUTH).toYRot(); } @Override @@ -177,8 +176,7 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { super.writeAdditional(compound, spawnPacket); if (motionBeforeStall != null) - compound.put("CachedMotion", - newDoubleList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z)); + compound.put("CachedMotion", newDoubleList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z)); Direction optional = entityData.get(INITIAL_ORIENTATION); if (optional.getAxis() @@ -200,7 +198,7 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { @Override public void onSyncedDataUpdated(EntityDataAccessor key) { super.onSyncedDataUpdated(key); - if (key == INITIAL_ORIENTATION && isInitialOrientationPresent() && !manuallyPlaced) + if (INITIAL_ORIENTATION.equals(key) && isInitialOrientationPresent() && !manuallyPlaced) startAtInitialYaw(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java index c217d15ff..90f40f9ac 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java @@ -5,19 +5,14 @@ import java.util.Collection; import java.util.HashSet; import java.util.Vector; -import org.lwjgl.glfw.GLFW; - -import com.mojang.blaze3d.platform.InputConstants; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.ControlsUtil; import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.player.Player; public class ControlsHandler { @@ -29,33 +24,28 @@ public class ControlsHandler { static WeakReference entityRef = new WeakReference<>(null); static BlockPos controlsPos; - public static void controllerClicked(AbstractContraptionEntity entity, BlockPos controllerLocalPos, Player player) { - AbstractContraptionEntity prevEntity = entityRef.get(); - if (prevEntity != null) { - stopControlling(); - if (prevEntity == entity) - return; - } - if (!entity.startControlling(controllerLocalPos, player)) - return; + public static void startControlling(AbstractContraptionEntity entity, BlockPos controllerLocalPos) { entityRef = new WeakReference(entity); controlsPos = controllerLocalPos; + Minecraft.getInstance().player.displayClientMessage( Lang.translate("contraption.controls.start_controlling", entity.getContraptionName()), true); } public static void stopControlling() { - AbstractContraptionEntity abstractContraptionEntity = entityRef.get(); - if (abstractContraptionEntity != null) - abstractContraptionEntity.stopControlling(controlsPos); ControlsUtil.getControls() .forEach(kb -> kb.setDown(ControlsUtil.isActuallyPressed(kb))); + AbstractContraptionEntity abstractContraptionEntity = entityRef.get(); + + if (!currentlyPressed.isEmpty() && abstractContraptionEntity != null) + AllPackets.channel.sendToServer( + new ControlsInputPacket(currentlyPressed, false, abstractContraptionEntity.getId(), controlsPos)); + packetCooldown = 0; entityRef = new WeakReference<>(null); controlsPos = null; -// if (!currentlyPressed.isEmpty()) -// AllPackets.channel.sendToServer(new LinkedControllerInputPacket(currentlyPressed, false)); currentlyPressed.clear(); + Minecraft.getInstance().player.displayClientMessage(Lang.translate("contraption.controls.stop_controlling"), true); } @@ -67,24 +57,6 @@ public class ControlsHandler { if (packetCooldown > 0) packetCooldown--; - Minecraft mc = Minecraft.getInstance(); - LocalPlayer player = mc.player; - - if (player.isSpectator()) { - stopControlling(); - return; - } - if (InputConstants.isKeyDown(mc.getWindow() - .getWindow(), GLFW.GLFW_KEY_ESCAPE)) { - stopControlling(); - return; - } - if (!entity.toGlobalVector(VecHelper.getCenterOf(controlsPos), 1) - .closerThan(player.position(), 10)) { - stopControlling(); - return; - } - Vector controls = ControlsUtil.getControls(); Collection pressedKeys = new HashSet<>(); for (int i = 0; i < controls.size(); i++) { @@ -99,34 +71,24 @@ public class ControlsHandler { // Released Keys if (!releasedKeys.isEmpty()) { -// AllPackets.channel.sendToServer(new LinkedControllerInputPacket(releasedKeys, false, lecternPos)); -// AllSoundEvents.CONTROLLER_CLICK.playAt(player.level, player.blockPosition(), 1f, .5f, true); + AllPackets.channel.sendToServer(new ControlsInputPacket(releasedKeys, false, entity.getId(), controlsPos)); +// AllSoundEvents.CONTROLLER_CLICK.playAt(player.level, player.blockPosition(), 1f, .5f, true); } // Newly Pressed Keys if (!newKeys.isEmpty()) { - if (newKeys.contains(Integer.valueOf(5))) { - stopControlling(); - return; - } - -// AllPackets.channel.sendToServer(new LinkedControllerInputPacket(newKeys, true, lecternPos)); -// packetCooldown = PACKET_RATE; -// AllSoundEvents.CONTROLLER_CLICK.playAt(player.level, player.blockPosition(), 1f, .75f, true); + AllPackets.channel.sendToServer(new ControlsInputPacket(newKeys, true, entity.getId(), controlsPos)); + packetCooldown = PACKET_RATE; +// AllSoundEvents.CONTROLLER_CLICK.playAt(player.level, player.blockPosition(), 1f, .75f, true); } // Keepalive Pressed Keys if (packetCooldown == 0) { -// if (!pressedKeys.isEmpty()) { -// AllPackets.channel.sendToServer(new LinkedControllerInputPacket(pressedKeys, true, lecternPos)); -// packetCooldown = PACKET_RATE; -// } - } - - // TODO do this server side - if (!entity.control(controlsPos, pressedKeys, player)) { - stopControlling(); - return; + if (!pressedKeys.isEmpty()) { + AllPackets.channel + .sendToServer(new ControlsInputPacket(pressedKeys, true, entity.getId(), controlsPos)); + packetCooldown = PACKET_RATE; + } } currentlyPressed = pressedKeys; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInputPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInputPacket.java new file mode 100644 index 000000000..f36dd55a6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInputPacket.java @@ -0,0 +1,76 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.UUID; +import java.util.function.Supplier; + +import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ControlsInputPacket extends SimplePacketBase { + + private Collection activatedButtons; + private boolean press; + private int contraptionEntityId; + private BlockPos controlsPos; + + public ControlsInputPacket(Collection activatedButtons, boolean press, int contraptionEntityId, + BlockPos controlsPos) { + this.contraptionEntityId = contraptionEntityId; + this.activatedButtons = activatedButtons; + this.press = press; + this.controlsPos = controlsPos; + } + + public ControlsInputPacket(FriendlyByteBuf buffer) { + contraptionEntityId = buffer.readInt(); + activatedButtons = new ArrayList<>(); + press = buffer.readBoolean(); + int size = buffer.readVarInt(); + for (int i = 0; i < size; i++) + activatedButtons.add(buffer.readVarInt()); + controlsPos = buffer.readBlockPos(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(contraptionEntityId); + buffer.writeBoolean(press); + buffer.writeVarInt(activatedButtons.size()); + activatedButtons.forEach(buffer::writeVarInt); + buffer.writeBlockPos(controlsPos); + } + + @Override + public void handle(Supplier context) { + Context ctx = context.get(); + ctx.enqueueWork(() -> { + ServerPlayer player = ctx.getSender(); + Level world = player.getCommandSenderWorld(); + UUID uniqueID = player.getUUID(); + + if (player.isSpectator() && press) + return; + + Entity entity = world.getEntity(contraptionEntityId); + if (!(entity instanceof AbstractContraptionEntity ace)) + return; + if (ace.toGlobalVector(Vec3.atCenterOf(controlsPos), 0) + .distanceTo(player.position()) > 10) + return; + + ControlsServerHandler.receivePressed(world, ace, controlsPos, uniqueID, activatedButtons, press); + }); + ctx.setPacketHandled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInteractionBehaviour.java index d47ef22c8..d64f24d1a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInteractionBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInteractionBehaviour.java @@ -1,5 +1,8 @@ package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; +import java.util.UUID; + +import com.google.common.base.Objects; import com.simibubi.create.AllItems; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour; @@ -7,6 +10,8 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Player; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; public class ControlsInteractionBehaviour extends MovingInteractionBehaviour { @@ -15,8 +20,23 @@ public class ControlsInteractionBehaviour extends MovingInteractionBehaviour { AbstractContraptionEntity contraptionEntity) { if (AllItems.WRENCH.isIn(player.getItemInHand(activeHand))) return false; + + UUID currentlyControlling = contraptionEntity.getControllingPlayer() + .orElse(null); + + if (currentlyControlling != null) { + contraptionEntity.stopControlling(localPos); + if (Objects.equal(currentlyControlling, player.getUUID())) + return true; + } + + if (!contraptionEntity.startControlling(localPos, player)) + return false; + + contraptionEntity.setControllingPlayer(player.getUUID()); if (player.level.isClientSide) - ControlsHandler.controllerClicked(contraptionEntity, localPos, player); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, + () -> () -> ControlsHandler.startControlling(contraptionEntity, localPos)); return true; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsMovementBehaviour.java index 1a169189a..c8d8921c5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsMovementBehaviour.java @@ -3,50 +3,80 @@ package com.simibubi.create.content.contraptions.components.structureMovement.in import java.util.Collection; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; 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.render.ContraptionMatrices; -import com.simibubi.create.content.logistics.trains.entity.Carriage; import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.core.Direction; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; public class ControlsMovementBehaviour extends MovementBehaviour { - // TODO: this is specific to Carriage Contraptions - need to move this behaviour - // there - LerpedFloat steering = LerpedFloat.linear(); - LerpedFloat speed = LerpedFloat.linear(); - LerpedFloat equipAnimation = LerpedFloat.linear(); + // TODO: rendering the levers should be specific to Carriage Contraptions - + static class LeverAngles { + LerpedFloat steering = LerpedFloat.linear(); + LerpedFloat speed = LerpedFloat.linear(); + LerpedFloat equipAnimation = LerpedFloat.linear(); + } @Override public void tick(MovementContext context) { - steering.tickChaser(); - speed.tickChaser(); - equipAnimation.tickChaser(); super.tick(context); + if (!context.world.isClientSide) + return; + if (!(context.temporaryData instanceof LeverAngles)) + context.temporaryData = new LeverAngles(); + LeverAngles angles = (LeverAngles) context.temporaryData; + angles.steering.tickChaser(); + angles.speed.tickChaser(); + angles.equipAnimation.tickChaser(); } @Override @OnlyIn(Dist.CLIENT) public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, ContraptionMatrices matrices, MultiBufferSource buffer) { - if (ControlsHandler.entityRef.get() == context.contraption.entity && ControlsHandler.controlsPos != null + if (!(context.temporaryData instanceof LeverAngles angles)) + return; + + AbstractContraptionEntity entity = context.contraption.entity; + if (!(entity instanceof CarriageContraptionEntity cce)) + return; + + StructureBlockInfo info = context.contraption.getBlocks() + .get(context.localPos); + Direction initialOrientation = cce.getInitialOrientation() + .getCounterClockWise(); + boolean inverted = false; + if (info != null && info.state.hasProperty(ControlsBlock.FACING)) + inverted = !info.state.getValue(ControlsBlock.FACING) + .equals(initialOrientation); + + if (ControlsHandler.entityRef.get() == entity && ControlsHandler.controlsPos != null && ControlsHandler.controlsPos.equals(context.localPos)) { Collection pressed = ControlsHandler.currentlyPressed; - equipAnimation.chase(1, .2f, Chaser.EXP); - steering.chase((pressed.contains(3) ? 1 : 0) + (pressed.contains(2) ? -1 : 0), 0.2f, Chaser.EXP); - speed.chase(0, 0.2f, Chaser.EXP); // TODO - } else - equipAnimation.chase(0, .2f, Chaser.EXP); + angles.equipAnimation.chase(1, .2f, Chaser.EXP); + angles.steering.chase((pressed.contains(3) ? 1 : 0) + (pressed.contains(2) ? -1 : 0), 0.2f, Chaser.EXP); + float f = cce.movingBackwards ^ inverted ? -1 : 1; + angles.speed.chase(Math.min(context.motion.length(), 0.5f) * f, 0.2f, Chaser.EXP); + + } else { + angles.equipAnimation.chase(0, .2f, Chaser.EXP); + angles.steering.chase(0, 0, Chaser.EXP); + angles.speed.chase(0, 0, Chaser.EXP); + } + float pt = AnimationTickHolder.getPartialTicks(context.world); - ControlsRenderer.render(context, renderWorld, matrices, buffer, equipAnimation.getValue(pt), speed.getValue(pt), - steering.getValue(pt)); + ControlsRenderer.render(context, renderWorld, matrices, buffer, angles.equipAnimation.getValue(pt), + angles.speed.getValue(pt), angles.steering.getValue(pt)); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsServerHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsServerHandler.java new file mode 100644 index 000000000..7f06b7cd1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsServerHandler.java @@ -0,0 +1,110 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; + +import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.foundation.utility.IntAttached; +import com.simibubi.create.foundation.utility.WorldAttached; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelAccessor; + +public class ControlsServerHandler { + + public static WorldAttached> receivedInputs = new WorldAttached<>($ -> new HashMap<>()); + static final int TIMEOUT = 30; + + public static void tick(LevelAccessor world) { + Map map = receivedInputs.get(world); + for (Iterator> iterator = map.entrySet() + .iterator(); iterator.hasNext();) { + + Entry entry = iterator.next(); + ControlsContext ctx = entry.getValue(); + Collection list = ctx.keys; + + for (Iterator entryIterator = list.iterator(); entryIterator.hasNext();) { + ManuallyPressedKey pressedKey = entryIterator.next(); + pressedKey.decrement(); + if (!pressedKey.isAlive()) + entryIterator.remove(); // key released + } + + if (!ctx.entity.control(ctx.controlsLocalPos, list.stream() + .map(ManuallyPressedKey::getSecond) + .toList(), world.getPlayerByUUID(entry.getKey()))) { + ctx.entity.stopControlling(ctx.controlsLocalPos); + } + + if (list.isEmpty()) + iterator.remove(); + } + } + + public static void receivePressed(LevelAccessor world, AbstractContraptionEntity entity, BlockPos controlsPos, + UUID uniqueID, Collection collect, boolean pressed) { + Map map = receivedInputs.get(world); + + if (map.containsKey(uniqueID) && map.get(uniqueID).entity != entity) + map.remove(uniqueID); + + ControlsContext ctx = map.computeIfAbsent(uniqueID, $ -> new ControlsContext(entity, controlsPos)); + Collection list = ctx.keys; + + WithNext: for (Integer activated : collect) { + for (Iterator iterator = list.iterator(); iterator.hasNext();) { + ManuallyPressedKey entry = iterator.next(); + Integer inputType = entry.getSecond(); + if (inputType.equals(activated)) { + if (!pressed) + entry.setFirst(0); + else + entry.keepAlive(); + continue WithNext; + } + } + + if (!pressed) + continue; + + list.add(new ManuallyPressedKey(activated)); // key newly pressed + } + } + + static class ControlsContext { + + Collection keys; + AbstractContraptionEntity entity; + BlockPos controlsLocalPos; + + public ControlsContext(AbstractContraptionEntity entity, BlockPos controlsPos) { + this.entity = entity; + controlsLocalPos = controlsPos; + keys = new ArrayList<>(); + } + + } + + static class ManuallyPressedKey extends IntAttached { + + public ManuallyPressedKey(Integer second) { + super(TIMEOUT, second); + } + + public void keepAlive() { + setFirst(TIMEOUT); + } + + public boolean isAlive() { + return getFirst() > 0; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsStopControllingPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsStopControllingPacket.java new file mode 100644 index 000000000..088f8bb50 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsStopControllingPacket.java @@ -0,0 +1,27 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; + +import java.util.function.Supplier; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ControlsStopControllingPacket extends SimplePacketBase { + + public ControlsStopControllingPacket() {} + + public ControlsStopControllingPacket(FriendlyByteBuf buffer) {} + + @Override + public void write(FriendlyByteBuf buffer) {} + + @Override + public void handle(Supplier context) { + context.get() + .enqueueWork(ControlsHandler::stopControlling); + context.get() + .setPacketHandled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/DoubleFaceAttachedBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/DoubleFaceAttachedBlock.java index 31f3d7e64..0d7625ff7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/DoubleFaceAttachedBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/DoubleFaceAttachedBlock.java @@ -57,7 +57,7 @@ public class DoubleFaceAttachedBlock extends HorizontalDirectionalBlock { face = DoubleAttachFace.WALL_REVERSED; } blockstate = this.defaultBlockState() - .setValue(FACE, face) // TODO wall reversed + .setValue(FACE, face) .setValue(FACING, direction.getOpposite()); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java b/src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java index adca87cd8..66facb602 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java @@ -157,12 +157,12 @@ public class GlobalRailwayManager { for (Train train : trains.values()) train.tick(level); - if (AllKeys.isKeyDown(GLFW.GLFW_KEY_H) && AllKeys.altDown()) - trackNetworks.values() - .forEach(TrackGraph::debugViewSignalData); - if (AllKeys.isKeyDown(GLFW.GLFW_KEY_J) && AllKeys.altDown()) - trackNetworks.values() - .forEach(TrackGraph::debugViewNodes); +// if (AllKeys.isKeyDown(GLFW.GLFW_KEY_H) && AllKeys.altDown()) +// trackNetworks.values() +// .forEach(TrackGraph::debugViewSignalData); +// if (AllKeys.isKeyDown(GLFW.GLFW_KEY_J) && AllKeys.altDown()) +// trackNetworks.values() +// .forEach(TrackGraph::debugViewNodes); } public void clientTick() { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java index 41af8af86..384c2c15b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java @@ -451,7 +451,7 @@ public class TrackGraph { EdgeData signalData = edge.getEdgeData(); UUID singleGroup = signalData.singleSignalGroup; SignalEdgeGroup signalEdgeGroup = - singleGroup == null ? null : Create.RAILWAYS.signalEdgeGroups.get(singleGroup); + singleGroup == null ? null : Create.RAILWAYS.sided(null).signalEdgeGroups.get(singleGroup); if (!edge.isTurn()) { Vec3 p1 = edge.getPosition(node, other, 0); @@ -479,7 +479,7 @@ public class TrackGraph { continue; prevBoundary = boundary; - group = Create.RAILWAYS.signalEdgeGroups.get(boundary.getGroup(node)); + group = Create.RAILWAYS.sided(null).signalEdgeGroups.get(boundary.getGroup(node)); if (group != null) CreateClient.OUTLINER @@ -496,7 +496,7 @@ public class TrackGraph { } if (prevBoundary != null) { - group = Create.RAILWAYS.signalEdgeGroups.get(prevBoundary.getGroup(other)); + group = Create.RAILWAYS.sided(null).signalEdgeGroups.get(prevBoundary.getGroup(other)); if (group != null) CreateClient.OUTLINER .showLine(edge, edge.getPosition(node, other, prev + 1 / 16f / length) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphHelper.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphHelper.java index fde26796b..613dfc7fb 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphHelper.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphHelper.java @@ -30,7 +30,8 @@ public class TrackGraphHelper { TrackNodeLocation location = new TrackNodeLocation(Vec3.atBottomCenterOf(pos) .add(0, track.getElevationAtCenter(level, pos, trackBlockState), 0)); - graph = Create.RAILWAYS.getGraph(level, location); + graph = Create.RAILWAYS.sided(level) + .getGraph(level, location); if (graph != null) { TrackNode node = graph.locateNode(location); if (node != null) { @@ -79,7 +80,8 @@ public class TrackGraphHelper { for (int i = 0; i < 100 && distance < 32; i++) { DiscoveredLocation loc = current; if (graph == null) - graph = Create.RAILWAYS.getGraph(level, loc); + graph = Create.RAILWAYS.sided(level) + .getGraph(level, loc); if (graph == null || graph.locateNode(loc) == null) { Collection list = ITrackBlock.walkConnectedTracks(level, loc, true); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java index 1677e278b..af58017e7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java @@ -1,7 +1,8 @@ package com.simibubi.create.content.logistics.trains.entity; import java.lang.ref.WeakReference; -import java.util.Optional; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -19,7 +20,9 @@ import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Entity.RemovalReason; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; @@ -65,6 +68,21 @@ public class Carriage { CarriageContraptionEntity entity = CarriageContraptionEntity.create(level, contraption); entity.setCarriage(this); contraption.startMoving(level); + contraption.onEntityInitialize(level, entity); + for (CarriageBogey carriageBogey : bogeys) + if (carriageBogey != null) + carriageBogey.updateAnchorPosition(); + alignEntity(entity); + + List players = new ArrayList<>(); + for (Entity passenger : entity.getPassengers()) + if (!(passenger instanceof Player)) + passenger.remove(RemovalReason.UNLOADED_WITH_PLAYER); + else + players.add(passenger); + for (Entity player : players) + player.stopRiding(); + serialisedEntity = entity.serializeNBT(); } @@ -137,16 +155,18 @@ public class Carriage { } public void createEntity(Level level) { - Optional entityFromData = EntityType.create(serialisedEntity, level); - Entity entity = entityFromData.orElse(null); + Entity entity = EntityType.loadEntityRecursive(serialisedEntity, level, e -> { + level.addFreshEntity(e); + return e; + }); if (!(entity instanceof CarriageContraptionEntity cce)) return; + Vec3 pos = leadingBogey().anchorPosition; cce.setPos(pos); cce.setCarriage(this); cce.setGraph(train.graph == null ? null : train.graph.id); cce.syncCarriage(); - level.addFreshEntity(cce); this.entity = new WeakReference<>(cce); } @@ -161,8 +181,12 @@ public class Carriage { createEntity(level); } else { CarriageEntityHandler.validateCarriageEntity(entity); - if (!entity.isAlive()) { + if (!entity.isAlive() || entity.leftTickingChunks) { + for (Entity passenger : entity.getPassengers()) + if (!(passenger instanceof Player)) + passenger.remove(RemovalReason.UNLOADED_WITH_PLAYER); serialisedEntity = entity.serializeNBT(); + entity.discard(); this.entity.clear(); return; } @@ -195,13 +219,6 @@ public class Carriage { entity.pitch = (float) (Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ)) * 180 / Math.PI) * -1; } - public void discardEntity() { - CarriageContraptionEntity entity = this.entity.get(); - if (entity == null) - return; - entity.discard(); - } - public TravellingPoint getLeadingPoint() { return leadingBogey().leading(); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java index c90860683..e151527ed 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java @@ -25,6 +25,7 @@ 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.nbt.ListTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.Tag; import net.minecraft.world.level.Level; @@ -138,7 +139,7 @@ public class CarriageContraption extends Contraption { tag.putBoolean("BackControls", backwardControls); tag.putBoolean("FrontBlazeConductor", blazeBurnerConductors.getFirst()); tag.putBoolean("BackBlazeConductor", blazeBurnerConductors.getSecond()); - NBTHelper.writeCompoundList(conductorSeats.entrySet(), e -> { + ListTag list = NBTHelper.writeCompoundList(conductorSeats.entrySet(), e -> { CompoundTag compoundTag = new CompoundTag(); compoundTag.put("Pos", NbtUtils.writeBlockPos(e.getKey())); compoundTag.putBoolean("Forward", e.getValue() @@ -147,6 +148,7 @@ public class CarriageContraption extends Contraption { .getSecond()); return compoundTag; }); + tag.put("ConductorSeats", list); return tag; } @@ -160,7 +162,7 @@ public class CarriageContraption extends Contraption { conductorSeats.clear(); NBTHelper.iterateCompoundList(nbt.getList("ConductorSeats", Tag.TAG_COMPOUND), c -> conductorSeats.put(NbtUtils.readBlockPos(c.getCompound("Pos")), - Couple.create(nbt.getBoolean("Forward"), nbt.getBoolean("Backward")))); + Couple.create(c.getBoolean("Forward"), c.getBoolean("Backward")))); super.readNBT(world, nbt, spawnData); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java index d84f6ab22..c94b2a8d7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java @@ -27,13 +27,13 @@ import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.KeybindComponent; import net.minecraft.network.chat.TextComponent; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; @@ -45,9 +45,6 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.DistExecutor; public class CarriageContraptionEntity extends OrientedContraptionEntity { @@ -61,6 +58,9 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { private Carriage carriage; public boolean validForRender; + public boolean movingBackwards; + + public boolean leftTickingChunks; public CarriageContraptionEntity(EntityType type, Level world) { super(type, world); @@ -95,10 +95,10 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { if (!level.isClientSide) return; - if (key == TRACK_GRAPH) + if (TRACK_GRAPH.equals(key)) updateTrackGraph(); - if (key == CARRIAGE_DATA) { + if (CARRIAGE_DATA.equals(key)) { CarriageSyncData carriageData = getCarriageData(); if (carriageData == null) return; @@ -177,8 +177,10 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { Vec3 diff = position().subtract(xo, yo, zo); Vec3 relativeDiff = VecHelper.rotate(diff, yaw, Axis.Y); - double distanceTo = diff.length() * Math.signum(-relativeDiff.x); + double signum = Math.signum(-relativeDiff.x); + double distanceTo = diff.length() * signum; + movingBackwards = signum < 0; carriage.bogeys.getFirst() .updateAngles(distanceTo); if (carriage.isOnTwoBogeys()) @@ -272,6 +274,14 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { return false; if (carriage.train.derailed) return false; + if (level.isClientSide) + return true; + if (player.isSpectator()) + return false; + if (!toGlobalVector(VecHelper.getCenterOf(controlsLocalPos), 1).closerThan(player.position(), 10)) + return false; + if (heldControls.contains(5)) + return false; StructureBlockInfo info = contraption.getBlocks() .get(controlsLocalPos); @@ -326,8 +336,8 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { new TextComponent(Strings.repeat("|", progress) + (arrived ? " ->" : " <-")); TextComponent greenComponent = new TextComponent((arrived ? "<- " : "-> ") + Strings.repeat("|", 30 - progress)); - int mixedColor = Color.mixColors(0xff_91EA44, 0xff_FFC244, progress / 30f); - int targetColor = arrived ? 0xff_91EA44 : 0xff_ffffff; + int mixedColor = Color.mixColors(0x00_91EA44, 0x00_FFC244, progress / 30f); + int targetColor = arrived ? 0x00_91EA44 : 0x00_ffffff; player.displayClientMessage(greenComponent.withStyle(st -> st.withColor(mixedColor)) .append(whiteComponent.withStyle(st -> st.withColor(targetColor))), true); return true; @@ -344,12 +354,9 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { navDistanceTotal = nav.distanceToDestination; return true; } - if (level.isClientSide) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> displayApproachStationMessage(lookAhead)); - } else { - if (level.isClientSide) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::cleanUpApproachStationMessage); - } + displayApproachStationMessage(player, lookAhead); + } else + cleanUpApproachStationMessage(player); } carriage.train.manualSteer = @@ -366,20 +373,17 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { boolean stationMessage = false; - @OnlyIn(Dist.CLIENT) - private void displayApproachStationMessage(GlobalStation station) { - Minecraft instance = Minecraft.getInstance(); - instance.player.displayClientMessage(Lang.translate("contraption.controls.approach_station", - instance.options.keyJump.getTranslatedKeyMessage(), station.name), true); + private void displayApproachStationMessage(Player player, GlobalStation station) { + player.displayClientMessage( + Lang.translate("contraption.controls.approach_station", new KeybindComponent("key.jump"), station.name), + true); stationMessage = true; } - @OnlyIn(Dist.CLIENT) - private void cleanUpApproachStationMessage() { + private void cleanUpApproachStationMessage(Player player) { if (!stationMessage) return; - Minecraft instance = Minecraft.getInstance(); - instance.player.displayClientMessage(new TextComponent(""), true); + player.displayClientMessage(new TextComponent(""), true); stationMessage = false; } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageEntityHandler.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageEntityHandler.java index be4eb4ff9..e288e4f86 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageEntityHandler.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageEntityHandler.java @@ -16,14 +16,14 @@ public class CarriageEntityHandler { if (!event.didChunkChange()) return; Entity entity = event.getEntity(); - if (!(entity instanceof CarriageContraptionEntity)) + if (!(entity instanceof CarriageContraptionEntity cce)) return; SectionPos newPos = event.getNewPos(); Level level = entity.getLevel(); if (level.isClientSide) return; if (!isActiveChunk(level, newPos.chunk())) - entity.discard(); + cce.leftTickingChunks = true; } public static void validateCarriageEntity(CarriageContraptionEntity entity) { @@ -33,7 +33,7 @@ public class CarriageEntityHandler { if (level.isClientSide) return; if (!isActiveChunk(level, entity.chunkPosition())) - entity.discard(); + entity.leftTickingChunks = true; } public static boolean isActiveChunk(Level level, ChunkPos chunk) { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationTileEntity.java index 062933e6d..ffaef3754 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationTileEntity.java @@ -155,12 +155,14 @@ public class StationTileEntity extends SmartTileEntity { Train imminentTrain = station.getImminentTrain(); boolean trainPresent = imminentTrain != null && imminentTrain.getCurrentStation() == station; + boolean canDisassemble = trainPresent && imminentTrain.canDisassemble(); UUID imminentID = imminentTrain != null ? imminentTrain.id : null; - if (this.trainPresent != trainPresent || !Objects.equals(imminentID, this.imminentTrain)) { + if (this.trainPresent != trainPresent || this.trainCanDisassemble != canDisassemble + || !Objects.equals(imminentID, this.imminentTrain)) { this.imminentTrain = imminentID; this.trainPresent = trainPresent; - this.trainCanDisassemble = trainPresent && imminentTrain.canDisassemble(); + this.trainCanDisassemble = canDisassemble; this.trainBackwards = imminentTrain != null && imminentTrain.currentlyBackwards; sendData(); } diff --git a/src/main/java/com/simibubi/create/events/CommonEvents.java b/src/main/java/com/simibubi/create/events/CommonEvents.java index 0463dc044..9d84d6518 100644 --- a/src/main/java/com/simibubi/create/events/CommonEvents.java +++ b/src/main/java/com/simibubi/create/events/CommonEvents.java @@ -3,6 +3,7 @@ package com.simibubi.create.events; import com.simibubi.create.AllFluids; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler; +import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsServerHandler; import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingPhysics; import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; import com.simibubi.create.content.contraptions.fluids.recipe.FluidTransferRecipes; @@ -114,6 +115,7 @@ public class CommonEvents { CapabilityMinecartController.tick(world); CouplingPhysics.tick(world); LinkedControllerServerHandler.tick(world); + ControlsServerHandler.tick(world); Create.RAILWAYS.tick(world); } diff --git a/src/main/java/com/simibubi/create/foundation/command/DumpRailwaysCommand.java b/src/main/java/com/simibubi/create/foundation/command/DumpRailwaysCommand.java index 34937f424..c6c4c7832 100644 --- a/src/main/java/com/simibubi/create/foundation/command/DumpRailwaysCommand.java +++ b/src/main/java/com/simibubi/create/foundation/command/DumpRailwaysCommand.java @@ -6,7 +6,7 @@ import java.util.UUID; import java.util.function.BiConsumer; import com.mojang.brigadier.builder.ArgumentBuilder; -import com.simibubi.create.CreateClient; +import com.simibubi.create.Create; import com.simibubi.create.content.logistics.trains.GlobalRailwayManager; import com.simibubi.create.content.logistics.trains.TrackGraph; import com.simibubi.create.content.logistics.trains.entity.Train; @@ -40,7 +40,7 @@ public class DumpRailwaysCommand { } static void fillReport(ServerLevel level, BiConsumer chat) { - GlobalRailwayManager railways = CreateClient.RAILWAYS; + GlobalRailwayManager railways = Create.RAILWAYS; int white = ChatFormatting.WHITE.getColor(); int blue = 0xD3DEDC; int darkBlue = 0x92A9BD; diff --git a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java index be53b64bb..03e767e96 100644 --- a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java +++ b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java @@ -12,6 +12,8 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket; import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryContraptionUpdatePacket; import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueEffectPacket; +import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsInputPacket; +import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsStopControllingPacket; import com.simibubi.create.content.contraptions.components.structureMovement.sync.ClientMotionPacket; import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionFluidPacket; import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionInteractionPacket; @@ -115,6 +117,7 @@ public enum AllPackets { CONFIGURE_STATION(StationEditPacket.class, StationEditPacket::new, PLAY_TO_SERVER), C_CONFIGURE_TRAIN(TrainEditPacket.class, TrainEditPacket::new, PLAY_TO_SERVER), RELOCATE_TRAIN(TrainRelocationPacket.class, TrainRelocationPacket::new, PLAY_TO_SERVER), + CONTROLS_INPUT(ControlsInputPacket.class, ControlsInputPacket::new, PLAY_TO_SERVER), // Server to Client SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT), @@ -142,6 +145,7 @@ public enum AllPackets { SYNC_TRAIN(TrainPacket.class, TrainPacket::new, PLAY_TO_CLIENT), REMOVE_TE(RemoveTileEntityPacket.class, RemoveTileEntityPacket::new, PLAY_TO_CLIENT), S_CONFIGURE_TRAIN(TrainEditReturnPacket.class, TrainEditReturnPacket::new, PLAY_TO_CLIENT), + CONTROLS_ABORT(ControlsStopControllingPacket.class, ControlsStopControllingPacket::new, PLAY_TO_CLIENT), ;