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 42bfa7abb..fe9401d56 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 @@ -28,6 +28,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.int 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; +import com.simibubi.create.foundation.mixin.accessor.ServerLevelAccessor; import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -44,10 +45,13 @@ 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.util.Mth; import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.decoration.HangingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.Projectile; @@ -267,7 +271,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } @Override - public final void tick() { + public void tick() { if (contraption == null) { discard(); return; @@ -287,6 +291,40 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit contraption.onEntityTick(level); tickContraption(); super.tick(); + + if (!(level instanceof ServerLevelAccessor sl)) + return; + + for (Entity entity : getPassengers()) { + if (entity instanceof Player) + continue; + if (entity.isAlwaysTicking()) + continue; + if (sl.create$getEntityTickList() + .contains(entity)) + continue; + positionRider(entity); + } + } + + public void alignPassenger(Entity passenger) { + Vec3 motion = getContactPointMotion(passenger.getEyePosition()); + if (Mth.equal(motion.length(), 0)) + return; + if (passenger instanceof ArmorStand) + return; + if (!(passenger instanceof LivingEntity living)) + return; + float angle = AngleHelper.deg(-Mth.atan2(motion.x, motion.z)); + if (level.isClientSide) { + living.lerpTo(0, 0, 0, 0, 0, 0, false); + living.lerpHeadTo(0, 0); + living.setYRot(angle); + living.setXRot(0); + living.yBodyRot = angle; + living.yHeadRot = angle; + } else + living.setYRot(angle); } protected abstract void tickContraption(); @@ -496,7 +534,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit return; StructureTransform transform = makeStructureTransform(); - + contraption.stop(level); AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), new ContraptionDisassemblyPacket(this.getId(), transform)); @@ -561,9 +599,6 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit @Override public void onRemovedFromWorld() { super.onRemovedFromWorld(); - if (level != null && level.isClientSide) - return; - getPassengers().forEach(Entity::discard); } @Override 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 4f68885fc..7249026b0 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 @@ -20,6 +20,7 @@ import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; +import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity.RemovalReason; @@ -160,18 +161,21 @@ public class Carriage { public void createEntity(Level level) { Entity entity = EntityType.loadEntityRecursive(serialisedEntity, level, e -> { - level.addFreshEntity(e); + e.moveTo(positionAnchor); return e; }); + if (!(entity instanceof CarriageContraptionEntity cce)) return; - Vec3 pos = positionAnchor; - cce.setPos(pos); - cce.setCarriage(this); cce.setGraph(train.graph == null ? null : train.graph.id); + cce.setCarriage(this); cce.syncCarriage(); + this.entity = new WeakReference<>(cce); + + if (level instanceof ServerLevel sl) + sl.tryAddFreshEntityWithPassengers(entity); } public void manageEntity(Level level) { @@ -196,11 +200,13 @@ public class Carriage { } private void removeAndSaveEntity(CarriageContraptionEntity entity) { + serialisedEntity = entity.serializeNBT(); + for (Entity passenger : entity.getPassengers()) if (!(passenger instanceof Player)) - passenger.remove(RemovalReason.UNLOADED_WITH_PLAYER); - serialisedEntity = entity.serializeNBT(); + passenger.discard(); entity.discard(); + this.entity.clear(); } 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 9f205b634..9dbb767a8 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 @@ -124,9 +124,24 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { return entity; } + @Override + public void tick() { + super.tick(); + + if (contraption instanceof CarriageContraption cc) + for (Entity entity : getPassengers()) { + BlockPos seatOf = cc.getSeatOf(entity.getUUID()); + if (seatOf == null) + continue; + if (cc.conductorSeats.get(seatOf) == null) + continue; + alignPassenger(entity); + } + } + @Override protected void tickContraption() { - if (!(contraption instanceof CarriageContraption)) + if (!(contraption instanceof CarriageContraption cc)) return; if (carriage == null) { if (level.isClientSide) { diff --git a/src/main/java/com/simibubi/create/foundation/mixin/accessor/ServerLevelAccessor.java b/src/main/java/com/simibubi/create/foundation/mixin/accessor/ServerLevelAccessor.java new file mode 100644 index 000000000..d3cf967da --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/accessor/ServerLevelAccessor.java @@ -0,0 +1,13 @@ +package com.simibubi.create.foundation.mixin.accessor; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.entity.EntityTickList; + +@Mixin(ServerLevel.class) +public interface ServerLevelAccessor { + @Accessor("entityTickList") + EntityTickList create$getEntityTickList(); +} diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json index 1327b92db..d824aacef 100644 --- a/src/main/resources/create.mixins.json +++ b/src/main/resources/create.mixins.json @@ -9,6 +9,7 @@ "accessor.AbstractProjectileDispenseBehaviorAccessor", "accessor.DispenserBlockAccessor", "accessor.FallingBlockEntityAccessor", + "accessor.ServerLevelAccessor", "accessor.LivingEntityAccessor" ], "client": [