From 2fa41abbba5b671e18ce9e86bdabe20d81c627da Mon Sep 17 00:00:00 2001 From: AbdElAziz333 Date: Thu, 8 Feb 2024 15:41:05 +0200 Subject: [PATCH] Backport 0.3.3 features to 1.18.2 --- .../PersistentEntitySectionManagerMixin.java | 186 ++++++++++++++++++ .../TransientEntitySectionManagerMixin.java | 65 ++++++ 2 files changed, 251 insertions(+) create mode 100644 src/main/java/com/abdelaziz/canary/mixin/ai/replace_streams/storage/PersistentEntitySectionManagerMixin.java create mode 100644 src/main/java/com/abdelaziz/canary/mixin/ai/replace_streams/storage/TransientEntitySectionManagerMixin.java diff --git a/src/main/java/com/abdelaziz/canary/mixin/ai/replace_streams/storage/PersistentEntitySectionManagerMixin.java b/src/main/java/com/abdelaziz/canary/mixin/ai/replace_streams/storage/PersistentEntitySectionManagerMixin.java new file mode 100644 index 0000000..cc87d64 --- /dev/null +++ b/src/main/java/com/abdelaziz/canary/mixin/ai/replace_streams/storage/PersistentEntitySectionManagerMixin.java @@ -0,0 +1,186 @@ +package com.abdelaziz.canary.mixin.ai.replace_streams.storage; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.LongSet; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.entity.*; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.List; +import java.util.Queue; +import java.util.function.Consumer; +import java.util.stream.Stream; + +@Mixin(PersistentEntitySectionManager.class) +public abstract class PersistentEntitySectionManagerMixin { + @Shadow @Final + private Long2ObjectMap chunkVisibility; + + @Shadow @Final + private LongSet chunksToUnload; + + @Shadow @Final + EntitySectionStorage sectionStorage; + + @Shadow @Final + private Long2ObjectMap chunkLoadStatuses; + + @Shadow @Final + private Queue> loadingInbox; + + @Shadow + abstract void stopTicking(T entity); + + @Shadow + abstract void stopTracking(T entity); + + @Shadow + abstract void startTracking(T entity); + + @Shadow + abstract void startTicking(T entity); + + @Shadow + protected abstract boolean storeChunkSections(long chunkPos, Consumer consumer); + + @Shadow + protected abstract void unloadEntity(EntityAccess entityAccess); + + @Shadow + protected abstract boolean addEntity(T entityType, boolean callback); + + @Shadow + protected abstract void ensureChunkQueuedForLoad(long chunkPos); + + /** + * @reason Avoid streams. + * @author AbdElAziz + * */ + @Overwrite + public void addLegacyChunkEntities(Stream stream) { + for (T entity : stream.toList()) { + this.addEntity(entity, true); + + if (entity instanceof Entity entity1) { + entity1.onAddedToWorld(); + } + } + } + + /** + * @reason Avoid streams. + * @author AbdElAziz + * */ + @Overwrite + public void addWorldGenChunkEntities(Stream stream) { + for (T entity : stream.toList()) { + this.addEntity(entity, false); + + if (entity instanceof Entity entity1) { + entity1.onAddedToWorld(); + } + } + } + + /** + * @reason Avoid streams. + * @author AbdElAziz + * */ + @Overwrite + public void updateChunkStatus(ChunkPos chunkPos, Visibility defaultVisibility) { + long i = chunkPos.toLong(); + + if (defaultVisibility == Visibility.HIDDEN) { + this.chunkVisibility.remove(i); + this.chunksToUnload.add(i); + } else { + this.chunkVisibility.put(i, defaultVisibility); + this.chunksToUnload.remove(i); + this.ensureChunkQueuedForLoad(i); + } + + List> list = this.sectionStorage.getExistingSectionsInChunk(i).toList(); + + for (EntitySection section : list) { + Visibility visibility = section.updateChunkStatus(defaultVisibility); + boolean flag = visibility.isAccessible(); + boolean flag1 = defaultVisibility.isAccessible(); + boolean flag2 = visibility.isTicking(); + boolean flag3 = defaultVisibility.isTicking(); + + if (flag2 && !flag3) { + for (T entity : section.getEntities().toList()) { + if (!entity.isAlwaysTicking()) { + this.stopTicking(entity); + } + } + } + + if (flag && !flag1) { + for (T entity : section.getEntities().toList()) { + if (!entity.isAlwaysTicking()) { + this.stopTracking(entity); + } + } + } else if (!flag && flag1) { + for (T entity : section.getEntities().toList()) { + if (!entity.isAlwaysTicking()) { + this.startTracking(entity); + } + } + } + + if (!flag2 && flag3) { + for (T entity : section.getEntities().toList()) { + if (!entity.isAlwaysTicking()) { + this.startTicking(entity); + } + } + } + } + } + + /** + * @reason Avoid streams. + * @author AbdElAziz + * */ + @Overwrite + private boolean processChunkUnload(long chunkPos) { + boolean flag = this.storeChunkSections(chunkPos, (type) -> { + for (EntityAccess entity : type.getPassengersAndSelf().toList()) { + this.unloadEntity(entity); + } + }); + if (!flag) { + return false; + } else { + this.chunkLoadStatuses.remove(chunkPos); + return true; + } + } + + /** + * @reason Avoid streams. + * @author AbdElAziz + * */ + @Overwrite + private void processPendingLoads() { + ChunkEntities chunkEntities; + while((chunkEntities = this.loadingInbox.poll()) != null) { + for (T entity : chunkEntities.getEntities().toList()) { + this.addEntity(entity, true); + + if (entity instanceof Entity entity1) { + entity1.onAddedToWorld(); + } + } + + this.chunkLoadStatuses.put(chunkEntities.getPos().toLong(), PersistentEntitySectionManager.ChunkLoadStatus.LOADED); + } + + } +} diff --git a/src/main/java/com/abdelaziz/canary/mixin/ai/replace_streams/storage/TransientEntitySectionManagerMixin.java b/src/main/java/com/abdelaziz/canary/mixin/ai/replace_streams/storage/TransientEntitySectionManagerMixin.java new file mode 100644 index 0000000..6ff0074 --- /dev/null +++ b/src/main/java/com/abdelaziz/canary/mixin/ai/replace_streams/storage/TransientEntitySectionManagerMixin.java @@ -0,0 +1,65 @@ +package com.abdelaziz.canary.mixin.ai.replace_streams.storage; + +import it.unimi.dsi.fastutil.longs.LongSet; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.entity.*; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(TransientEntitySectionManager.class) +public class TransientEntitySectionManagerMixin { + @Shadow @Final + private LongSet tickingChunks; + + @Shadow @Final + EntitySectionStorage sectionStorage; + + @Shadow @Final + LevelCallback callbacks; + + /** + * @reason Avoid streams. + * @author AbdElAziz + * */ + @Overwrite + public void startTicking(ChunkPos chunkPos) { + long i = chunkPos.toLong(); + this.tickingChunks.add(i); + + for (EntitySection section : this.sectionStorage.getExistingSectionsInChunk(i).toList()) { + Visibility visibility = section.updateChunkStatus(Visibility.TICKING); + + if (!visibility.isTicking()) { + for (T entity : section.getEntities().toList()) { + if (!entity.isAlwaysTicking()) { + this.callbacks.onTickingStart(entity); + } + } + } + } + } + + /** + * @reason Avoid streams. + * @author AbdElAziz + * */ + @Overwrite + public void stopTicking(ChunkPos chunkPos) { + long i = chunkPos.toLong(); + this.tickingChunks.remove(i); + + for (EntitySection section : this.sectionStorage.getExistingSectionsInChunk(i).toList()) { + Visibility visibility = section.updateChunkStatus(Visibility.TRACKED); + + if (visibility.isTicking()) { + for (T entity : section.getEntities().toList()) { + if (!entity.isAlwaysTicking()) { + this.callbacks.onTickingEnd(entity); + } + } + } + } + } +} \ No newline at end of file