diff --git a/common/src/main/java/dev/ryanhcode/sable/mixin/entity/entities_stick_sublevels/ClientPacketListenerMixin.java b/common/src/main/java/dev/ryanhcode/sable/mixin/entity/entities_stick_sublevels/ClientPacketListenerMixin.java index b8bc2e5e..6a34aac0 100644 --- a/common/src/main/java/dev/ryanhcode/sable/mixin/entity/entities_stick_sublevels/ClientPacketListenerMixin.java +++ b/common/src/main/java/dev/ryanhcode/sable/mixin/entity/entities_stick_sublevels/ClientPacketListenerMixin.java @@ -103,13 +103,15 @@ public abstract class ClientPacketListenerMixin { final SubLevel existingSubLevel = Sable.HELPER.getContaining(this.level, entity.position()); if (subLevel != null && actuallyInSubLevel && existingSubLevel != subLevel) { - entity.setPos(subLevel.logicalPose().transformPositionInverse(entity.position())); + final Vec3 newPos = subLevel.logicalPose().transformPositionInverse(entity.position()); + entity.moveTo(newPos.x, newPos.y, newPos.z); } else if (existingSubLevel != null && subLevel == null) { - entity.setPos(existingSubLevel.logicalPose().transformPosition(entity.position())); + final Vec3 newPos = existingSubLevel.logicalPose().transformPosition(entity.position()); + entity.moveTo(newPos.x, newPos.y, newPos.z); } entity.lerpTo(pX, pY, pZ, pYRot, pXRot, pLerpSteps); extension.sable$setPlotPosition(null); } } -} \ No newline at end of file +} diff --git a/common/src/main/java/dev/ryanhcode/sable/mixin/entity/entity_rendering/LevelRendererMixin.java b/common/src/main/java/dev/ryanhcode/sable/mixin/entity/entity_rendering/LevelRendererMixin.java index b5450c09..59e7ae5e 100644 --- a/common/src/main/java/dev/ryanhcode/sable/mixin/entity/entity_rendering/LevelRendererMixin.java +++ b/common/src/main/java/dev/ryanhcode/sable/mixin/entity/entity_rendering/LevelRendererMixin.java @@ -44,7 +44,7 @@ private void renderEntityOnSubLevel(final Entity entity, @Local(ordinal = 5) final LocalDoubleRef entityZ, @Share("renderPose") final LocalRef renderPoseShare) { // Render the entity on the data - final ClientSubLevel subLevel = (ClientSubLevel) Sable.HELPER.getContaining(entity); + final ClientSubLevel subLevel = Sable.HELPER.getContainingClient(entity.getX(), entity.getZ()); if (subLevel == null) { // Tracking sub-levels diff --git a/common/src/main/java/dev/ryanhcode/sable/mixin/entity/entity_sublevel_collision/ArmorStandMixin.java b/common/src/main/java/dev/ryanhcode/sable/mixin/entity/entity_sublevel_collision/ArmorStandMixin.java new file mode 100644 index 00000000..530836e8 --- /dev/null +++ b/common/src/main/java/dev/ryanhcode/sable/mixin/entity/entity_sublevel_collision/ArmorStandMixin.java @@ -0,0 +1,56 @@ +package dev.ryanhcode.sable.mixin.entity.entity_sublevel_collision; + +import dev.ryanhcode.sable.Sable; +import dev.ryanhcode.sable.api.entity.EntitySubLevelUtil; +import dev.ryanhcode.sable.sublevel.SubLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ArmorStand.class) +public abstract class ArmorStandMixin extends Entity { + + public ArmorStandMixin(final EntityType entityType, final Level level) { + super(entityType, level); + } + + @Unique + private int sable$lastAttachedTick; + + @Inject(method = "tick", at = @At("TAIL")) + private void sable$postTick(final CallbackInfo ci) { + if (this.level().isClientSide) return; + + final SubLevel containingSubLevel = Sable.HELPER.getContaining(this); + + if (containingSubLevel != null) { + if (this.tickCount - this.sable$lastAttachedTick > 1 && !this.onGround()) { + EntitySubLevelUtil.kickEntity(containingSubLevel, this); + } + } else if (this.onGround()) { + final SubLevel landed = Sable.HELPER.getTrackingSubLevel(this); + if (landed != null) { + final Vec3 shipyardPos = landed.logicalPose().transformPositionInverse(this.position()); + final BlockPos belowPos = BlockPos.containing(shipyardPos.x, shipyardPos.y - 0.5, shipyardPos.z); + final BlockState belowState = this.level().getBlockState(belowPos); + if (belowState.isFaceSturdy(this.level(), belowPos, Direction.UP) + && Math.abs(shipyardPos.y - (belowPos.getY() + 1)) < 0.1) { + final Vec3 shipyardVel = landed.logicalPose().transformNormalInverse(this.getDeltaMovement()); + this.moveTo(shipyardPos.x, shipyardPos.y, shipyardPos.z); + this.setDeltaMovement(shipyardVel); + this.sable$lastAttachedTick = this.tickCount; + } + } + } + } +} diff --git a/common/src/main/java/dev/ryanhcode/sable/mixin/entity/no_culling/EntityMixin.java b/common/src/main/java/dev/ryanhcode/sable/mixin/entity/no_culling/EntityMixin.java new file mode 100644 index 00000000..a8bba03b --- /dev/null +++ b/common/src/main/java/dev/ryanhcode/sable/mixin/entity/no_culling/EntityMixin.java @@ -0,0 +1,22 @@ +package dev.ryanhcode.sable.mixin.entity.no_culling; + +import dev.ryanhcode.sable.api.entity.EntitySubLevelUtil; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.Level; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Entity.class) +public abstract class EntityMixin { + + @Inject(method = "", at = @At("TAIL")) + private void sable$disableCullingForRetained(final EntityType type, final Level level, final CallbackInfo ci) { + final Entity self = (Entity) (Object) this; + if (!EntitySubLevelUtil.shouldKick(self)) { + self.noCulling = true; + } + } +} \ No newline at end of file diff --git a/common/src/main/resources/data/sable/tags/entity_type/destroy_when_leaving_plot.json b/common/src/main/resources/data/sable/tags/entity_type/destroy_when_leaving_plot.json index 131ae636..cefca84d 100644 --- a/common/src/main/resources/data/sable/tags/entity_type/destroy_when_leaving_plot.json +++ b/common/src/main/resources/data/sable/tags/entity_type/destroy_when_leaving_plot.json @@ -2,11 +2,10 @@ "replace": false, "values": [ { "id": "exposure:camera_stand", "required": false }, - "minecraft:armor_stand", "minecraft:minecart", "minecraft:hopper_minecart", "minecraft:chest_minecart", "minecraft:furnace_minecart", "minecraft:tnt_minecart" ] -} \ No newline at end of file +} diff --git a/common/src/main/resources/sable.mixins.json b/common/src/main/resources/sable.mixins.json index faf5ee1b..b3900eeb 100644 --- a/common/src/main/resources/sable.mixins.json +++ b/common/src/main/resources/sable.mixins.json @@ -41,6 +41,7 @@ "entity.entity_sublevel_collision.CameraMixin", "entity.entity_swimming.CameraMixin", "entity.parrot.ParrotMixin", + "entity.no_culling.EntityMixin", "loaded_chunk_debug.BlockUpdatePacketMixin", "loaded_chunk_debug.ChunkBorderRendererMixin", "loaded_chunk_debug.ClientChunkCacheStorageAccessor", @@ -149,6 +150,7 @@ "entity.entity_rotations_and_riding.ServerEntityMixin", "entity.entity_rotations_and_riding.ServerPlayerMixin", "entity.entity_sublevel_collision.AbstractMinecartMixin", + "entity.entity_sublevel_collision.ArmorStandMixin", "entity.entity_sublevel_collision.EntityMixin", "entity.entity_sublevel_collision.ItemEntityMixin", "entity.entity_sublevel_collision.LevelMixin",