diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/entity/MixinEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/entity/MixinEntity.java index 94b1c5eb3..c23ef380c 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/entity/MixinEntity.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/entity/MixinEntity.java @@ -6,6 +6,7 @@ import net.minecraft.CrashReportCategory; import net.minecraft.ReportedException; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; @@ -154,6 +155,16 @@ private void preCalculateViewVector(final float xRot, final float yRot, final Ca cir.setReturnValue(newViewVector); } + @Inject(method = "touchingUnloadedChunk", at = @At("HEAD"), cancellable = true, remap = false) + private void isTouchingUnloadedChunkOrShip(CallbackInfoReturnable cir) { + if (!level.isClientSide) { + ServerLevel slevel = (ServerLevel) level; + if (VSGameUtilsKt.getShipsIntersecting(slevel, getBoundingBox()).iterator().hasNext()) { + cir.setReturnValue(true); + } + } + } + // region shadow functions and fields @Shadow public Level level; @@ -184,6 +195,9 @@ private void preCalculateViewVector(final float xRot, final float yRot, final Ca @Shadow public abstract EntityType getType(); + @Shadow + public abstract Vec3 getPosition(float f); + @Override @NotNull public EntityDraggingInformation getDraggingInformation() { diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/unloaded_chunk_flight/MixinPersistentEntitySectionManagerCallback.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/unloaded_chunk_flight/MixinPersistentEntitySectionManagerCallback.java new file mode 100644 index 000000000..7b4ab9453 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/unloaded_chunk_flight/MixinPersistentEntitySectionManagerCallback.java @@ -0,0 +1,85 @@ +package org.valkyrienskies.mod.mixin.feature.unloaded_chunk_flight; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.entity.EntityAccess; +import net.minecraft.world.level.entity.EntitySection; +import net.minecraft.world.level.entity.PersistentEntitySectionManager; +import net.minecraft.world.level.entity.PersistentEntitySectionManager.Callback; +import net.minecraft.world.level.entity.Visibility; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.core.api.ships.LoadedServerShip; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.EntityDraggingInformation; +import org.valkyrienskies.mod.common.util.IEntityDraggingInformationProvider; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(Callback.class) +public class MixinPersistentEntitySectionManagerCallback { + + @Shadow + @Final + private EntityAccess entity; + + @Shadow + private long currentSectionKey; + + @Shadow + private EntitySection currentSection; + + @Shadow + @Final + PersistentEntitySectionManager field_27271; + + @Shadow + private void updateStatus(Visibility visibility, Visibility visibility2) { + throw new IllegalStateException("Mixin failed to apply"); + } + + @Inject(method = "onMove", at = @At("HEAD"), cancellable = true, remap = false) + private void onMoveInclShips(CallbackInfo ci) { + // Do nothing + Entity realEntity = (Entity) this.entity; + BlockPos blockPos = this.entity.blockPosition(); + if (realEntity.level != null && !realEntity.level.isClientSide) { + ServerLevel slevel = (ServerLevel) realEntity.level; + + EntityDraggingInformation draggingInformation = ((IEntityDraggingInformationProvider) realEntity).getDraggingInformation(); + + LoadedServerShip loadedShip = null; + + if (draggingInformation.isEntityBeingDraggedByAShip() && draggingInformation.getLastShipStoodOn() != null) { + loadedShip = VSGameUtilsKt.getShipObjectWorld(slevel).getLoadedShips().getById(draggingInformation.getLastShipStoodOn()); + } else if (VSGameUtilsKt.getShipMountedTo(realEntity) != null) { + loadedShip = VSGameUtilsKt.getShipObjectWorld(slevel).getLoadedShips().getById(VSGameUtilsKt.getShipMountedTo(realEntity).getId()); + } else if (VSGameUtilsKt.getShipsIntersecting(slevel, realEntity.getBoundingBox()).iterator().hasNext()) { + loadedShip = VSGameUtilsKt.getShipObjectWorld(slevel).getLoadedShips().getById(VSGameUtilsKt.getShipsIntersecting(slevel, realEntity.getBoundingBox()).iterator().next().getId()); + } + + if (loadedShip != null) { + long l = SectionPos.asLong(new BlockPos(VectorConversionsMCKt.toMinecraft(loadedShip.getTransform().getWorldToShip().transformPosition(VectorConversionsMCKt.toJOMLD(blockPos))))); + if (l != this.currentSectionKey) { + Visibility visibility = this.currentSection.getStatus(); + if (!this.currentSection.remove(realEntity)) { + //LOGGER.warn("Entity {} wasn't found in section {} (moving to {})", this.entity, SectionPos.of(this.currentSectionKey), l); + } + ((PersistentEntitySectionManagerAccessor) this.field_27271).invokeRemoveSectionIfEmpty(this.currentSectionKey, this.currentSection); + EntitySection entitySection = ((PersistentEntitySectionManagerAccessor) this.field_27271).getSectionStorage().getOrCreateSection(l); + entitySection.add(realEntity); + this.currentSection = entitySection; + this.currentSectionKey = l; + this.updateStatus(visibility, entitySection.getStatus()); + } + ci.cancel(); + return; + } + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/unloaded_chunk_flight/PersistentEntitySectionManagerAccessor.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/unloaded_chunk_flight/PersistentEntitySectionManagerAccessor.java new file mode 100644 index 000000000..67cdc8396 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/unloaded_chunk_flight/PersistentEntitySectionManagerAccessor.java @@ -0,0 +1,19 @@ +package org.valkyrienskies.mod.mixin.feature.unloaded_chunk_flight; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.entity.EntitySection; +import net.minecraft.world.level.entity.EntitySectionStorage; +import net.minecraft.world.level.entity.PersistentEntitySectionManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(PersistentEntitySectionManager.class) +public interface PersistentEntitySectionManagerAccessor { + + @Accessor + EntitySectionStorage getSectionStorage(); + + @Invoker + void invokeRemoveSectionIfEmpty(long l, EntitySection entitySection); +} diff --git a/common/src/main/resources/valkyrienskies-common.mixins.json b/common/src/main/resources/valkyrienskies-common.mixins.json index 569f9e31a..ecd1f63be 100644 --- a/common/src/main/resources/valkyrienskies-common.mixins.json +++ b/common/src/main/resources/valkyrienskies-common.mixins.json @@ -49,6 +49,8 @@ "feature.shipyard_entities.MixinTransientEntitySectionManager", "feature.spawn_player_on_ship.MixinServerGamePacketListenerImpl", "feature.tick_ship_chunks.MixinChunkMap", + "feature.unloaded_chunk_flight.MixinPersistentEntitySectionManagerCallback", + "feature.unloaded_chunk_flight.PersistentEntitySectionManagerAccessor", "feature.water_in_ships_entity.MixinEntity", "feature.world_border.MixinLevel", "feature.world_border.MixinWorldBorder", @@ -168,9 +170,9 @@ "mod_compat.create.client.MixinSoundScapes", "mod_compat.create.client.MixinTileEntityRenderHelper", "mod_compat.create.client.MixinTrainRelocator", + "mod_compat.create.client.MixinValueBox", "mod_compat.create.client.trackOutlines.MixinBigOutlines", "mod_compat.create.client.trackOutlines.MixinTrackBlockOutline", - "mod_compat.create.client.MixinValueBox", "mod_compat.flywheel.InstancingEngineAccessor", "mod_compat.flywheel.MixinBlockEntityInstanceManager", "mod_compat.flywheel.MixinInstanceManager",