Super cool entities and fun
- Conductor entities now rotate to face their carts' motion - Fixed Contraption passengers not visible to clients whenever the seat position offsets them out of ticking chunks just after loading in
This commit is contained in:
parent
273a276fda
commit
9d8803d280
5 changed files with 82 additions and 12 deletions
|
@ -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.mounted.MountedContraption;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionSeatMappingPacket;
|
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionSeatMappingPacket;
|
||||||
import com.simibubi.create.foundation.collision.Matrix3d;
|
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.networking.AllPackets;
|
||||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
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.EntityDataSerializers;
|
||||||
import net.minecraft.network.syncher.SynchedEntityData;
|
import net.minecraft.network.syncher.SynchedEntityData;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.damagesource.DamageSource;
|
import net.minecraft.world.damagesource.DamageSource;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.EntityType;
|
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.decoration.HangingEntity;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.entity.projectile.Projectile;
|
import net.minecraft.world.entity.projectile.Projectile;
|
||||||
|
@ -267,7 +271,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void tick() {
|
public void tick() {
|
||||||
if (contraption == null) {
|
if (contraption == null) {
|
||||||
discard();
|
discard();
|
||||||
return;
|
return;
|
||||||
|
@ -287,6 +291,40 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
||||||
contraption.onEntityTick(level);
|
contraption.onEntityTick(level);
|
||||||
tickContraption();
|
tickContraption();
|
||||||
super.tick();
|
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();
|
protected abstract void tickContraption();
|
||||||
|
@ -496,7 +534,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
||||||
return;
|
return;
|
||||||
|
|
||||||
StructureTransform transform = makeStructureTransform();
|
StructureTransform transform = makeStructureTransform();
|
||||||
|
|
||||||
contraption.stop(level);
|
contraption.stop(level);
|
||||||
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
||||||
new ContraptionDisassemblyPacket(this.getId(), transform));
|
new ContraptionDisassemblyPacket(this.getId(), transform));
|
||||||
|
@ -561,9 +599,6 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
||||||
@Override
|
@Override
|
||||||
public void onRemovedFromWorld() {
|
public void onRemovedFromWorld() {
|
||||||
super.onRemovedFromWorld();
|
super.onRemovedFromWorld();
|
||||||
if (level != null && level.isClientSide)
|
|
||||||
return;
|
|
||||||
getPassengers().forEach(Entity::discard);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,6 +20,7 @@ import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.Entity.RemovalReason;
|
import net.minecraft.world.entity.Entity.RemovalReason;
|
||||||
|
@ -160,18 +161,21 @@ public class Carriage {
|
||||||
|
|
||||||
public void createEntity(Level level) {
|
public void createEntity(Level level) {
|
||||||
Entity entity = EntityType.loadEntityRecursive(serialisedEntity, level, e -> {
|
Entity entity = EntityType.loadEntityRecursive(serialisedEntity, level, e -> {
|
||||||
level.addFreshEntity(e);
|
e.moveTo(positionAnchor);
|
||||||
return e;
|
return e;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!(entity instanceof CarriageContraptionEntity cce))
|
if (!(entity instanceof CarriageContraptionEntity cce))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Vec3 pos = positionAnchor;
|
|
||||||
cce.setPos(pos);
|
|
||||||
cce.setCarriage(this);
|
|
||||||
cce.setGraph(train.graph == null ? null : train.graph.id);
|
cce.setGraph(train.graph == null ? null : train.graph.id);
|
||||||
|
cce.setCarriage(this);
|
||||||
cce.syncCarriage();
|
cce.syncCarriage();
|
||||||
|
|
||||||
this.entity = new WeakReference<>(cce);
|
this.entity = new WeakReference<>(cce);
|
||||||
|
|
||||||
|
if (level instanceof ServerLevel sl)
|
||||||
|
sl.tryAddFreshEntityWithPassengers(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void manageEntity(Level level) {
|
public void manageEntity(Level level) {
|
||||||
|
@ -196,11 +200,13 @@ public class Carriage {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeAndSaveEntity(CarriageContraptionEntity entity) {
|
private void removeAndSaveEntity(CarriageContraptionEntity entity) {
|
||||||
|
serialisedEntity = entity.serializeNBT();
|
||||||
|
|
||||||
for (Entity passenger : entity.getPassengers())
|
for (Entity passenger : entity.getPassengers())
|
||||||
if (!(passenger instanceof Player))
|
if (!(passenger instanceof Player))
|
||||||
passenger.remove(RemovalReason.UNLOADED_WITH_PLAYER);
|
passenger.discard();
|
||||||
serialisedEntity = entity.serializeNBT();
|
|
||||||
entity.discard();
|
entity.discard();
|
||||||
|
|
||||||
this.entity.clear();
|
this.entity.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,9 +124,24 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
||||||
return entity;
|
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
|
@Override
|
||||||
protected void tickContraption() {
|
protected void tickContraption() {
|
||||||
if (!(contraption instanceof CarriageContraption))
|
if (!(contraption instanceof CarriageContraption cc))
|
||||||
return;
|
return;
|
||||||
if (carriage == null) {
|
if (carriage == null) {
|
||||||
if (level.isClientSide) {
|
if (level.isClientSide) {
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -9,6 +9,7 @@
|
||||||
"accessor.AbstractProjectileDispenseBehaviorAccessor",
|
"accessor.AbstractProjectileDispenseBehaviorAccessor",
|
||||||
"accessor.DispenserBlockAccessor",
|
"accessor.DispenserBlockAccessor",
|
||||||
"accessor.FallingBlockEntityAccessor",
|
"accessor.FallingBlockEntityAccessor",
|
||||||
|
"accessor.ServerLevelAccessor",
|
||||||
"accessor.LivingEntityAccessor"
|
"accessor.LivingEntityAccessor"
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
|
|
Loading…
Reference in a new issue