mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-14 19:43:41 +01:00
TCP Handbrake
- Manual Train Controls now use network packets - Carriages now properly re-introduce their passengers when entering ticking chunks - Fixed approach station prompt no longer appearing - Fixed players shunted to 0,0 when seated while train assembles - Fixed relocator not using client-side graph when testing validity - Fixed entity data not synched properly from dedicated servers - Fixed controls storing state in behaviour class - Fixed carriages not serialising conductor seat data correctly
This commit is contained in:
parent
fa47939428
commit
ed6712fd0b
20 changed files with 417 additions and 139 deletions
|
@ -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<Boolean> STALLED =
|
||||
SynchedEntityData.defineId(AbstractContraptionEntity.class, EntityDataSerializers.BOOLEAN);
|
||||
private static final EntityDataAccessor<Optional<UUID>> CONTROLLED_BY =
|
||||
SynchedEntityData.defineId(AbstractContraptionEntity.class, EntityDataSerializers.OPTIONAL_UUID);
|
||||
|
||||
public final Map<Entity, MutableInt> collidingEntities;
|
||||
|
||||
|
@ -178,6 +185,14 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
|||
return getName();
|
||||
}
|
||||
|
||||
public Optional<UUID> 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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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<AbstractContraptionEntity> 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<AbstractContraptionEntity>(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<KeyMapping> controls = ControlsUtil.getControls();
|
||||
Collection<Integer> 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;
|
||||
|
|
|
@ -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<Integer> activatedButtons;
|
||||
private boolean press;
|
||||
private int contraptionEntityId;
|
||||
private BlockPos controlsPos;
|
||||
|
||||
public ControlsInputPacket(Collection<Integer> 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) {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Integer> 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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<Map<UUID, ControlsContext>> receivedInputs = new WorldAttached<>($ -> new HashMap<>());
|
||||
static final int TIMEOUT = 30;
|
||||
|
||||
public static void tick(LevelAccessor world) {
|
||||
Map<UUID, ControlsContext> map = receivedInputs.get(world);
|
||||
for (Iterator<Entry<UUID, ControlsContext>> iterator = map.entrySet()
|
||||
.iterator(); iterator.hasNext();) {
|
||||
|
||||
Entry<UUID, ControlsContext> entry = iterator.next();
|
||||
ControlsContext ctx = entry.getValue();
|
||||
Collection<ManuallyPressedKey> list = ctx.keys;
|
||||
|
||||
for (Iterator<ManuallyPressedKey> 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<Integer> collect, boolean pressed) {
|
||||
Map<UUID, ControlsContext> 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<ManuallyPressedKey> list = ctx.keys;
|
||||
|
||||
WithNext: for (Integer activated : collect) {
|
||||
for (Iterator<ManuallyPressedKey> 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<ManuallyPressedKey> keys;
|
||||
AbstractContraptionEntity entity;
|
||||
BlockPos controlsLocalPos;
|
||||
|
||||
public ControlsContext(AbstractContraptionEntity entity, BlockPos controlsPos) {
|
||||
this.entity = entity;
|
||||
controlsLocalPos = controlsPos;
|
||||
keys = new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class ManuallyPressedKey extends IntAttached<Integer> {
|
||||
|
||||
public ManuallyPressedKey(Integer second) {
|
||||
super(TIMEOUT, second);
|
||||
}
|
||||
|
||||
public void keepAlive() {
|
||||
setFirst(TIMEOUT);
|
||||
}
|
||||
|
||||
public boolean isAlive() {
|
||||
return getFirst() > 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {
|
||||
context.get()
|
||||
.enqueueWork(ControlsHandler::stopControlling);
|
||||
context.get()
|
||||
.setPacketHandled(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<DiscoveredLocation> list = ITrackBlock.walkConnectedTracks(level, loc, true);
|
||||
|
|
|
@ -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<Entity> 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<Entity> 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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<String, Integer> chat) {
|
||||
GlobalRailwayManager railways = CreateClient.RAILWAYS;
|
||||
GlobalRailwayManager railways = Create.RAILWAYS;
|
||||
int white = ChatFormatting.WHITE.getColor();
|
||||
int blue = 0xD3DEDC;
|
||||
int darkBlue = 0x92A9BD;
|
||||
|
|
|
@ -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),
|
||||
|
||||
;
|
||||
|
||||
|
|
Loading…
Reference in a new issue