From 1feb46711e1905d275e1d22edb7f42932a4286ad Mon Sep 17 00:00:00 2001 From: Taiyou06 Date: Tue, 30 Jul 2024 22:11:06 +0300 Subject: [PATCH 1/4] 1.21 update cycle begins --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 22c7c80..8efcbf6 100755 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ mixinExtras = "0.3.5" paperweight = "1.7.1" shadow = "8.1.2" spotless = "6.25.0" -paper = "1.20.6-R0.1-SNAPSHOT" +paper = "1.21-R0.1-SNAPSHOT" [libraries] jetbrains-annotations = { module = "org.jetbrains:annotations", version.ref = "jetbrains" } From c244617cfd8ddd3b46305c6d306d7fa6cc82a868 Mon Sep 17 00:00:00 2001 From: Taiyou06 Date: Tue, 30 Jul 2024 22:53:01 +0300 Subject: [PATCH 2/4] pain --- .../nitori/access/IMixinChunkEntitySlicesAccess.java | 2 +- .../nitori/tracker/MultithreadedTracker.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkEntitySlicesAccess.java b/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkEntitySlicesAccess.java index 93e34a2..74a052d 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkEntitySlicesAccess.java +++ b/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkEntitySlicesAccess.java @@ -14,7 +14,7 @@ // along with this program. If not, see . package net.gensokyoreimagined.nitori.access; -import com.destroystokyo.paper.util.maplist.EntityList; +import ca.spottedleaf.moonrise.common.list.EntityList; public interface IMixinChunkEntitySlicesAccess { @SuppressWarnings("EmptyMethod") diff --git a/src/main/java/net/gensokyoreimagined/nitori/tracker/MultithreadedTracker.java b/src/main/java/net/gensokyoreimagined/nitori/tracker/MultithreadedTracker.java index 84a5482..ed47c4c 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/tracker/MultithreadedTracker.java +++ b/src/main/java/net/gensokyoreimagined/nitori/tracker/MultithreadedTracker.java @@ -19,8 +19,8 @@ */ import com.google.common.util.concurrent.ThreadFactoryBuilder; -import io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet; -import io.papermc.paper.world.ChunkEntitySlices; +import ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet; //io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet; +import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices; //io.papermc.paper.world.ChunkEntitySlices; import net.gensokyoreimagined.nitori.access.IMixinChunkEntitySlicesAccess; import net.gensokyoreimagined.nitori.access.IMixinChunkMap_TrackedEntityAccess; import net.gensokyoreimagined.nitori.access.IMixinIteratorSafeOrderedReferenceSetAccess; From 036aaf8b72a6198dd9ba81cb3bcc7325fb9b5cd6 Mon Sep 17 00:00:00 2001 From: Altiami Date: Wed, 31 Jul 2024 03:35:43 -0700 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=94=A5=F0=9F=8E=B5I'M=20NOT=20A=20BIG?= =?UTF-8?q?=20FAN=20OF=20PAPER=F0=9F=8E=B5=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IMixinChunkMap_TrackedEntityAccess.java | 5 +- .../nitori/common/block/BlockStateFlags.java | 2 +- .../math/random/RandomGeneratorRandom.java | 5 ++ .../nitori/mixin/ChunkMapMixin.java | 11 +-- .../nitori/mixin/MixinChunkEntitySlices.java | 4 +- .../MixinIteratorSafeOrderedReferenceSet.java | 2 +- .../nitori/tracker/MultithreadedTracker.java | 75 ++++++++----------- 7 files changed, 50 insertions(+), 54 deletions(-) diff --git a/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkMap_TrackedEntityAccess.java b/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkMap_TrackedEntityAccess.java index ef1447f..fb36476 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkMap_TrackedEntityAccess.java +++ b/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkMap_TrackedEntityAccess.java @@ -14,14 +14,15 @@ // along with this program. If not, see . package net.gensokyoreimagined.nitori.access; -import com.destroystokyo.paper.util.misc.PooledLinkedHashSets; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; +import java.util.List; + public interface IMixinChunkMap_TrackedEntityAccess { @SuppressWarnings("EmptyMethod") Entity getEntity(); @SuppressWarnings("EmptyMethod") - void callUpdatePlayers(PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates); + void callUpdatePlayers(List players); } diff --git a/src/main/java/net/gensokyoreimagined/nitori/common/block/BlockStateFlags.java b/src/main/java/net/gensokyoreimagined/nitori/common/block/BlockStateFlags.java index 93a9b4a..85cc09f 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/common/block/BlockStateFlags.java +++ b/src/main/java/net/gensokyoreimagined/nitori/common/block/BlockStateFlags.java @@ -67,7 +67,7 @@ public boolean test(BlockState operand) { OVERSIZED_SHAPE = new TrackedBlockStatePredicate(countingFlags.size()) { @Override public boolean test(BlockState operand) { - return operand.shapeExceedsCube(); + return operand.hasLargeCollisionShape(); } }; countingFlags.add(OVERSIZED_SHAPE); diff --git a/src/main/java/net/gensokyoreimagined/nitori/common/math/random/RandomGeneratorRandom.java b/src/main/java/net/gensokyoreimagined/nitori/common/math/random/RandomGeneratorRandom.java index 3123612..229bb67 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/common/math/random/RandomGeneratorRandom.java +++ b/src/main/java/net/gensokyoreimagined/nitori/common/math/random/RandomGeneratorRandom.java @@ -94,6 +94,11 @@ public RandomSource fromHashOf(String seed) { return new RandomGeneratorRandom((long) seed.hashCode() ^ this.seed); } + @Override + public RandomSource fromSeed(long seed) { + return new RandomGeneratorRandom(seed ^ this.seed); + } + /* @Override public Random split(long seed) { diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/ChunkMapMixin.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/ChunkMapMixin.java index aab125a..993701e 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/ChunkMapMixin.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/ChunkMapMixin.java @@ -14,7 +14,7 @@ // along with this program. If not, see . package net.gensokyoreimagined.nitori.mixin; -import com.destroystokyo.paper.util.misc.PooledLinkedHashSets; +import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel; import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; @@ -42,6 +42,7 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; import javax.annotation.Nullable; @@ -86,13 +87,13 @@ private void reassignEntityTrackers(CallbackInfo ci) { } } - @Inject(method = "processTrackQueue", at = @At("HEAD"), cancellable = true) + @Inject(method = "newTrackerTick", at = @At("HEAD"), cancellable = true) private void atProcessTrackQueueHead(CallbackInfo callbackInfo) { // Implementation of 0107-Multithreaded-Tracker.patch //TODO: Restore config condition //if (NitoriConfig.enableAsyncEntityTracker) { if (this.gensouHacks$multithreadedTracker == null) { - this.gensouHacks$multithreadedTracker = new MultithreadedTracker(this.level.chunkSource.entityTickingChunks, this.gensouHacks$trackerMainThreadTasks); + this.gensouHacks$multithreadedTracker = new MultithreadedTracker(((ChunkSystemServerLevel) this.level).moonrise$getEntityTickingChunks(), this.gensouHacks$trackerMainThreadTasks); } this.gensouHacks$tracking = true; @@ -132,9 +133,9 @@ private void reassignSeenBy(CallbackInfo ci) { @Override @Final @Invoker - public abstract void callUpdatePlayers(PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates); // Mirai -> public + public abstract void callUpdatePlayers(List players); // Mirai -> public - @Redirect(method = "updatePlayers(Lcom/destroystokyo/paper/util/misc/PooledLinkedHashSets$PooledObjectLinkedOpenHashSet;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkMap$TrackedEntity;updatePlayer(Lnet/minecraft/server/level/ServerPlayer;)V")) + @Redirect(method = "updatePlayers", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkMap$TrackedEntity;updatePlayer(Lnet/minecraft/server/level/ServerPlayer;)V")) private void handleCitizensPluginTracking(ChunkMap.TrackedEntity self, ServerPlayer serverPlayer) { // Nitori - Citizens tracker must run on the main thread to avoid cyclic wait if (PluginCompatibilityRegistry.CITIZENS.shouldRedirectToMainThread(self, serverPlayer)) { diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinChunkEntitySlices.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinChunkEntitySlices.java index 8560844..2d8c418 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinChunkEntitySlices.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinChunkEntitySlices.java @@ -14,8 +14,8 @@ // along with this program. If not, see . package net.gensokyoreimagined.nitori.mixin; -import com.destroystokyo.paper.util.maplist.EntityList; -import io.papermc.paper.world.ChunkEntitySlices; +import ca.spottedleaf.moonrise.common.list.EntityList; +import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices; import net.gensokyoreimagined.nitori.access.IMixinChunkEntitySlicesAccess; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinIteratorSafeOrderedReferenceSet.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinIteratorSafeOrderedReferenceSet.java index 12049aa..f74f4a5 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinIteratorSafeOrderedReferenceSet.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinIteratorSafeOrderedReferenceSet.java @@ -14,7 +14,7 @@ // along with this program. If not, see . package net.gensokyoreimagined.nitori.mixin; -import io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet; +import ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet; import net.gensokyoreimagined.nitori.access.IMixinIteratorSafeOrderedReferenceSetAccess; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/main/java/net/gensokyoreimagined/nitori/tracker/MultithreadedTracker.java b/src/main/java/net/gensokyoreimagined/nitori/tracker/MultithreadedTracker.java index ed47c4c..0d688b8 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/tracker/MultithreadedTracker.java +++ b/src/main/java/net/gensokyoreimagined/nitori/tracker/MultithreadedTracker.java @@ -18,6 +18,8 @@ * Ported from Petal, derived from Airplane */ +import ca.spottedleaf.moonrise.common.list.ReferenceList; +import ca.spottedleaf.moonrise.common.misc.NearbyPlayers; import com.google.common.util.concurrent.ThreadFactoryBuilder; import ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet; //io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet; import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices; //io.papermc.paper.world.ChunkEntitySlices; @@ -26,9 +28,13 @@ import net.gensokyoreimagined.nitori.access.IMixinIteratorSafeOrderedReferenceSetAccess; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.chunk.LevelChunk; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; import java.util.concurrent.Executors; @@ -47,64 +53,44 @@ private enum TrackerStage { .setPriority(Thread.NORM_PRIORITY - 2) .build()); - private final IteratorSafeOrderedReferenceSet entityTickingChunks; + private final ReferenceList entityTickingChunks; private final AtomicInteger taskIndex = new AtomicInteger(); private final ConcurrentLinkedQueue mainThreadTasks; private final AtomicInteger finishedTasks = new AtomicInteger(); - public MultithreadedTracker(IteratorSafeOrderedReferenceSet entityTickingChunks, ConcurrentLinkedQueue mainThreadTasks) { + public MultithreadedTracker(ReferenceList entityTickingChunks, ConcurrentLinkedQueue mainThreadTasks) { this.entityTickingChunks = entityTickingChunks; this.mainThreadTasks = mainThreadTasks; } public void tick() { - int iterator = this.entityTickingChunks.createRawIterator(); + this.taskIndex.set(0); + this.finishedTasks.set(0); - if (iterator == -1) { - return; + for (int i = 0; i < parallelism; i++) { + trackerExecutor.execute(this::runUpdatePlayers); } // start with updating players - try { - this.taskIndex.set(iterator); - this.finishedTasks.set(0); - - for (int i = 0; i < parallelism; i++) { - trackerExecutor.execute(this::runUpdatePlayers); - } - - while (this.taskIndex.get() < ((IMixinIteratorSafeOrderedReferenceSetAccess) (Object) this.entityTickingChunks).getListSize()) { - this.runMainThreadTasks(); - this.handleChunkUpdates(5); // assist - } - - while (this.finishedTasks.get() != parallelism) { - this.runMainThreadTasks(); - } - - this.runMainThreadTasks(); // finish any remaining tasks - } finally { - this.entityTickingChunks.finishRawIterator(); + while (this.taskIndex.get() < this.entityTickingChunks.size()) { + this.runMainThreadTasks(); + this.handleChunkUpdates(5); // assist } // then send changes - iterator = this.entityTickingChunks.createRawIterator(); - - if (iterator == -1) { - return; + while (this.finishedTasks.get() != parallelism) { + this.runMainThreadTasks(); } - try { - do { - LevelChunk chunk = this.entityTickingChunks.rawGet(iterator); + this.runMainThreadTasks(); // finish any remaining tasks - if (chunk != null) { - this.updateChunkEntities(chunk, TrackerStage.SEND_CHANGES); - } - } while (++iterator < ((IMixinIteratorSafeOrderedReferenceSetAccess) (Object) this.entityTickingChunks).getListSize()); - } finally { - this.entityTickingChunks.finishRawIterator(); + for (ServerChunkCache.ChunkAndHolder chunkAndHolder : this.entityTickingChunks) { + LevelChunk chunk = chunkAndHolder.chunk(); + + if (chunk != null) { + this.updateChunkEntities(chunk, TrackerStage.SEND_CHANGES); + } } } @@ -129,9 +115,9 @@ private void runUpdatePlayers() { private boolean handleChunkUpdates(int tasks) { int index; - while ((index = this.taskIndex.getAndAdd(tasks)) < ((IMixinIteratorSafeOrderedReferenceSetAccess) (Object) this.entityTickingChunks).getListSize()) { - for (int i = index; i < index + tasks && i < ((IMixinIteratorSafeOrderedReferenceSetAccess) (Object) this.entityTickingChunks).getListSize(); i++) { - LevelChunk chunk = this.entityTickingChunks.rawGet(i); + while ((index = this.taskIndex.getAndAdd(tasks)) < this.entityTickingChunks.size()) { + for (int i = index; i < index + tasks && i < this.entityTickingChunks.size(); i++) { + LevelChunk chunk = this.entityTickingChunks.getChecked(i).chunk(); if (chunk != null) { try { this.updateChunkEntities(chunk, TrackerStage.UPDATE_PLAYERS); @@ -149,7 +135,7 @@ private boolean handleChunkUpdates(int tasks) { } private void updateChunkEntities(LevelChunk chunk, TrackerStage trackerStage) { - final ChunkEntitySlices entitySlices = chunk.level.getEntityLookup().getChunk(chunk.locX, chunk.locZ); + final ChunkEntitySlices entitySlices = chunk.level.moonrise$getEntityLookup().getChunk(chunk.locX, chunk.locZ); if (entitySlices == null) { return; } @@ -165,7 +151,10 @@ private void updateChunkEntities(LevelChunk chunk, TrackerStage trackerStage) { if (trackerStage == TrackerStage.SEND_CHANGES) { entityTracker.serverEntity.sendChanges(); } else if (trackerStage == TrackerStage.UPDATE_PLAYERS) { - ((IMixinChunkMap_TrackedEntityAccess) (Object) entityTracker).callUpdatePlayers(((IMixinChunkMap_TrackedEntityAccess) (Object) entityTracker).getEntity().getPlayersInTrackRange()); + ReferenceList nearbyPlayers = chunkMap.level.moonrise$getNearbyPlayers().getChunk(entity.chunkPosition()).getPlayers(NearbyPlayers.NearbyMapType.VIEW_DISTANCE); + List nearbyPlayersList = new ArrayList(nearbyPlayers.size()); // intentionally typed as List for requirement clarity + nearbyPlayers.forEach(nearbyPlayersList::add); + ((IMixinChunkMap_TrackedEntityAccess) (Object) entityTracker).callUpdatePlayers(nearbyPlayersList); } } } From 1361c4b05c9c84c140e6b8938606eea1fe86b599 Mon Sep 17 00:00:00 2001 From: Taiyou06 Date: Wed, 31 Jul 2024 19:18:28 +0300 Subject: [PATCH 4/4] 1.21 "works" --- gradle.properties | 2 +- .../nitori/access/IMixinChunkMapAccess.java | 6 +- .../IMixinChunkMap_TrackedEntityAccess.java | 24 +- .../api/inventory/LithiumInventory.java | 22 +- .../common/block/BlockListeningSection.java | 24 +- .../ChunkSectionChangeCallback.java | 204 ++++----- .../SectionedBlockChangeTracker.java | 418 +++++++++--------- .../EntityMovementTrackerSection.java | 32 +- .../SectionedEntityMovementTracker.java | 390 ++++++++-------- .../nitori/common/world/LithiumData.java | 106 ++--- .../world/chunk/LithiumHashPalette.java | 394 ++++++++--------- .../nitori/mixin/ChunkMapMixin.java | 310 ++++++------- .../nitori/mixin/MixinServerEntity.java | 226 +++++----- .../nitori/mixin/MixinServerWorld.java | 70 +-- .../nitori/mixin/MixinSpongeSIMD.java | 34 +- .../nitori/mixin/MixinWorldGenRegion.java | 94 ++-- .../ServerChunkManagerMixin.java | 74 ++-- .../attributes/AttributeContainerMixin.java | 76 ++-- .../block_tracking/ChunkSectionMixin.java | 366 +++++++-------- .../util/accessors/ServerWorldAccessor.java | 24 +- .../campfire/CampfireBlockEntityMixin.java | 134 +++--- .../lit/CampfireBlockEntityMixin.java | 76 ++-- .../unlit/CampfireBlockEntityMixin.java | 64 +-- .../nitori/tracker/MultithreadedTracker.java | 288 ++++++------ src/main/resources/ignite.mod.json | 2 +- src/main/resources/mixins.core.json | 10 - 26 files changed, 1720 insertions(+), 1750 deletions(-) diff --git a/gradle.properties b/gradle.properties index 6ef13b5..442a9e6 100755 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group=net.gensokyoreimagined.nitori -version=1.3-SNAPSHOT +version=1.5-SNAPSHOT description=Converting patches into mixins, for the Ignite Framework org.gradle.parallel=true diff --git a/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkMapAccess.java b/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkMapAccess.java index c6fe9da..63662ce 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkMapAccess.java +++ b/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkMapAccess.java @@ -14,6 +14,6 @@ // along with this program. If not, see . package net.gensokyoreimagined.nitori.access; -public interface IMixinChunkMapAccess { - void gensouHacks$runOnTrackerMainThread(final Runnable runnable); -} +//public interface IMixinChunkMapAccess { +// void gensouHacks$runOnTrackerMainThread(final Runnable runnable); +//} diff --git a/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkMap_TrackedEntityAccess.java b/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkMap_TrackedEntityAccess.java index fb36476..e3c7760 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkMap_TrackedEntityAccess.java +++ b/src/main/java/net/gensokyoreimagined/nitori/access/IMixinChunkMap_TrackedEntityAccess.java @@ -14,15 +14,15 @@ // along with this program. If not, see . package net.gensokyoreimagined.nitori.access; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; - -import java.util.List; - -public interface IMixinChunkMap_TrackedEntityAccess { - @SuppressWarnings("EmptyMethod") - Entity getEntity(); - - @SuppressWarnings("EmptyMethod") - void callUpdatePlayers(List players); -} +//import net.minecraft.server.level.ServerPlayer; +//import net.minecraft.world.entity.Entity; +// +//import java.util.List; +// +//public interface IMixinChunkMap_TrackedEntityAccess { +// @SuppressWarnings("EmptyMethod") +// Entity getEntity(); +// +// @SuppressWarnings("EmptyMethod") +// void callUpdatePlayers(List players); +//} diff --git a/src/main/java/net/gensokyoreimagined/nitori/api/inventory/LithiumInventory.java b/src/main/java/net/gensokyoreimagined/nitori/api/inventory/LithiumInventory.java index 6dd14af..eaca039 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/api/inventory/LithiumInventory.java +++ b/src/main/java/net/gensokyoreimagined/nitori/api/inventory/LithiumInventory.java @@ -5,27 +5,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; -/** - * Provides the ability for mods to allow Lithium's hopper optimizations to access their inventories' for item transfers. - * This exists because Lithium's optimized hopper logic will only interact with inventories more efficiently than - * vanilla if the stack list can be directly accessed and replaced with Lithium's custom stack list. - * It is not required to implement this interface, but doing so will allow the mod's inventories to benefit from - * Lithium's optimizations. - *

- * This interface should be implemented by your {@link net.minecraft.inventory.Inventory} or - * {@link net.minecraft.inventory.SidedInventory} type to access the stack list. - *

- * An inventory must not extend {@link net.minecraft.block.entity.BlockEntity} if it has a supporting block that - * implements {@link net.minecraft.block.InventoryProvider}. - *

- * The hopper interaction behavior of a LithiumInventory should only change if the content of the inventory - * stack list also changes. For example, an inventory which only accepts an item if it already contains an item of the - * same type would work fine (changing the acceptance condition only happens when changing the inventory contents here). - * However, an inventory which accepts an item only if a certain block is near its position will need to signal this - * change to hoppers by calling {@link LithiumNonNullList#changedInteractionConditions()}. - * - * @author 2No2Name - */ + public interface LithiumInventory extends ContainerEntity { /** diff --git a/src/main/java/net/gensokyoreimagined/nitori/common/block/BlockListeningSection.java b/src/main/java/net/gensokyoreimagined/nitori/common/block/BlockListeningSection.java index 41c22a7..21dc0ed 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/common/block/BlockListeningSection.java +++ b/src/main/java/net/gensokyoreimagined/nitori/common/block/BlockListeningSection.java @@ -1,14 +1,14 @@ package net.gensokyoreimagined.nitori.common.block; -import net.gensokyoreimagined.nitori.common.entity.block_tracking.SectionedBlockChangeTracker; -import net.minecraft.core.SectionPos; -import net.minecraft.world.level.Level; - -public interface BlockListeningSection { - - void lithium$addToCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker, long sectionPos, Level world); - - void lithium$removeFromCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker); - - void lithium$invalidateListeningSection(SectionPos sectionPos); -} \ No newline at end of file +//import net.gensokyoreimagined.nitori.common.entity.block_tracking.SectionedBlockChangeTracker; +//import net.minecraft.core.SectionPos; +//import net.minecraft.world.level.Level; +// +//public interface BlockListeningSection { +// +// void lithium$addToCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker, long sectionPos, Level world); +// +// void lithium$removeFromCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker); +// +// void lithium$invalidateListeningSection(SectionPos sectionPos); +//} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/common/entity/block_tracking/ChunkSectionChangeCallback.java b/src/main/java/net/gensokyoreimagined/nitori/common/entity/block_tracking/ChunkSectionChangeCallback.java index 769c28e..5b5c61e 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/common/entity/block_tracking/ChunkSectionChangeCallback.java +++ b/src/main/java/net/gensokyoreimagined/nitori/common/entity/block_tracking/ChunkSectionChangeCallback.java @@ -1,104 +1,104 @@ package net.gensokyoreimagined.nitori.common.entity.block_tracking; -import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; -import net.gensokyoreimagined.nitori.common.block.BlockListeningSection; -import net.gensokyoreimagined.nitori.common.block.BlockStateFlags; -import net.gensokyoreimagined.nitori.common.block.ListeningBlockStatePredicate; -import net.gensokyoreimagined.nitori.common.util.Pos; -import net.gensokyoreimagined.nitori.common.world.LithiumData; -import net.gensokyoreimagined.nitori.common.world.chunk.ChunkStatusTracker; -import net.minecraft.core.SectionPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.chunk.LevelChunkSection; - -import java.util.ArrayList; - -public final class ChunkSectionChangeCallback { - private final ArrayList[] trackers; - private short listeningMask; - - static { - if (BlockListeningSection.class.isAssignableFrom(LevelChunkSection.class)) { - ChunkStatusTracker.registerUnloadCallback((serverWorld, chunkPos) -> { - Long2ReferenceOpenHashMap changeCallbacks = ((LithiumData) serverWorld).lithium$getData().chunkSectionChangeCallbacks(); - int x = chunkPos.x; - int z = chunkPos.z; - for (int y = Pos.SectionYCoord.getMinYSection(serverWorld); y <= Pos.SectionYCoord.getMaxYSectionInclusive(serverWorld); y++) { - SectionPos chunkSectionPos = SectionPos.of(x, y, z); - ChunkSectionChangeCallback chunkSectionChangeCallback = changeCallbacks.remove(chunkSectionPos.asLong()); - if (chunkSectionChangeCallback != null) { - chunkSectionChangeCallback.onChunkSectionInvalidated(chunkSectionPos); - } - } - }); - } - } - - public ChunkSectionChangeCallback() { - //noinspection unchecked - this.trackers = new ArrayList[BlockStateFlags.NUM_LISTENING_FLAGS]; - this.listeningMask = 0; - } - - public static ChunkSectionChangeCallback create(long sectionPos, Level world) { - ChunkSectionChangeCallback chunkSectionChangeCallback = new ChunkSectionChangeCallback(); - Long2ReferenceOpenHashMap changeCallbacks = ((LithiumData) world).lithium$getData().chunkSectionChangeCallbacks(); - ChunkSectionChangeCallback previous = changeCallbacks.put(sectionPos, chunkSectionChangeCallback); - if (previous != null) { - previous.onChunkSectionInvalidated(SectionPos.of(sectionPos)); - } - return chunkSectionChangeCallback; - } - - public short onBlockChange(int blockGroupIndex, BlockListeningSection section) { - ArrayList sectionedBlockChangeTrackers = this.trackers[blockGroupIndex]; - this.trackers[blockGroupIndex] = null; - if (sectionedBlockChangeTrackers != null) { - //noinspection ForLoopReplaceableByForEach - for (int i = 0; i < sectionedBlockChangeTrackers.size(); i++) { - sectionedBlockChangeTrackers.get(i).setChanged(section); - } - } - this.listeningMask &= (short) ~(1 << blockGroupIndex); - - return this.listeningMask; - } - - public short addTracker(SectionedBlockChangeTracker tracker, ListeningBlockStatePredicate blockGroup) { - int blockGroupIndex = blockGroup.getIndex(); - ArrayList sectionedBlockChangeTrackers = this.trackers[blockGroupIndex]; - if (sectionedBlockChangeTrackers == null) { - this.trackers[blockGroupIndex] = (sectionedBlockChangeTrackers = new ArrayList<>()); - } - sectionedBlockChangeTrackers.add(tracker); - - this.listeningMask |= (short) (1 << blockGroupIndex); - return this.listeningMask; - } - - public short removeTracker(SectionedBlockChangeTracker tracker, ListeningBlockStatePredicate blockGroup) { - int blockGroupIndex = blockGroup.getIndex(); - ArrayList sectionedBlockChangeTrackers = this.trackers[blockGroupIndex]; - if (sectionedBlockChangeTrackers != null) { - sectionedBlockChangeTrackers.remove(tracker); - if (sectionedBlockChangeTrackers.isEmpty()) { - this.listeningMask &= (short) ~(1 << blockGroup.getIndex()); - } - } - return this.listeningMask; - } - - public void onChunkSectionInvalidated(SectionPos sectionPos) { - for (int flagIndex = 0; flagIndex < this.trackers.length; flagIndex++) { - ArrayList sectionedBlockChangeTrackers = this.trackers[flagIndex]; - this.trackers[flagIndex] = null; - if (sectionedBlockChangeTrackers != null) { - //noinspection ForLoopReplaceableByForEach - for (int i = 0; i < sectionedBlockChangeTrackers.size(); i++) { - sectionedBlockChangeTrackers.get(i).onChunkSectionInvalidated(sectionPos); - } - } - } - this.listeningMask = 0; - } -} \ No newline at end of file +//import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; +//import net.gensokyoreimagined.nitori.common.block.BlockListeningSection; +//import net.gensokyoreimagined.nitori.common.block.BlockStateFlags; +//import net.gensokyoreimagined.nitori.common.block.ListeningBlockStatePredicate; +//import net.gensokyoreimagined.nitori.common.util.Pos; +//import net.gensokyoreimagined.nitori.common.world.LithiumData; +//import net.gensokyoreimagined.nitori.common.world.chunk.ChunkStatusTracker; +//import net.minecraft.core.SectionPos; +//import net.minecraft.world.level.Level; +//import net.minecraft.world.level.chunk.LevelChunkSection; +// +//import java.util.ArrayList; +// +//public final class ChunkSectionChangeCallback { +// private final ArrayList[] trackers; +// private short listeningMask; +// +// static { +// if (BlockListeningSection.class.isAssignableFrom(LevelChunkSection.class)) { +// ChunkStatusTracker.registerUnloadCallback((serverWorld, chunkPos) -> { +// Long2ReferenceOpenHashMap changeCallbacks = ((LithiumData) serverWorld).lithium$getData().chunkSectionChangeCallbacks(); +// int x = chunkPos.x; +// int z = chunkPos.z; +// for (int y = Pos.SectionYCoord.getMinYSection(serverWorld); y <= Pos.SectionYCoord.getMaxYSectionInclusive(serverWorld); y++) { +// SectionPos chunkSectionPos = SectionPos.of(x, y, z); +// ChunkSectionChangeCallback chunkSectionChangeCallback = changeCallbacks.remove(chunkSectionPos.asLong()); +// if (chunkSectionChangeCallback != null) { +// chunkSectionChangeCallback.onChunkSectionInvalidated(chunkSectionPos); +// } +// } +// }); +// } +// } +// +// public ChunkSectionChangeCallback() { +// //noinspection unchecked +// this.trackers = new ArrayList[BlockStateFlags.NUM_LISTENING_FLAGS]; +// this.listeningMask = 0; +// } +// +// public static ChunkSectionChangeCallback create(long sectionPos, Level world) { +// ChunkSectionChangeCallback chunkSectionChangeCallback = new ChunkSectionChangeCallback(); +// Long2ReferenceOpenHashMap changeCallbacks = ((LithiumData) world).lithium$getData().chunkSectionChangeCallbacks(); +// ChunkSectionChangeCallback previous = changeCallbacks.put(sectionPos, chunkSectionChangeCallback); +// if (previous != null) { +// previous.onChunkSectionInvalidated(SectionPos.of(sectionPos)); +// } +// return chunkSectionChangeCallback; +// } +// +// public short onBlockChange(int blockGroupIndex, BlockListeningSection section) { +// ArrayList sectionedBlockChangeTrackers = this.trackers[blockGroupIndex]; +// this.trackers[blockGroupIndex] = null; +// if (sectionedBlockChangeTrackers != null) { +// //noinspection ForLoopReplaceableByForEach +// for (int i = 0; i < sectionedBlockChangeTrackers.size(); i++) { +// sectionedBlockChangeTrackers.get(i).setChanged(section); +// } +// } +// this.listeningMask &= (short) ~(1 << blockGroupIndex); +// +// return this.listeningMask; +// } +// +// public short addTracker(SectionedBlockChangeTracker tracker, ListeningBlockStatePredicate blockGroup) { +// int blockGroupIndex = blockGroup.getIndex(); +// ArrayList sectionedBlockChangeTrackers = this.trackers[blockGroupIndex]; +// if (sectionedBlockChangeTrackers == null) { +// this.trackers[blockGroupIndex] = (sectionedBlockChangeTrackers = new ArrayList<>()); +// } +// sectionedBlockChangeTrackers.add(tracker); +// +// this.listeningMask |= (short) (1 << blockGroupIndex); +// return this.listeningMask; +// } +// +// public short removeTracker(SectionedBlockChangeTracker tracker, ListeningBlockStatePredicate blockGroup) { +// int blockGroupIndex = blockGroup.getIndex(); +// ArrayList sectionedBlockChangeTrackers = this.trackers[blockGroupIndex]; +// if (sectionedBlockChangeTrackers != null) { +// sectionedBlockChangeTrackers.remove(tracker); +// if (sectionedBlockChangeTrackers.isEmpty()) { +// this.listeningMask &= (short) ~(1 << blockGroup.getIndex()); +// } +// } +// return this.listeningMask; +// } +// +// public void onChunkSectionInvalidated(SectionPos sectionPos) { +// for (int flagIndex = 0; flagIndex < this.trackers.length; flagIndex++) { +// ArrayList sectionedBlockChangeTrackers = this.trackers[flagIndex]; +// this.trackers[flagIndex] = null; +// if (sectionedBlockChangeTrackers != null) { +// //noinspection ForLoopReplaceableByForEach +// for (int i = 0; i < sectionedBlockChangeTrackers.size(); i++) { +// sectionedBlockChangeTrackers.get(i).onChunkSectionInvalidated(sectionPos); +// } +// } +// } +// this.listeningMask = 0; +// } +//} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/common/entity/block_tracking/SectionedBlockChangeTracker.java b/src/main/java/net/gensokyoreimagined/nitori/common/entity/block_tracking/SectionedBlockChangeTracker.java index 4d8ce4c..a0247d8 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/common/entity/block_tracking/SectionedBlockChangeTracker.java +++ b/src/main/java/net/gensokyoreimagined/nitori/common/entity/block_tracking/SectionedBlockChangeTracker.java @@ -1,211 +1,211 @@ package net.gensokyoreimagined.nitori.common.entity.block_tracking; -import net.gensokyoreimagined.nitori.common.block.BlockListeningSection; -import net.gensokyoreimagined.nitori.common.block.ListeningBlockStatePredicate; -import net.gensokyoreimagined.nitori.common.util.Pos; -import net.gensokyoreimagined.nitori.common.util.deduplication.LithiumInterner; -import net.gensokyoreimagined.nitori.common.util.tuples.WorldSectionBox; -import net.gensokyoreimagined.nitori.common.world.LithiumData; -import net.minecraft.world.phys.AABB; -import net.minecraft.core.SectionPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.LevelChunkSection; -import net.minecraft.world.level.chunk.status.ChunkStatus; - -import java.util.ArrayList; -import java.util.Objects; - -public class SectionedBlockChangeTracker { - public final WorldSectionBox trackedWorldSections; - public final ListeningBlockStatePredicate blockGroup; - - private long maxChangeTime; - - private int timesRegistered; - //Some sections may not exist / be unloaded. We have to be aware of those. //TODO Invalidation when sections / chunks unload (but the entity does not (?), not sure whether this is possible) - boolean isListeningToAll = false; - private ArrayList sectionsNotListeningTo = null; - private ArrayList sectionsUnsubscribed = null; - - public SectionedBlockChangeTracker(WorldSectionBox trackedWorldSections, ListeningBlockStatePredicate blockGroup) { - this.trackedWorldSections = trackedWorldSections; - this.blockGroup = blockGroup; - - this.maxChangeTime = 0; - } - - public boolean matchesMovedBox(AABB box) { - return this.trackedWorldSections.matchesRelevantBlocksBox(box); - } - - public static SectionedBlockChangeTracker registerAt(Level world, AABB entityBoundingBox, ListeningBlockStatePredicate blockGroup) { - WorldSectionBox worldSectionBox = WorldSectionBox.relevantExpandedBlocksBox(world, entityBoundingBox); - SectionedBlockChangeTracker tracker = new SectionedBlockChangeTracker(worldSectionBox, blockGroup); - - LithiumInterner blockChangeTrackers = ((LithiumData) world).lithium$getData().blockChangeTrackers(); - tracker = blockChangeTrackers.getCanonical(tracker); - - tracker.register(); - return tracker; - } - - long getWorldTime() { - return this.trackedWorldSections.world().getGameTime(); - } - - public void register() { - if (this.timesRegistered == 0) { - WorldSectionBox trackedSections = this.trackedWorldSections; - for (int x = trackedSections.chunkX1(); x < trackedSections.chunkX2(); x++) { - for (int z = trackedSections.chunkZ1(); z < trackedSections.chunkZ2(); z++) { - Level world = trackedSections.world(); - ChunkAccess chunk = world.getChunk(x, z, ChunkStatus.FULL, false); - LevelChunkSection[] sectionArray = chunk == null ? null : chunk.getSections(); - for (int y = trackedSections.chunkY1(); y < trackedSections.chunkY2(); y++) { - if (Pos.SectionYCoord.getMinYSection(world) > y || Pos.SectionYCoord.getMaxYSectionExclusive(world) <= y) { - continue; - } - SectionPos sectionPos = SectionPos.of(x, y, z); - if (sectionArray == null) { - if (this.sectionsNotListeningTo == null) { - this.sectionsNotListeningTo = new ArrayList<>(); - } - this.sectionsNotListeningTo.add(sectionPos); - continue; - } - LevelChunkSection section = sectionArray[Pos.SectionYIndex.fromSectionCoord(world, y)]; - - BlockListeningSection blockListeningSection = (BlockListeningSection) section; - blockListeningSection.lithium$addToCallback(this.blockGroup, this, SectionPos.asLong(x, y, z), world); - } - } - } - this.isListeningToAll = (this.sectionsNotListeningTo == null || this.sectionsNotListeningTo.isEmpty()) - && (this.sectionsUnsubscribed == null || this.sectionsUnsubscribed.isEmpty()); - this.setChanged(this.getWorldTime()); - } - this.timesRegistered++; - } - - public void unregister() { - if (--this.timesRegistered > 0) { - return; - } - WorldSectionBox trackedSections = this.trackedWorldSections; - Level world = trackedSections.world(); - for (int x = trackedSections.chunkX1(); x < trackedSections.chunkX2(); x++) { - for (int z = trackedSections.chunkZ1(); z < trackedSections.chunkZ2(); z++) { - ChunkAccess chunk = world.getChunk(x, z, ChunkStatus.FULL, false); - LevelChunkSection[] sectionArray = chunk == null ? null : chunk.getSections(); - for (int y = trackedSections.chunkY1(); y < trackedSections.chunkY2(); y++) { - - if (sectionArray == null) { - continue; - } - if (Pos.SectionYCoord.getMinYSection(world) > y || Pos.SectionYCoord.getMaxYSectionExclusive(world) <= y) { - continue; - } - LevelChunkSection section = sectionArray[Pos.SectionYIndex.fromSectionCoord(world, y)]; - - BlockListeningSection blockListeningSection = (BlockListeningSection) section; - blockListeningSection.lithium$removeFromCallback(this.blockGroup, this); - } - } - } - this.sectionsNotListeningTo = null; - LithiumInterner blockChangeTrackers = ((LithiumData) world).lithium$getData().blockChangeTrackers(); - blockChangeTrackers.deleteCanonical(this); - } - - public void listenToAllSections() { - boolean changed = false; - ArrayList notListeningTo = this.sectionsNotListeningTo; - if (notListeningTo != null) { - for (int i = notListeningTo.size() - 1; i >= 0; i--) { - changed = true; - SectionPos chunkSectionPos = notListeningTo.get(i); - Level world = this.trackedWorldSections.world(); - ChunkAccess chunk = world.getChunk(chunkSectionPos.getX(), chunkSectionPos.getZ(), ChunkStatus.FULL, false); - if (chunk != null) { - notListeningTo.remove(i); - } else { - //Chunk not loaded, cannot listen to all sections. - return; - } - LevelChunkSection section = chunk.getSections()[Pos.SectionYIndex.fromSectionCoord(world, chunkSectionPos.getY())]; - BlockListeningSection blockListeningSection = (BlockListeningSection) section; - blockListeningSection.lithium$addToCallback(this.blockGroup, this, chunkSectionPos.asLong(), world); - } - } - if (this.sectionsUnsubscribed != null) { - ArrayList unsubscribed = this.sectionsUnsubscribed; - for (int i = unsubscribed.size() - 1; i >= 0; i--) { - changed = true; - BlockListeningSection blockListeningSection = unsubscribed.remove(i); - blockListeningSection.lithium$addToCallback(this.blockGroup, this, Long.MIN_VALUE, null); - } - } - this.isListeningToAll = true; - if (changed) { - this.setChanged(this.getWorldTime()); - } - } - - public void setChanged(BlockListeningSection section) { - if (this.sectionsUnsubscribed == null) { - this.sectionsUnsubscribed = new ArrayList<>(); - } - this.sectionsUnsubscribed.add(section); - this.setChanged(this.getWorldTime()); - this.isListeningToAll = false; - } - - public void setChanged(long atTime) { - if (atTime > this.maxChangeTime) { - this.maxChangeTime = atTime; - } - } - - /** - * Method to quickly check whether any relevant blocks changed inside the relevant chunk sections after - * the last test. - * - * @param lastCheckedTime time of the last interaction attempt - * @return whether any relevant entity moved in the tracked area - */ - public boolean isUnchangedSince(long lastCheckedTime) { - if (lastCheckedTime <= this.maxChangeTime) { - return false; - } - if (!this.isListeningToAll) { - this.listenToAllSections(); - return this.isListeningToAll && lastCheckedTime > this.maxChangeTime; - } - return true; - } - - //Do not modify, used for deduplication of instances - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - var that = (SectionedBlockChangeTracker) obj; - return Objects.equals(this.trackedWorldSections, that.trackedWorldSections) && - Objects.equals(this.blockGroup, that.blockGroup); - } - //Do not modify, used for deduplication of instances - @Override - public int hashCode() { - return this.getClass().hashCode() ^ this.trackedWorldSections.hashCode() ^ this.blockGroup.hashCode(); - } - - public void onChunkSectionInvalidated(SectionPos sectionPos) { - if (this.sectionsNotListeningTo == null) { - this.sectionsNotListeningTo = new ArrayList<>(); - } - this.sectionsNotListeningTo.add(sectionPos); - this.setChanged(this.getWorldTime()); - this.isListeningToAll = false; - } -} \ No newline at end of file +//import net.gensokyoreimagined.nitori.common.block.BlockListeningSection; +//import net.gensokyoreimagined.nitori.common.block.ListeningBlockStatePredicate; +//import net.gensokyoreimagined.nitori.common.util.Pos; +//import net.gensokyoreimagined.nitori.common.util.deduplication.LithiumInterner; +//import net.gensokyoreimagined.nitori.common.util.tuples.WorldSectionBox; +//import net.gensokyoreimagined.nitori.common.world.LithiumData; +//import net.minecraft.world.phys.AABB; +//import net.minecraft.core.SectionPos; +//import net.minecraft.world.level.Level; +//import net.minecraft.world.level.chunk.ChunkAccess; +//import net.minecraft.world.level.chunk.LevelChunkSection; +//import net.minecraft.world.level.chunk.status.ChunkStatus; +// +//import java.util.ArrayList; +//import java.util.Objects; +// +//public class SectionedBlockChangeTracker { +// public final WorldSectionBox trackedWorldSections; +// public final ListeningBlockStatePredicate blockGroup; +// +// private long maxChangeTime; +// +// private int timesRegistered; +// //Some sections may not exist / be unloaded. We have to be aware of those. //TODO Invalidation when sections / chunks unload (but the entity does not (?), not sure whether this is possible) +// boolean isListeningToAll = false; +// private ArrayList sectionsNotListeningTo = null; +// private ArrayList sectionsUnsubscribed = null; +// +// public SectionedBlockChangeTracker(WorldSectionBox trackedWorldSections, ListeningBlockStatePredicate blockGroup) { +// this.trackedWorldSections = trackedWorldSections; +// this.blockGroup = blockGroup; +// +// this.maxChangeTime = 0; +// } +// +// public boolean matchesMovedBox(AABB box) { +// return this.trackedWorldSections.matchesRelevantBlocksBox(box); +// } +// +// public static SectionedBlockChangeTracker registerAt(Level world, AABB entityBoundingBox, ListeningBlockStatePredicate blockGroup) { +// WorldSectionBox worldSectionBox = WorldSectionBox.relevantExpandedBlocksBox(world, entityBoundingBox); +// SectionedBlockChangeTracker tracker = new SectionedBlockChangeTracker(worldSectionBox, blockGroup); +// +// LithiumInterner blockChangeTrackers = ((LithiumData) world).lithium$getData().blockChangeTrackers(); +// tracker = blockChangeTrackers.getCanonical(tracker); +// +// tracker.register(); +// return tracker; +// } +// +// long getWorldTime() { +// return this.trackedWorldSections.world().getGameTime(); +// } +// +// public void register() { +// if (this.timesRegistered == 0) { +// WorldSectionBox trackedSections = this.trackedWorldSections; +// for (int x = trackedSections.chunkX1(); x < trackedSections.chunkX2(); x++) { +// for (int z = trackedSections.chunkZ1(); z < trackedSections.chunkZ2(); z++) { +// Level world = trackedSections.world(); +// ChunkAccess chunk = world.getChunk(x, z, ChunkStatus.FULL, false); +// LevelChunkSection[] sectionArray = chunk == null ? null : chunk.getSections(); +// for (int y = trackedSections.chunkY1(); y < trackedSections.chunkY2(); y++) { +// if (Pos.SectionYCoord.getMinYSection(world) > y || Pos.SectionYCoord.getMaxYSectionExclusive(world) <= y) { +// continue; +// } +// SectionPos sectionPos = SectionPos.of(x, y, z); +// if (sectionArray == null) { +// if (this.sectionsNotListeningTo == null) { +// this.sectionsNotListeningTo = new ArrayList<>(); +// } +// this.sectionsNotListeningTo.add(sectionPos); +// continue; +// } +// LevelChunkSection section = sectionArray[Pos.SectionYIndex.fromSectionCoord(world, y)]; +// +// BlockListeningSection blockListeningSection = (BlockListeningSection) section; +// blockListeningSection.lithium$addToCallback(this.blockGroup, this, SectionPos.asLong(x, y, z), world); +// } +// } +// } +// this.isListeningToAll = (this.sectionsNotListeningTo == null || this.sectionsNotListeningTo.isEmpty()) +// && (this.sectionsUnsubscribed == null || this.sectionsUnsubscribed.isEmpty()); +// this.setChanged(this.getWorldTime()); +// } +// this.timesRegistered++; +// } +// +// public void unregister() { +// if (--this.timesRegistered > 0) { +// return; +// } +// WorldSectionBox trackedSections = this.trackedWorldSections; +// Level world = trackedSections.world(); +// for (int x = trackedSections.chunkX1(); x < trackedSections.chunkX2(); x++) { +// for (int z = trackedSections.chunkZ1(); z < trackedSections.chunkZ2(); z++) { +// ChunkAccess chunk = world.getChunk(x, z, ChunkStatus.FULL, false); +// LevelChunkSection[] sectionArray = chunk == null ? null : chunk.getSections(); +// for (int y = trackedSections.chunkY1(); y < trackedSections.chunkY2(); y++) { +// +// if (sectionArray == null) { +// continue; +// } +// if (Pos.SectionYCoord.getMinYSection(world) > y || Pos.SectionYCoord.getMaxYSectionExclusive(world) <= y) { +// continue; +// } +// LevelChunkSection section = sectionArray[Pos.SectionYIndex.fromSectionCoord(world, y)]; +// +// BlockListeningSection blockListeningSection = (BlockListeningSection) section; +// blockListeningSection.lithium$removeFromCallback(this.blockGroup, this); +// } +// } +// } +// this.sectionsNotListeningTo = null; +// LithiumInterner blockChangeTrackers = ((LithiumData) world).lithium$getData().blockChangeTrackers(); +// blockChangeTrackers.deleteCanonical(this); +// } +// +// public void listenToAllSections() { +// boolean changed = false; +// ArrayList notListeningTo = this.sectionsNotListeningTo; +// if (notListeningTo != null) { +// for (int i = notListeningTo.size() - 1; i >= 0; i--) { +// changed = true; +// SectionPos chunkSectionPos = notListeningTo.get(i); +// Level world = this.trackedWorldSections.world(); +// ChunkAccess chunk = world.getChunk(chunkSectionPos.getX(), chunkSectionPos.getZ(), ChunkStatus.FULL, false); +// if (chunk != null) { +// notListeningTo.remove(i); +// } else { +// //Chunk not loaded, cannot listen to all sections. +// return; +// } +// LevelChunkSection section = chunk.getSections()[Pos.SectionYIndex.fromSectionCoord(world, chunkSectionPos.getY())]; +// BlockListeningSection blockListeningSection = (BlockListeningSection) section; +// blockListeningSection.lithium$addToCallback(this.blockGroup, this, chunkSectionPos.asLong(), world); +// } +// } +// if (this.sectionsUnsubscribed != null) { +// ArrayList unsubscribed = this.sectionsUnsubscribed; +// for (int i = unsubscribed.size() - 1; i >= 0; i--) { +// changed = true; +// BlockListeningSection blockListeningSection = unsubscribed.remove(i); +// blockListeningSection.lithium$addToCallback(this.blockGroup, this, Long.MIN_VALUE, null); +// } +// } +// this.isListeningToAll = true; +// if (changed) { +// this.setChanged(this.getWorldTime()); +// } +// } +// +// public void setChanged(BlockListeningSection section) { +// if (this.sectionsUnsubscribed == null) { +// this.sectionsUnsubscribed = new ArrayList<>(); +// } +// this.sectionsUnsubscribed.add(section); +// this.setChanged(this.getWorldTime()); +// this.isListeningToAll = false; +// } +// +// public void setChanged(long atTime) { +// if (atTime > this.maxChangeTime) { +// this.maxChangeTime = atTime; +// } +// } +// +// /** +// * Method to quickly check whether any relevant blocks changed inside the relevant chunk sections after +// * the last test. +// * +// * @param lastCheckedTime time of the last interaction attempt +// * @return whether any relevant entity moved in the tracked area +// */ +// public boolean isUnchangedSince(long lastCheckedTime) { +// if (lastCheckedTime <= this.maxChangeTime) { +// return false; +// } +// if (!this.isListeningToAll) { +// this.listenToAllSections(); +// return this.isListeningToAll && lastCheckedTime > this.maxChangeTime; +// } +// return true; +// } +// +// //Do not modify, used for deduplication of instances +// @Override +// public boolean equals(Object obj) { +// if (obj == this) return true; +// if (obj == null || obj.getClass() != this.getClass()) return false; +// var that = (SectionedBlockChangeTracker) obj; +// return Objects.equals(this.trackedWorldSections, that.trackedWorldSections) && +// Objects.equals(this.blockGroup, that.blockGroup); +// } +// //Do not modify, used for deduplication of instances +// @Override +// public int hashCode() { +// return this.getClass().hashCode() ^ this.trackedWorldSections.hashCode() ^ this.blockGroup.hashCode(); +// } +// +// public void onChunkSectionInvalidated(SectionPos sectionPos) { +// if (this.sectionsNotListeningTo == null) { +// this.sectionsNotListeningTo = new ArrayList<>(); +// } +// this.sectionsNotListeningTo.add(sectionPos); +// this.setChanged(this.getWorldTime()); +// this.isListeningToAll = false; +// } +//} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/common/entity/movement_tracker/EntityMovementTrackerSection.java b/src/main/java/net/gensokyoreimagined/nitori/common/entity/movement_tracker/EntityMovementTrackerSection.java index 0917f0c..7c58f93 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/common/entity/movement_tracker/EntityMovementTrackerSection.java +++ b/src/main/java/net/gensokyoreimagined/nitori/common/entity/movement_tracker/EntityMovementTrackerSection.java @@ -1,18 +1,18 @@ package net.gensokyoreimagined.nitori.common.entity.movement_tracker; -import net.minecraft.world.level.entity.EntityAccess; -import net.minecraft.world.level.entity.EntitySectionStorage; - -public interface EntityMovementTrackerSection { - void lithium$addListener(SectionedEntityMovementTracker listener); - - void lithium$removeListener(EntitySectionStorage sectionedEntityCache, SectionedEntityMovementTracker listener); - - void lithium$trackEntityMovement(int notificationMask, long time); - - long lithium$getChangeTime(int trackedClass); - - void lithium$listenToMovementOnce(SectionedEntityMovementTracker listener, int trackedClass); - - void lithium$removeListenToMovementOnce(SectionedEntityMovementTracker listener, int trackedClass); -} +//import net.minecraft.world.level.entity.EntityAccess; +//import net.minecraft.world.level.entity.EntitySectionStorage; +// +//public interface EntityMovementTrackerSection { +// void lithium$addListener(SectionedEntityMovementTracker listener); +// +// void lithium$removeListener(EntitySectionStorage sectionedEntityCache, SectionedEntityMovementTracker listener); +// +// void lithium$trackEntityMovement(int notificationMask, long time); +// +// long lithium$getChangeTime(int trackedClass); +// +// void lithium$listenToMovementOnce(SectionedEntityMovementTracker listener, int trackedClass); +// +// void lithium$removeListenToMovementOnce(SectionedEntityMovementTracker listener, int trackedClass); +//} diff --git a/src/main/java/net/gensokyoreimagined/nitori/common/entity/movement_tracker/SectionedEntityMovementTracker.java b/src/main/java/net/gensokyoreimagined/nitori/common/entity/movement_tracker/SectionedEntityMovementTracker.java index d163944..bd9b71c 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/common/entity/movement_tracker/SectionedEntityMovementTracker.java +++ b/src/main/java/net/gensokyoreimagined/nitori/common/entity/movement_tracker/SectionedEntityMovementTracker.java @@ -1,197 +1,197 @@ package net.gensokyoreimagined.nitori.common.entity.movement_tracker; -import it.unimi.dsi.fastutil.HashCommon; -import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; -import net.gensokyoreimagined.nitori.common.util.tuples.WorldSectionBox; -import net.gensokyoreimagined.nitori.common.world.LithiumData; -import net.gensokyoreimagined.nitori.mixin.util.accessors.ServerEntityManagerAccessor; -import net.gensokyoreimagined.nitori.mixin.util.accessors.ServerWorldAccessor; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.core.SectionPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.entity.EntityAccess; -import net.minecraft.world.level.entity.EntitySection; -import net.minecraft.world.level.entity.EntitySectionStorage; - -import java.util.ArrayList; - -public abstract class SectionedEntityMovementTracker { - final WorldSectionBox trackedWorldSections; - final Class clazz; - private final int trackedClass; - ArrayList> sortedSections; - boolean[] sectionVisible; - private int timesRegistered; - private final ArrayList sectionsNotListeningTo; - - private long maxChangeTime; - - private ReferenceOpenHashSet sectionedEntityMovementListeners; - - public SectionedEntityMovementTracker(WorldSectionBox interactionChunks, Class clazz) { - this.clazz = clazz; - this.trackedWorldSections = interactionChunks; - this.trackedClass = MovementTrackerHelper.MOVEMENT_NOTIFYING_ENTITY_CLASSES.indexOf(clazz); - assert this.trackedClass != -1; - this.sectionedEntityMovementListeners = null; - this.sectionsNotListeningTo = new ArrayList<>(); - } - - @Override - public int hashCode() { - return HashCommon.mix(this.trackedWorldSections.hashCode()) ^ HashCommon.mix(this.trackedClass) ^ this.getClass().hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj.getClass() == this.getClass() && - this.clazz == ((SectionedEntityMovementTracker) obj).clazz && - this.trackedWorldSections.equals(((SectionedEntityMovementTracker) obj).trackedWorldSections); - } - - /** - * Method to quickly check whether any relevant entities moved inside the relevant entity sections after - * the last interaction attempt. - * - * @param lastCheckedTime time of the last interaction attempt - * @return whether any relevant entity moved in the tracked area - */ - public boolean isUnchangedSince(long lastCheckedTime) { - if (lastCheckedTime <= this.maxChangeTime) { - return false; - } - if (!this.sectionsNotListeningTo.isEmpty()) { - this.setChanged(this.listenToAllSectionsAndGetMaxChangeTime()); - return lastCheckedTime > this.maxChangeTime; - } - return true; - } - - private long listenToAllSectionsAndGetMaxChangeTime() { - long maxChangeTime = Long.MIN_VALUE; - ArrayList notListeningTo = this.sectionsNotListeningTo; - for (int i = notListeningTo.size() - 1; i >= 0; i--) { - EntityMovementTrackerSection entityMovementTrackerSection = notListeningTo.remove(i); - entityMovementTrackerSection.lithium$listenToMovementOnce(this, this.trackedClass); - maxChangeTime = Math.max(maxChangeTime, entityMovementTrackerSection.lithium$getChangeTime(this.trackedClass)); - } - return maxChangeTime; - } - - public void register(ServerLevel world) { - assert world == this.trackedWorldSections.world(); - - if (this.timesRegistered == 0) { - //noinspection unchecked - EntitySectionStorage cache = ((ServerEntityManagerAccessor) ((ServerWorldAccessor) world).getEntityManager()).getSectionStorage(); - - WorldSectionBox trackedSections = this.trackedWorldSections; - int size = trackedSections.numSections(); - assert size > 0; - this.sortedSections = new ArrayList<>(size); - this.sectionVisible = new boolean[size]; - - //vanilla iteration order in EntitySectionStorage is xzy - //WorldSectionBox upper coordinates are exclusive - for (int x = trackedSections.chunkX1(); x < trackedSections.chunkX2(); x++) { - for (int z = trackedSections.chunkZ1(); z < trackedSections.chunkZ2(); z++) { - for (int y = trackedSections.chunkY1(); y < trackedSections.chunkY2(); y++) { - EntitySection section = cache.getSection(SectionPos.asLong(x, y, z)); - EntityMovementTrackerSection sectionAccess = (EntityMovementTrackerSection) section; - this.sortedSections.add(section); - sectionAccess.lithium$addListener(this); - } - } - } - this.setChanged(world.getGameTime()); - } - - this.timesRegistered++; - } - - public void unRegister(Level world) { - assert world == this.trackedWorldSections.world(); - if (--this.timesRegistered > 0) { - return; - } - assert this.timesRegistered == 0; - //noinspection unchecked - EntitySectionStorage cache = ((ServerEntityManagerAccessor) ((ServerWorldAccessor) world).getEntityManager()).getSectionStorage(); - ((LithiumData) world).lithium$getData().entityMovementTrackers().deleteCanonical(this); - - ArrayList> sections = this.sortedSections; - for (int i = sections.size() - 1; i >= 0; i--) { - EntitySection section = sections.get(i); - EntityMovementTrackerSection sectionAccess = (EntityMovementTrackerSection) section; - sectionAccess.lithium$removeListener(cache, this); - if (!this.sectionsNotListeningTo.remove(section)) { - ((EntityMovementTrackerSection) section).lithium$removeListenToMovementOnce(this, this.trackedClass); - } - } - this.setChanged(world.getGameTime()); - } - - /** - * Register an entity section to this listener, so this listener can look for changes in the section. - */ - public void onSectionEnteredRange(EntityMovementTrackerSection section) { - this.setChanged(this.trackedWorldSections.world().getGameTime()); - //noinspection SuspiciousMethodCalls - int sectionIndex = this.sortedSections.lastIndexOf(section); - this.sectionVisible[sectionIndex] = true; - - this.sectionsNotListeningTo.add(section); - this.notifyAllListeners(); - } - - public void onSectionLeftRange(EntityMovementTrackerSection section) { - this.setChanged(this.trackedWorldSections.world().getGameTime()); - //noinspection SuspiciousMethodCalls - int sectionIndex = this.sortedSections.lastIndexOf(section); - - this.sectionVisible[sectionIndex] = false; - - if (!this.sectionsNotListeningTo.remove(section)) { - section.lithium$removeListenToMovementOnce(this, this.trackedClass); - this.notifyAllListeners(); - } - } - - /** - * Method that marks that new entities might have appeared or moved in the tracked chunk sections. - */ - private void setChanged(long atTime) { - if (atTime > this.maxChangeTime) { - this.maxChangeTime = atTime; - } - } - - public void listenToEntityMovementOnce(SectionedEntityMovementListener listener) { - if (this.sectionedEntityMovementListeners == null) { - this.sectionedEntityMovementListeners = new ReferenceOpenHashSet<>(); - } - this.sectionedEntityMovementListeners.add(listener); - - if (!this.sectionsNotListeningTo.isEmpty()) { - this.setChanged(this.listenToAllSectionsAndGetMaxChangeTime()); - } - - } - - public void emitEntityMovement(int classMask, EntityMovementTrackerSection section) { - if ((classMask & (1 << this.trackedClass)) != 0) { - this.notifyAllListeners(); - this.sectionsNotListeningTo.add(section); - } - } - - private void notifyAllListeners() { - ReferenceOpenHashSet listeners = this.sectionedEntityMovementListeners; - if (listeners != null && !listeners.isEmpty()) { - for (SectionedEntityMovementListener listener : listeners) { - listener.lithium$handleEntityMovement(this.clazz); - } - listeners.clear(); - } - } -} \ No newline at end of file +//import it.unimi.dsi.fastutil.HashCommon; +//import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; +//import net.gensokyoreimagined.nitori.common.util.tuples.WorldSectionBox; +//import net.gensokyoreimagined.nitori.common.world.LithiumData; +//import net.gensokyoreimagined.nitori.mixin.util.accessors.ServerEntityManagerAccessor; +//import net.gensokyoreimagined.nitori.mixin.util.accessors.ServerWorldAccessor; +//import net.minecraft.server.level.ServerLevel; +//import net.minecraft.core.SectionPos; +//import net.minecraft.world.level.Level; +//import net.minecraft.world.level.entity.EntityAccess; +//import net.minecraft.world.level.entity.EntitySection; +//import net.minecraft.world.level.entity.EntitySectionStorage; +// +//import java.util.ArrayList; +// +//public abstract class SectionedEntityMovementTracker { +// final WorldSectionBox trackedWorldSections; +// final Class clazz; +// private final int trackedClass; +// ArrayList> sortedSections; +// boolean[] sectionVisible; +// private int timesRegistered; +// private final ArrayList sectionsNotListeningTo; +// +// private long maxChangeTime; +// +// private ReferenceOpenHashSet sectionedEntityMovementListeners; +// +// public SectionedEntityMovementTracker(WorldSectionBox interactionChunks, Class clazz) { +// this.clazz = clazz; +// this.trackedWorldSections = interactionChunks; +// this.trackedClass = MovementTrackerHelper.MOVEMENT_NOTIFYING_ENTITY_CLASSES.indexOf(clazz); +// assert this.trackedClass != -1; +// this.sectionedEntityMovementListeners = null; +// this.sectionsNotListeningTo = new ArrayList<>(); +// } +// +// @Override +// public int hashCode() { +// return HashCommon.mix(this.trackedWorldSections.hashCode()) ^ HashCommon.mix(this.trackedClass) ^ this.getClass().hashCode(); +// } +// +// @Override +// public boolean equals(Object obj) { +// return obj.getClass() == this.getClass() && +// this.clazz == ((SectionedEntityMovementTracker) obj).clazz && +// this.trackedWorldSections.equals(((SectionedEntityMovementTracker) obj).trackedWorldSections); +// } +// +// /** +// * Method to quickly check whether any relevant entities moved inside the relevant entity sections after +// * the last interaction attempt. +// * +// * @param lastCheckedTime time of the last interaction attempt +// * @return whether any relevant entity moved in the tracked area +// */ +// public boolean isUnchangedSince(long lastCheckedTime) { +// if (lastCheckedTime <= this.maxChangeTime) { +// return false; +// } +// if (!this.sectionsNotListeningTo.isEmpty()) { +// this.setChanged(this.listenToAllSectionsAndGetMaxChangeTime()); +// return lastCheckedTime > this.maxChangeTime; +// } +// return true; +// } +// +// private long listenToAllSectionsAndGetMaxChangeTime() { +// long maxChangeTime = Long.MIN_VALUE; +// ArrayList notListeningTo = this.sectionsNotListeningTo; +// for (int i = notListeningTo.size() - 1; i >= 0; i--) { +// EntityMovementTrackerSection entityMovementTrackerSection = notListeningTo.remove(i); +// entityMovementTrackerSection.lithium$listenToMovementOnce(this, this.trackedClass); +// maxChangeTime = Math.max(maxChangeTime, entityMovementTrackerSection.lithium$getChangeTime(this.trackedClass)); +// } +// return maxChangeTime; +// } +// +// public void register(ServerLevel world) { +// assert world == this.trackedWorldSections.world(); +// +// if (this.timesRegistered == 0) { +// //noinspection unchecked +// EntitySectionStorage cache = ((ServerEntityManagerAccessor) ((ServerWorldAccessor) world).getEntityManager()).getSectionStorage(); +// +// WorldSectionBox trackedSections = this.trackedWorldSections; +// int size = trackedSections.numSections(); +// assert size > 0; +// this.sortedSections = new ArrayList<>(size); +// this.sectionVisible = new boolean[size]; +// +// //vanilla iteration order in EntitySectionStorage is xzy +// //WorldSectionBox upper coordinates are exclusive +// for (int x = trackedSections.chunkX1(); x < trackedSections.chunkX2(); x++) { +// for (int z = trackedSections.chunkZ1(); z < trackedSections.chunkZ2(); z++) { +// for (int y = trackedSections.chunkY1(); y < trackedSections.chunkY2(); y++) { +// EntitySection section = cache.getSection(SectionPos.asLong(x, y, z)); +// EntityMovementTrackerSection sectionAccess = (EntityMovementTrackerSection) section; +// this.sortedSections.add(section); +// sectionAccess.lithium$addListener(this); +// } +// } +// } +// this.setChanged(world.getGameTime()); +// } +// +// this.timesRegistered++; +// } +// +// public void unRegister(Level world) { +// assert world == this.trackedWorldSections.world(); +// if (--this.timesRegistered > 0) { +// return; +// } +// assert this.timesRegistered == 0; +// //noinspection unchecked +// EntitySectionStorage cache = ((ServerEntityManagerAccessor) ((ServerWorldAccessor) world).getEntityManager()).getSectionStorage(); +// ((LithiumData) world).lithium$getData().entityMovementTrackers().deleteCanonical(this); +// +// ArrayList> sections = this.sortedSections; +// for (int i = sections.size() - 1; i >= 0; i--) { +// EntitySection section = sections.get(i); +// EntityMovementTrackerSection sectionAccess = (EntityMovementTrackerSection) section; +// sectionAccess.lithium$removeListener(cache, this); +// if (!this.sectionsNotListeningTo.remove(section)) { +// ((EntityMovementTrackerSection) section).lithium$removeListenToMovementOnce(this, this.trackedClass); +// } +// } +// this.setChanged(world.getGameTime()); +// } +// +// /** +// * Register an entity section to this listener, so this listener can look for changes in the section. +// */ +// public void onSectionEnteredRange(EntityMovementTrackerSection section) { +// this.setChanged(this.trackedWorldSections.world().getGameTime()); +// //noinspection SuspiciousMethodCalls +// int sectionIndex = this.sortedSections.lastIndexOf(section); +// this.sectionVisible[sectionIndex] = true; +// +// this.sectionsNotListeningTo.add(section); +// this.notifyAllListeners(); +// } +// +// public void onSectionLeftRange(EntityMovementTrackerSection section) { +// this.setChanged(this.trackedWorldSections.world().getGameTime()); +// //noinspection SuspiciousMethodCalls +// int sectionIndex = this.sortedSections.lastIndexOf(section); +// +// this.sectionVisible[sectionIndex] = false; +// +// if (!this.sectionsNotListeningTo.remove(section)) { +// section.lithium$removeListenToMovementOnce(this, this.trackedClass); +// this.notifyAllListeners(); +// } +// } +// +// /** +// * Method that marks that new entities might have appeared or moved in the tracked chunk sections. +// */ +// private void setChanged(long atTime) { +// if (atTime > this.maxChangeTime) { +// this.maxChangeTime = atTime; +// } +// } +// +// public void listenToEntityMovementOnce(SectionedEntityMovementListener listener) { +// if (this.sectionedEntityMovementListeners == null) { +// this.sectionedEntityMovementListeners = new ReferenceOpenHashSet<>(); +// } +// this.sectionedEntityMovementListeners.add(listener); +// +// if (!this.sectionsNotListeningTo.isEmpty()) { +// this.setChanged(this.listenToAllSectionsAndGetMaxChangeTime()); +// } +// +// } +// +// public void emitEntityMovement(int classMask, EntityMovementTrackerSection section) { +// if ((classMask & (1 << this.trackedClass)) != 0) { +// this.notifyAllListeners(); +// this.sectionsNotListeningTo.add(section); +// } +// } +// +// private void notifyAllListeners() { +// ReferenceOpenHashSet listeners = this.sectionedEntityMovementListeners; +// if (listeners != null && !listeners.isEmpty()) { +// for (SectionedEntityMovementListener listener : listeners) { +// listener.lithium$handleEntityMovement(this.clazz); +// } +// listeners.clear(); +// } +// } +//} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/common/world/LithiumData.java b/src/main/java/net/gensokyoreimagined/nitori/common/world/LithiumData.java index b0e0fd2..10dc1f1 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/common/world/LithiumData.java +++ b/src/main/java/net/gensokyoreimagined/nitori/common/world/LithiumData.java @@ -1,55 +1,55 @@ package net.gensokyoreimagined.nitori.common.world; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; -import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; -import net.gensokyoreimagined.nitori.common.entity.block_tracking.ChunkSectionChangeCallback; -import net.gensokyoreimagined.nitori.common.entity.block_tracking.SectionedBlockChangeTracker; -import net.gensokyoreimagined.nitori.common.entity.movement_tracker.SectionedEntityMovementTracker; -import net.gensokyoreimagined.nitori.common.util.deduplication.LithiumInterner; -import net.minecraft.world.entity.ai.navigation.PathNavigation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.core.registries.Registries; -import net.minecraft.world.entity.raid.Raid; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.gameevent.GameEventDispatcher; -import net.minecraft.world.level.gameevent.GameEventListenerRegistry; - -public interface LithiumData { - - record Data( - // Map of chunk position -> y section -> game event dispatcher - // This should be faster than the chunk lookup, since there are usually a lot more chunks than - // chunk with game event dispatchers (we only initialize them when non-empty set of listeners) - // All Int2ObjectMap objects are also stored in a field of the corresponding WorldChunk. - Long2ReferenceOpenHashMap> gameEventDispatchersByChunk, - - // Cached ominous banner, must not be mutated. - ItemStack ominousBanner, - - // Set of active mob navigations (active = have a path) - ReferenceOpenHashSet activeNavigations, - - // Block change tracker deduplication - LithiumInterner blockChangeTrackers, - - // Entity movement tracker deduplication - LithiumInterner> entityMovementTrackers, - - // Block ChunkSection listeners - Long2ReferenceOpenHashMap chunkSectionChangeCallbacks - ) { - public Data(Level world) { - this( - new Long2ReferenceOpenHashMap<>(), - world.registryAccess().lookup(Registries.BANNER_PATTERN).map(Raid::getLeaderBannerInstance).orElse(null), - new ReferenceOpenHashSet<>(), - new LithiumInterner<>(), - new LithiumInterner<>(), - new Long2ReferenceOpenHashMap<>() - ); - } - } - - LithiumData.Data lithium$getData(); -} \ No newline at end of file +//import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +//import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; +//import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; +//import net.gensokyoreimagined.nitori.common.entity.block_tracking.ChunkSectionChangeCallback; +//import net.gensokyoreimagined.nitori.common.entity.block_tracking.SectionedBlockChangeTracker; +//import net.gensokyoreimagined.nitori.common.entity.movement_tracker.SectionedEntityMovementTracker; +//import net.gensokyoreimagined.nitori.common.util.deduplication.LithiumInterner; +//import net.minecraft.world.entity.ai.navigation.PathNavigation; +//import net.minecraft.world.item.ItemStack; +//import net.minecraft.core.registries.Registries; +//import net.minecraft.world.entity.raid.Raid; +//import net.minecraft.world.level.Level; +//import net.minecraft.world.level.gameevent.GameEventDispatcher; +//import net.minecraft.world.level.gameevent.GameEventListenerRegistry; +// +//public interface LithiumData { +// +// record Data( +// // Map of chunk position -> y section -> game event dispatcher +// // This should be faster than the chunk lookup, since there are usually a lot more chunks than +// // chunk with game event dispatchers (we only initialize them when non-empty set of listeners) +// // All Int2ObjectMap objects are also stored in a field of the corresponding WorldChunk. +// Long2ReferenceOpenHashMap> gameEventDispatchersByChunk, +// +// // Cached ominous banner, must not be mutated. +// ItemStack ominousBanner, +// +// // Set of active mob navigations (active = have a path) +// ReferenceOpenHashSet activeNavigations, +// +// // Block change tracker deduplication +// LithiumInterner blockChangeTrackers, +// +// // Entity movement tracker deduplication +// LithiumInterner> entityMovementTrackers, +// +// // Block ChunkSection listeners +// Long2ReferenceOpenHashMap chunkSectionChangeCallbacks +// ) { +// public Data(Level world) { +// this( +// new Long2ReferenceOpenHashMap<>(), +// world.registryAccess().lookup(Registries.BANNER_PATTERN).map(Raid::getLeaderBannerInstance).orElse(null), +// new ReferenceOpenHashSet<>(), +// new LithiumInterner<>(), +// new LithiumInterner<>(), +// new Long2ReferenceOpenHashMap<>() +// ); +// } +// } +// +// LithiumData.Data lithium$getData(); +//} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/common/world/chunk/LithiumHashPalette.java b/src/main/java/net/gensokyoreimagined/nitori/common/world/chunk/LithiumHashPalette.java index c8c89ad..d73bfd1 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/common/world/chunk/LithiumHashPalette.java +++ b/src/main/java/net/gensokyoreimagined/nitori/common/world/chunk/LithiumHashPalette.java @@ -1,199 +1,199 @@ package net.gensokyoreimagined.nitori.common.world.chunk; -import com.google.common.collect.ImmutableList; -import it.unimi.dsi.fastutil.HashCommon; -import it.unimi.dsi.fastutil.objects.Reference2IntMap; -import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; -import net.gensokyoreimagined.nitori.mixin.needs_testing.chunk.palette.PaletteResizeAccessor; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.VarInt; -import net.minecraft.core.IdMap; -import net.minecraft.world.level.chunk.MissingPaletteEntryException; -import net.minecraft.world.level.chunk.Palette; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.List; -import java.util.function.Predicate; - -import static it.unimi.dsi.fastutil.Hash.FAST_LOAD_FACTOR; - -/** -* Generally provides better performance over the vanilla {@link net.minecraft.world.level.chunk.HashMapPalette} when calling -* {@link LithiumHashPalette#idFor(Object)} through using a faster backing map and reducing pointer chasing. -*/ -public class LithiumHashPalette implements Palette { - private static final int ABSENT_VALUE = -1; - - private final IdMap idList; - // private final PaletteResize resizeHandler; - private final PaletteResizeAccessor resizeHandler; - private final int indexBits; - - private final Reference2IntMap table; - private T[] entries; - private int size = 0; - - public LithiumHashPalette(IdMap idList, PaletteResizeAccessor resizeHandler, int indexBits, T[] entries, Reference2IntMap table, int size) { - this.idList = idList; - this.resizeHandler = resizeHandler; - this.indexBits = indexBits; - this.entries = entries; - this.table = table; - this.size = size; - } - - public LithiumHashPalette(IdMap idList, int bits, PaletteResizeAccessor resizeHandler, List list) { - this(idList, bits, resizeHandler); - - for (T t : list) { - this.addEntry(t); - } - } - - @SuppressWarnings("unchecked") - public LithiumHashPalette(IdMap idList, int bits, PaletteResizeAccessor resizeHandler) { - this.idList = idList; - this.indexBits = bits; - this.resizeHandler = resizeHandler; - - int capacity = 1 << bits; - - this.entries = (T[]) new Object[capacity]; - this.table = new Reference2IntOpenHashMap<>(capacity, FAST_LOAD_FACTOR); - this.table.defaultReturnValue(ABSENT_VALUE); - } - - @Override - public int idFor(T obj) { - int id = this.table.getInt(obj); - - if (id == ABSENT_VALUE) { - id = this.computeEntry(obj); - } - - return id; - } - - @Override - public boolean maybeHas(Predicate predicate) { - for (int i = 0; i < this.size; ++i) { - if (predicate.test(this.entries[i])) { - return true; - } - } - - return false; - } - - private int computeEntry(T obj) { - int id = this.addEntry(obj); - - if (id >= 1 << this.indexBits) { - if (this.resizeHandler == null) { - throw new IllegalStateException("Cannot grow"); - } else { - id = this.resizeHandler.callOnResize(this.indexBits + 1, obj); - } - } - - return id; - } - - private int addEntry(T obj) { - int nextId = this.size; - - if (nextId >= this.entries.length) { - this.resize(this.size); - } - - this.table.put(obj, nextId); - this.entries[nextId] = obj; - - this.size++; - - return nextId; - } - - private void resize(int neededCapacity) { - this.entries = Arrays.copyOf(this.entries, HashCommon.nextPowerOfTwo(neededCapacity + 1)); - } - - @Override - public @NotNull T valueFor(int id) { - T[] entries = this.entries; - - T entry = null; - if (id >= 0 && id < entries.length) { - entry = entries[id]; - } - - if (entry != null) { - return entry; - } else { - throw new MissingPaletteEntryException(id); - } - } - - @Override - public void read(FriendlyByteBuf buf) { - this.clear(); - - int entryCount = buf.readVarInt(); - - for (int i = 0; i < entryCount; ++i) { - this.addEntry(this.idList.byId(buf.readVarInt())); - } - } - - @Override - public void write(FriendlyByteBuf buf) { - int size = this.size; - buf.writeVarInt(size); - - for (int i = 0; i < size; ++i) { - buf.writeVarInt(this.idList.getId(this.valueFor(i))); - } - } - - @Override - public int getSerializedSize() { - int size = VarInt.getByteSize(this.size); - - for (int i = 0; i < this.size; ++i) { - size += VarInt.getByteSize(this.idList.getId(this.valueFor(i))); - } - - return size; - } - - @Override - public int getSize() { - return this.size; - } - - @Override - public Palette copy() { - return new LithiumHashPalette<>(this.idList, this.resizeHandler, this.indexBits, this.entries.clone(), new Reference2IntOpenHashMap<>(this.table), this.size); - } - - private void clear() { - Arrays.fill(this.entries, null); - this.table.clear(); - this.size = 0; - } - - public List getElements() { - ImmutableList.Builder builder = new ImmutableList.Builder<>(); - for (T entry : this.entries) { - if (entry != null) { - builder.add(entry); - } - } - return builder.build(); - } - - public static Palette create(int bits, IdMap idList, PaletteResizeAccessor listener, List list) { - return new LithiumHashPalette<>(idList, bits, listener, list); - } -} \ No newline at end of file +//import com.google.common.collect.ImmutableList; +//import it.unimi.dsi.fastutil.HashCommon; +//import it.unimi.dsi.fastutil.objects.Reference2IntMap; +//import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; +//import net.gensokyoreimagined.nitori.mixin.needs_testing.chunk.palette.PaletteResizeAccessor; +//import net.minecraft.network.FriendlyByteBuf; +//import net.minecraft.network.VarInt; +//import net.minecraft.core.IdMap; +//import net.minecraft.world.level.chunk.MissingPaletteEntryException; +//import net.minecraft.world.level.chunk.Palette; +//import org.jetbrains.annotations.NotNull; +// +//import java.util.Arrays; +//import java.util.List; +//import java.util.function.Predicate; +// +//import static it.unimi.dsi.fastutil.Hash.FAST_LOAD_FACTOR; +// +///** +//* Generally provides better performance over the vanilla {@link net.minecraft.world.level.chunk.HashMapPalette} when calling +//* {@link LithiumHashPalette#idFor(Object)} through using a faster backing map and reducing pointer chasing. +//*/ +//public class LithiumHashPalette implements Palette { +// private static final int ABSENT_VALUE = -1; +// +// private final IdMap idList; +// // private final PaletteResize resizeHandler; +// private final PaletteResizeAccessor resizeHandler; +// private final int indexBits; +// +// private final Reference2IntMap table; +// private T[] entries; +// private int size = 0; +// +// public LithiumHashPalette(IdMap idList, PaletteResizeAccessor resizeHandler, int indexBits, T[] entries, Reference2IntMap table, int size) { +// this.idList = idList; +// this.resizeHandler = resizeHandler; +// this.indexBits = indexBits; +// this.entries = entries; +// this.table = table; +// this.size = size; +// } +// +// public LithiumHashPalette(IdMap idList, int bits, PaletteResizeAccessor resizeHandler, List list) { +// this(idList, bits, resizeHandler); +// +// for (T t : list) { +// this.addEntry(t); +// } +// } +// +// @SuppressWarnings("unchecked") +// public LithiumHashPalette(IdMap idList, int bits, PaletteResizeAccessor resizeHandler) { +// this.idList = idList; +// this.indexBits = bits; +// this.resizeHandler = resizeHandler; +// +// int capacity = 1 << bits; +// +// this.entries = (T[]) new Object[capacity]; +// this.table = new Reference2IntOpenHashMap<>(capacity, FAST_LOAD_FACTOR); +// this.table.defaultReturnValue(ABSENT_VALUE); +// } +// +// @Override +// public int idFor(T obj) { +// int id = this.table.getInt(obj); +// +// if (id == ABSENT_VALUE) { +// id = this.computeEntry(obj); +// } +// +// return id; +// } +// +// @Override +// public boolean maybeHas(Predicate predicate) { +// for (int i = 0; i < this.size; ++i) { +// if (predicate.test(this.entries[i])) { +// return true; +// } +// } +// +// return false; +// } +// +// private int computeEntry(T obj) { +// int id = this.addEntry(obj); +// +// if (id >= 1 << this.indexBits) { +// if (this.resizeHandler == null) { +// throw new IllegalStateException("Cannot grow"); +// } else { +// id = this.resizeHandler.callOnResize(this.indexBits + 1, obj); +// } +// } +// +// return id; +// } +// +// private int addEntry(T obj) { +// int nextId = this.size; +// +// if (nextId >= this.entries.length) { +// this.resize(this.size); +// } +// +// this.table.put(obj, nextId); +// this.entries[nextId] = obj; +// +// this.size++; +// +// return nextId; +// } +// +// private void resize(int neededCapacity) { +// this.entries = Arrays.copyOf(this.entries, HashCommon.nextPowerOfTwo(neededCapacity + 1)); +// } +// +// @Override +// public @NotNull T valueFor(int id) { +// T[] entries = this.entries; +// +// T entry = null; +// if (id >= 0 && id < entries.length) { +// entry = entries[id]; +// } +// +// if (entry != null) { +// return entry; +// } else { +// throw new MissingPaletteEntryException(id); +// } +// } +// +// @Override +// public void read(FriendlyByteBuf buf) { +// this.clear(); +// +// int entryCount = buf.readVarInt(); +// +// for (int i = 0; i < entryCount; ++i) { +// this.addEntry(this.idList.byId(buf.readVarInt())); +// } +// } +// +// @Override +// public void write(FriendlyByteBuf buf) { +// int size = this.size; +// buf.writeVarInt(size); +// +// for (int i = 0; i < size; ++i) { +// buf.writeVarInt(this.idList.getId(this.valueFor(i))); +// } +// } +// +// @Override +// public int getSerializedSize() { +// int size = VarInt.getByteSize(this.size); +// +// for (int i = 0; i < this.size; ++i) { +// size += VarInt.getByteSize(this.idList.getId(this.valueFor(i))); +// } +// +// return size; +// } +// +// @Override +// public int getSize() { +// return this.size; +// } +// +// @Override +// public Palette copy() { +// return new LithiumHashPalette<>(this.idList, this.resizeHandler, this.indexBits, this.entries.clone(), new Reference2IntOpenHashMap<>(this.table), this.size); +// } +// +// private void clear() { +// Arrays.fill(this.entries, null); +// this.table.clear(); +// this.size = 0; +// } +// +// public List getElements() { +// ImmutableList.Builder builder = new ImmutableList.Builder<>(); +// for (T entry : this.entries) { +// if (entry != null) { +// builder.add(entry); +// } +// } +// return builder.build(); +// } +// +// public static Palette create(int bits, IdMap idList, PaletteResizeAccessor listener, List list) { +// return new LithiumHashPalette<>(idList, bits, listener, list); +// } +//} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/ChunkMapMixin.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/ChunkMapMixin.java index 993701e..3ff77fa 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/ChunkMapMixin.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/ChunkMapMixin.java @@ -14,158 +14,158 @@ // along with this program. If not, see . package net.gensokyoreimagined.nitori.mixin; -import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel; -import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; -import it.unimi.dsi.fastutil.objects.ReferenceSets; -//import net.gensokyoreimagined.nitori.config.NitoriConfig; -import net.gensokyoreimagined.nitori.access.IMixinChunkMapAccess; -import net.gensokyoreimagined.nitori.access.IMixinChunkMap_TrackedEntityAccess; -import net.gensokyoreimagined.nitori.compatibility.PluginCompatibilityRegistry; -import net.gensokyoreimagined.nitori.tracker.MultithreadedTracker; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ServerEntity; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerPlayerConnection; -import net.minecraft.world.entity.Entity; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.List; -import java.util.Set; -import java.util.concurrent.ConcurrentLinkedQueue; -import javax.annotation.Nullable; - -@Mixin(ChunkMap.class) -public class ChunkMapMixin implements IMixinChunkMapAccess { - - @Mutable - @Shadow @Final public Int2ObjectMap entityMap; - - // Implementation of 0107-Multithreaded-Tracker.patch - @Final - @Shadow - public ServerLevel level; - - // Implementation of 0107-Multithreaded-Tracker.patch - @Unique - private @Nullable MultithreadedTracker gensouHacks$multithreadedTracker; - - // Implementation of 0107-Multithreaded-Tracker.patch - @Final - @Unique - private final ConcurrentLinkedQueue gensouHacks$trackerMainThreadTasks = new ConcurrentLinkedQueue<>(); - - // Implementation of 0107-Multithreaded-Tracker.patch - @Unique - private boolean gensouHacks$tracking = false; - - @Inject(method = "", at = @At("RETURN")) - private void reassignEntityTrackers(CallbackInfo ci) { - this.entityMap = new Int2ObjectLinkedOpenHashMap<>(); - } - - // Implementation of 0107-Multithreaded-Tracker.patch - @Override - @Unique - public void gensouHacks$runOnTrackerMainThread(final Runnable runnable) { - if (this.gensouHacks$tracking) { - this.gensouHacks$trackerMainThreadTasks.add(runnable); - } else { - runnable.run(); - } - } - - @Inject(method = "newTrackerTick", at = @At("HEAD"), cancellable = true) - private void atProcessTrackQueueHead(CallbackInfo callbackInfo) { - // Implementation of 0107-Multithreaded-Tracker.patch - //TODO: Restore config condition - //if (NitoriConfig.enableAsyncEntityTracker) { - if (this.gensouHacks$multithreadedTracker == null) { - this.gensouHacks$multithreadedTracker = new MultithreadedTracker(((ChunkSystemServerLevel) this.level).moonrise$getEntityTickingChunks(), this.gensouHacks$trackerMainThreadTasks); - } - - this.gensouHacks$tracking = true; - try { - this.gensouHacks$multithreadedTracker.tick(); - } finally { - this.gensouHacks$tracking = false; - } - callbackInfo.cancel(); - //} - // Mirai end - } - - @Mixin(ChunkMap.TrackedEntity.class) - public static abstract class TrackedEntity implements IMixinChunkMap_TrackedEntityAccess { - // Implementation of 0107-Multithreaded-Tracker.patch - @Override - @Final - @Accessor - public abstract Entity getEntity(); // Mirai -> public - - @Final - @Mutable - @Shadow - public Set seenBy; - - @Shadow - public abstract void updatePlayer(ServerPlayer player); - - @Inject(method = "", at = @At("RETURN")) - private void reassignSeenBy(CallbackInfo ci) { - // Implementation of 0107-Multithreaded-Tracker.patch - this.seenBy = ReferenceSets.synchronize(new ReferenceOpenHashSet<>()); // Mirai - sync - } - - // Implementation of 0107-Multithreaded-Tracker.patch - @Override - @Final - @Invoker - public abstract void callUpdatePlayers(List players); // Mirai -> public - - @Redirect(method = "updatePlayers", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkMap$TrackedEntity;updatePlayer(Lnet/minecraft/server/level/ServerPlayer;)V")) - private void handleCitizensPluginTracking(ChunkMap.TrackedEntity self, ServerPlayer serverPlayer) { - // Nitori - Citizens tracker must run on the main thread to avoid cyclic wait - if (PluginCompatibilityRegistry.CITIZENS.shouldRedirectToMainThread(self, serverPlayer)) { - ((IMixinChunkMapAccess) (Object) ((ServerLevel) serverPlayer.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> - this.updatePlayer(serverPlayer) - ); - } else { - this.updatePlayer(serverPlayer); - } - } - - // Implementation of 0107-Multithreaded-Tracker.patch - @SuppressWarnings("EmptyMethod") - @Redirect(method = "removePlayer", at = @At(value = "INVOKE", target = "Lorg/spigotmc/AsyncCatcher;catchOp(Ljava/lang/String;)V")) - private void skipSpigotAsyncPlayerTrackerClear(String reason) {} // Mirai - we can remove async too - - // Implementation of 0107-Multithreaded-Tracker.patch - @SuppressWarnings("EmptyMethod") - @Redirect(method = "updatePlayer", at = @At(value = "INVOKE", target = "Lorg/spigotmc/AsyncCatcher;catchOp(Ljava/lang/String;)V")) - private void skipSpigotAsyncPlayerTrackerUpdate(String reason) {} // Mirai - we can update async - - @Redirect(method = "updatePlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerEntity;addPairing(Lnet/minecraft/server/level/ServerPlayer;)V")) - private void handleTrainCartsPluginAddPairing(ServerEntity self, ServerPlayer serverPlayer) { - if (PluginCompatibilityRegistry.TRAIN_CARTS.shouldRedirectToMainThread((ChunkMap.TrackedEntity) (Object) this)) { - ((IMixinChunkMapAccess) (Object) ((ServerLevel) serverPlayer.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> - self.addPairing(serverPlayer) - ); - } else { - self.addPairing(serverPlayer); - } - } - } -} +//import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel; +//import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; +//import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +//import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; +//import it.unimi.dsi.fastutil.objects.ReferenceSets; +////import net.gensokyoreimagined.nitori.config.NitoriConfig; +//import net.gensokyoreimagined.nitori.access.IMixinChunkMapAccess; +//import net.gensokyoreimagined.nitori.access.IMixinChunkMap_TrackedEntityAccess; +//import net.gensokyoreimagined.nitori.compatibility.PluginCompatibilityRegistry; +//import net.gensokyoreimagined.nitori.tracker.MultithreadedTracker; +//import net.minecraft.server.level.ChunkMap; +//import net.minecraft.server.level.ServerEntity; +//import net.minecraft.server.level.ServerLevel; +//import net.minecraft.server.level.ServerPlayer; +//import net.minecraft.server.network.ServerPlayerConnection; +//import net.minecraft.world.entity.Entity; +//import org.spongepowered.asm.mixin.Final; +//import org.spongepowered.asm.mixin.Mixin; +//import org.spongepowered.asm.mixin.Mutable; +//import org.spongepowered.asm.mixin.Shadow; +//import org.spongepowered.asm.mixin.Unique; +//import org.spongepowered.asm.mixin.gen.Accessor; +//import org.spongepowered.asm.mixin.gen.Invoker; +//import org.spongepowered.asm.mixin.injection.At; +//import org.spongepowered.asm.mixin.injection.Inject; +//import org.spongepowered.asm.mixin.injection.Redirect; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +// +//import java.util.List; +//import java.util.Set; +//import java.util.concurrent.ConcurrentLinkedQueue; +//import javax.annotation.Nullable; +// +//@Mixin(ChunkMap.class) +//public class ChunkMapMixin implements IMixinChunkMapAccess { +// +// @Mutable +// @Shadow @Final public Int2ObjectMap entityMap; +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @Final +// @Shadow +// public ServerLevel level; +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @Unique +// private @Nullable MultithreadedTracker gensouHacks$multithreadedTracker; +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @Final +// @Unique +// private final ConcurrentLinkedQueue gensouHacks$trackerMainThreadTasks = new ConcurrentLinkedQueue<>(); +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @Unique +// private boolean gensouHacks$tracking = false; +// +// @Inject(method = "", at = @At("RETURN")) +// private void reassignEntityTrackers(CallbackInfo ci) { +// this.entityMap = new Int2ObjectLinkedOpenHashMap<>(); +// } +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @Override +// @Unique +// public void gensouHacks$runOnTrackerMainThread(final Runnable runnable) { +// if (this.gensouHacks$tracking) { +// this.gensouHacks$trackerMainThreadTasks.add(runnable); +// } else { +// runnable.run(); +// } +// } +// +// @Inject(method = "newTrackerTick", at = @At("HEAD"), cancellable = true) +// private void atProcessTrackQueueHead(CallbackInfo callbackInfo) { +// // Implementation of 0107-Multithreaded-Tracker.patch +// //TODO: Restore config condition +// //if (NitoriConfig.enableAsyncEntityTracker) { +// if (this.gensouHacks$multithreadedTracker == null) { +// this.gensouHacks$multithreadedTracker = new MultithreadedTracker(((ChunkSystemServerLevel) this.level).moonrise$getEntityTickingChunks(), this.gensouHacks$trackerMainThreadTasks); +// } +// +// this.gensouHacks$tracking = true; +// try { +// this.gensouHacks$multithreadedTracker.tick(); +// } finally { +// this.gensouHacks$tracking = false; +// } +// callbackInfo.cancel(); +// //} +// // Mirai end +// } +// +// @Mixin(ChunkMap.TrackedEntity.class) +// public static abstract class TrackedEntity implements IMixinChunkMap_TrackedEntityAccess { +// // Implementation of 0107-Multithreaded-Tracker.patch +// @Override +// @Final +// @Accessor +// public abstract Entity getEntity(); // Mirai -> public +// +// @Final +// @Mutable +// @Shadow +// public Set seenBy; +// +// @Shadow +// public abstract void updatePlayer(ServerPlayer player); +// +// @Inject(method = "", at = @At("RETURN")) +// private void reassignSeenBy(CallbackInfo ci) { +// // Implementation of 0107-Multithreaded-Tracker.patch +// this.seenBy = ReferenceSets.synchronize(new ReferenceOpenHashSet<>()); // Mirai - sync +// } +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @Override +// @Final +// @Invoker +// public abstract void callUpdatePlayers(List players); // Mirai -> public +// +// @Redirect(method = "updatePlayers", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkMap$TrackedEntity;updatePlayer(Lnet/minecraft/server/level/ServerPlayer;)V")) +// private void handleCitizensPluginTracking(ChunkMap.TrackedEntity self, ServerPlayer serverPlayer) { +// // Nitori - Citizens tracker must run on the main thread to avoid cyclic wait +// if (PluginCompatibilityRegistry.CITIZENS.shouldRedirectToMainThread(self, serverPlayer)) { +// ((IMixinChunkMapAccess) (Object) ((ServerLevel) serverPlayer.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> +// this.updatePlayer(serverPlayer) +// ); +// } else { +// this.updatePlayer(serverPlayer); +// } +// } +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @SuppressWarnings("EmptyMethod") +// @Redirect(method = "removePlayer", at = @At(value = "INVOKE", target = "Lorg/spigotmc/AsyncCatcher;catchOp(Ljava/lang/String;)V")) +// private void skipSpigotAsyncPlayerTrackerClear(String reason) {} // Mirai - we can remove async too +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @SuppressWarnings("EmptyMethod") +// @Redirect(method = "updatePlayer", at = @At(value = "INVOKE", target = "Lorg/spigotmc/AsyncCatcher;catchOp(Ljava/lang/String;)V")) +// private void skipSpigotAsyncPlayerTrackerUpdate(String reason) {} // Mirai - we can update async +// +// @Redirect(method = "updatePlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerEntity;addPairing(Lnet/minecraft/server/level/ServerPlayer;)V")) +// private void handleTrainCartsPluginAddPairing(ServerEntity self, ServerPlayer serverPlayer) { +// if (PluginCompatibilityRegistry.TRAIN_CARTS.shouldRedirectToMainThread((ChunkMap.TrackedEntity) (Object) this)) { +// ((IMixinChunkMapAccess) (Object) ((ServerLevel) serverPlayer.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> +// self.addPairing(serverPlayer) +// ); +// } else { +// self.addPairing(serverPlayer); +// } +// } +// } +//} diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinServerEntity.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinServerEntity.java index 4858b6e..4ede944 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinServerEntity.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinServerEntity.java @@ -14,116 +14,116 @@ // along with this program. If not, see . package net.gensokyoreimagined.nitori.mixin; -import com.google.common.collect.Lists; -import com.llamalad7.mixinextras.sugar.Local; -import net.gensokyoreimagined.nitori.access.IMixinChunkMapAccess; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ClientGamePacketListener; -import net.minecraft.network.protocol.game.ClientboundBundlePacket; -import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket; -import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; -import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket; -import net.minecraft.network.syncher.SynchedEntityData; -import net.minecraft.server.level.ServerEntity; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.ai.attributes.AttributeInstance; -import org.objectweb.asm.Opcodes; -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.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import java.util.List; -import java.util.Set; -import java.util.function.Consumer; - -@Mixin(ServerEntity.class) -public abstract class MixinServerEntity { - @Final - @Shadow - private Entity entity; - - @Shadow - public void sendPairingData(ServerPlayer serverplayer, Consumer> consumer) { - throw new AssertionError("Mixin failed to apply!"); - } - - // Implementation of 0107-Multithreaded-Tracker.patch - @SuppressWarnings("EmptyMethod") - @Redirect(method = "removePairing", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V")) - private void skipSendForOriginalRemovePairing(ServerGamePacketListenerImpl self, Packet packet) {} - - // Implementation of 0107-Multithreaded-Tracker.patch - @Inject(method = "removePairing", at = @At(value = "TAIL")) - private void invokeRemovePairingSendOnMain(ServerPlayer serverplayer, CallbackInfo callbackInfo) { - // Mirai start - ensure main thread - ((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> - serverplayer.connection.send(new ClientboundRemoveEntitiesPacket(this.entity.getId())) - ); - // Mirai end - } - - // Implementation of 0107-Multithreaded-Tracker.patch - @SuppressWarnings("EmptyMethod") - @Redirect(method = "addPairing", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerEntity;sendPairingData(Lnet/minecraft/server/level/ServerPlayer;Ljava/util/function/Consumer;)V")) - private void skipSendPrepForOriginalAddPairing(ServerEntity self, ServerPlayer serverplayer, Consumer> consumer) {} - - // Implementation of 0107-Multithreaded-Tracker.patch - @SuppressWarnings("EmptyMethod") - @Redirect(method = "addPairing", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V")) - private void skipSendForOriginalAddPairing(ServerGamePacketListenerImpl self, Packet packet) {} - - // Implementation of 0107-Multithreaded-Tracker.patch - @Inject(method = "addPairing", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", target = "Lnet/minecraft/server/level/ServerEntity;entity:Lnet/minecraft/world/entity/Entity;", opcode = Opcodes.GETFIELD, shift = At.Shift.BEFORE)) - private void invokeAddPairingSendOnMain(ServerPlayer serverplayer, CallbackInfo callbackInfo, @Local List> list) { - ((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> { // Mirai - main thread - this.sendPairingData(serverplayer, list::add); - serverplayer.connection.send(new ClientboundBundlePacket(list)); - }); - } - - // Implementation of 0107-Multithreaded-Tracker.patch - @SuppressWarnings("EmptyMethod") - @Redirect(method = "sendDirtyEntityData", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerEntity;broadcastAndSend(Lnet/minecraft/network/protocol/Packet;)V")) - private void skipTrasmitForNonDefault(ServerEntity self, Packet packet) {} - - // Implementation of 0107-Multithreaded-Tracker.patch - @Inject(method = "sendDirtyEntityData", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", target = "Lnet/minecraft/server/level/ServerEntity;entity:Lnet/minecraft/world/entity/Entity;", opcode = Opcodes.GETFIELD, ordinal = 2, shift = At.Shift.BY, by = -4)) - private void invokeSendForGenericDirtyEntityDataOnMain(CallbackInfo callbackInfo, @Local SynchedEntityData synchedentitydata, @Local List> list) { - // Mirai start - sync - ((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> - this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), list)) - ); - // Mirai end - } - - // stubbing of broadcastAndSend in if (this.entity instanceof LivingEntity) handled in skipTrasmitForNonDefault - - // Implementation of 0107-Multithreaded-Tracker.patch - @Inject(method = "sendDirtyEntityData", at = @At(value = "INVOKE", target = "Ljava/util/Set;clear()V", shift = At.Shift.BY, by = -4)) - private void invokeSendForLivingDirtyEntityDataOnMain(CallbackInfo callbackInfo, @Local Set set) { - // Mirai start - sync - final var copy = Lists.newArrayList(set); - ((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> { - // CraftBukkit start - Send scaled max health - if (this.entity instanceof ServerPlayer) { - ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(copy, false); - } - // CraftBukkit end - this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), copy)); - }); - // Mirai end - } - - @Shadow - private void broadcastAndSend(Packet packet) { - throw new AssertionError("Mixin failed to apply!"); - } -} +//import com.google.common.collect.Lists; +//import com.llamalad7.mixinextras.sugar.Local; +//import net.gensokyoreimagined.nitori.access.IMixinChunkMapAccess; +//import net.minecraft.network.protocol.Packet; +//import net.minecraft.network.protocol.game.ClientGamePacketListener; +//import net.minecraft.network.protocol.game.ClientboundBundlePacket; +//import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket; +//import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; +//import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket; +//import net.minecraft.network.syncher.SynchedEntityData; +//import net.minecraft.server.level.ServerEntity; +//import net.minecraft.server.level.ServerLevel; +//import net.minecraft.server.level.ServerPlayer; +//import net.minecraft.server.network.ServerGamePacketListenerImpl; +//import net.minecraft.world.entity.Entity; +//import net.minecraft.world.entity.ai.attributes.AttributeInstance; +//import org.objectweb.asm.Opcodes; +//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.Redirect; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +//import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +// +//import java.util.List; +//import java.util.Set; +//import java.util.function.Consumer; +// +//@Mixin(ServerEntity.class) +//public abstract class MixinServerEntity { +// @Final +// @Shadow +// private Entity entity; +// +// @Shadow +// public void sendPairingData(ServerPlayer serverplayer, Consumer> consumer) { +// throw new AssertionError("Mixin failed to apply!"); +// } +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @SuppressWarnings("EmptyMethod") +// @Redirect(method = "removePairing", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V")) +// private void skipSendForOriginalRemovePairing(ServerGamePacketListenerImpl self, Packet packet) {} +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @Inject(method = "removePairing", at = @At(value = "TAIL")) +// private void invokeRemovePairingSendOnMain(ServerPlayer serverplayer, CallbackInfo callbackInfo) { +// // Mirai start - ensure main thread +// ((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> +// serverplayer.connection.send(new ClientboundRemoveEntitiesPacket(this.entity.getId())) +// ); +// // Mirai end +// } +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @SuppressWarnings("EmptyMethod") +// @Redirect(method = "addPairing", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerEntity;sendPairingData(Lnet/minecraft/server/level/ServerPlayer;Ljava/util/function/Consumer;)V")) +// private void skipSendPrepForOriginalAddPairing(ServerEntity self, ServerPlayer serverplayer, Consumer> consumer) {} +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @SuppressWarnings("EmptyMethod") +// @Redirect(method = "addPairing", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V")) +// private void skipSendForOriginalAddPairing(ServerGamePacketListenerImpl self, Packet packet) {} +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @Inject(method = "addPairing", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", target = "Lnet/minecraft/server/level/ServerEntity;entity:Lnet/minecraft/world/entity/Entity;", opcode = Opcodes.GETFIELD, shift = At.Shift.BEFORE)) +// private void invokeAddPairingSendOnMain(ServerPlayer serverplayer, CallbackInfo callbackInfo, @Local List> list) { +// ((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> { // Mirai - main thread +// this.sendPairingData(serverplayer, list::add); +// serverplayer.connection.send(new ClientboundBundlePacket(list)); +// }); +// } +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @SuppressWarnings("EmptyMethod") +// @Redirect(method = "sendDirtyEntityData", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerEntity;broadcastAndSend(Lnet/minecraft/network/protocol/Packet;)V")) +// private void skipTrasmitForNonDefault(ServerEntity self, Packet packet) {} +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @Inject(method = "sendDirtyEntityData", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", target = "Lnet/minecraft/server/level/ServerEntity;entity:Lnet/minecraft/world/entity/Entity;", opcode = Opcodes.GETFIELD, ordinal = 2, shift = At.Shift.BY, by = -4)) +// private void invokeSendForGenericDirtyEntityDataOnMain(CallbackInfo callbackInfo, @Local SynchedEntityData synchedentitydata, @Local List> list) { +// // Mirai start - sync +// ((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> +// this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), list)) +// ); +// // Mirai end +// } +// +// // stubbing of broadcastAndSend in if (this.entity instanceof LivingEntity) handled in skipTrasmitForNonDefault +// +// // Implementation of 0107-Multithreaded-Tracker.patch +// @Inject(method = "sendDirtyEntityData", at = @At(value = "INVOKE", target = "Ljava/util/Set;clear()V", shift = At.Shift.BY, by = -4)) +// private void invokeSendForLivingDirtyEntityDataOnMain(CallbackInfo callbackInfo, @Local Set set) { +// // Mirai start - sync +// final var copy = Lists.newArrayList(set); +// ((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> { +// // CraftBukkit start - Send scaled max health +// if (this.entity instanceof ServerPlayer) { +// ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(copy, false); +// } +// // CraftBukkit end +// this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), copy)); +// }); +// // Mirai end +// } +// +// @Shadow +// private void broadcastAndSend(Packet packet) { +// throw new AssertionError("Mixin failed to apply!"); +// } +//} diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinServerWorld.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinServerWorld.java index 8c519d0..dfb2b03 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinServerWorld.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinServerWorld.java @@ -27,38 +27,38 @@ // Taken from Lithium // https://github.com/CaffeineMC/lithium-fabric/blob/427dd75ffc922cc1858c1db4b283cc54744567e0/src/main/java/me/jellysquid/mods/lithium/mixin/alloc/chunk_random/ServerWorldMixin.java#L24 -@Mixin(ServerLevel.class) -public abstract class MixinServerWorld { - @Unique - private final BlockPos.MutableBlockPos nitori$randomPosInChunkCachedPos = new BlockPos.MutableBlockPos(); - - /** - * @reason Avoid allocating BlockPos every invocation through using our allocation-free variant - */ - @Redirect( - method = "tickChunk", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerLevel;getBlockRandomPos(IIII)Lnet/minecraft/core/BlockPos;" - ) - ) - private BlockPos redirectTickGetRandomPosInChunk(ServerLevel serverWorld, int x, int y, int z, int mask) { - ((ChunkRandomSource) serverWorld).nitori$getRandomPosInChunk(x, y, z, mask, this.nitori$randomPosInChunkCachedPos); - - return this.nitori$randomPosInChunkCachedPos; - } - - /** - * @reason Ensure an immutable block position is passed on block tick - */ - @Redirect( - method = "tickChunk", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/block/state/BlockState;randomTick(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/util/RandomSource;)V" - ) - ) - private void redirectBlockStateTick(BlockState blockState, ServerLevel world, BlockPos pos, RandomSource rand) { - blockState.randomTick(world, pos.immutable(), rand); - } -} \ No newline at end of file +//@Mixin(ServerLevel.class) +//public abstract class MixinServerWorld { +// @Unique +// private final BlockPos.MutableBlockPos nitori$randomPosInChunkCachedPos = new BlockPos.MutableBlockPos(); +// +// /** +// * @reason Avoid allocating BlockPos every invocation through using our allocation-free variant +// */ +// @Redirect( +// method = "tickChunk", +// at = @At( +// value = "INVOKE", +// target = "Lnet/minecraft/server/level/ServerLevel;getBlockRandomPos(IIII)Lnet/minecraft/core/BlockPos;" +// ) +// ) +// private BlockPos redirectTickGetRandomPosInChunk(ServerLevel serverWorld, int x, int y, int z, int mask) { +// ((ChunkRandomSource) serverWorld).nitori$getRandomPosInChunk(x, y, z, mask, this.nitori$randomPosInChunkCachedPos); +// +// return this.nitori$randomPosInChunkCachedPos; +// } +// +// /** +// * @reason Ensure an immutable block position is passed on block tick +// */ +// @Redirect( +// method = "tickChunk", +// at = @At( +// value = "INVOKE", +// target = "Lnet/minecraft/server/level/ServerLevel;optimiseRandomTick(Lnet/minecraft/world/level/chunk/LevelChunk;I)V" +// ) +// ) +// private void redirectBlockStateTick(BlockState blockState, ServerLevel world, BlockPos pos, RandomSource rand) { +// blockState.randomTick(world, pos.immutable(), rand); +// } +//} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinSpongeSIMD.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinSpongeSIMD.java index 2bca161..011a1b2 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinSpongeSIMD.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinSpongeSIMD.java @@ -14,20 +14,20 @@ // along with this program. If not, see . package net.gensokyoreimagined.nitori.mixin; -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.CallbackInfoReturnable; - -@Mixin(targets = "gg.pufferfish.pufferfish.simd.SIMDDetection") -public abstract class MixinSpongeSIMD { - @Inject(method = "getJavaVersion", at = @At("RETURN"), cancellable = true) - private static void loadPufferfishConfig(CallbackInfoReturnable callback) { - // We troll the Pufferfish developers by changing the return value of the method - // System.out.println("Thought that it was " + callback.getReturnValue() + " for java version"); - if (callback.getReturnValue() == 21) { - System.out.println("Successfully trolled Pufferfish into thinking we're on Java 19!"); - callback.setReturnValue(19); - } - } -} +//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.CallbackInfoReturnable; +// +//@Mixin(targets = "gg.pufferfish.pufferfish.simd.SIMDDetection") +//public abstract class MixinSpongeSIMD { +// @Inject(method = "getJavaVersion", at = @At("RETURN"), cancellable = true) +// private static void loadPufferfishConfig(CallbackInfoReturnable callback) { +// // We troll the Pufferfish developers by changing the return value of the method +// // System.out.println("Thought that it was " + callback.getReturnValue() + " for java version"); +// if (callback.getReturnValue() == 21) { +// System.out.println("Successfully trolled Pufferfish into thinking we're on Java 19!"); +// callback.setReturnValue(19); +// } +// } +//} diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinWorldGenRegion.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinWorldGenRegion.java index b6d4717..229e8fb 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinWorldGenRegion.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/MixinWorldGenRegion.java @@ -33,50 +33,50 @@ import java.util.List; -@Mixin(WorldGenRegion.class) -public class MixinWorldGenRegion { - @Shadow @Final private ChunkPos firstPos; - @Shadow @Final private int size; - - @Unique - private ChunkAccess[] gensouHacks$chunksArr; - @Unique - private int gensouHacks$minChunkX; - @Unique - private int gensouHacks$minChunkZ; - - @Inject(method = "", at = @At("RETURN")) - private void onInit(ServerLevel world, List chunks, ChunkStatus status, int placementRadius, CallbackInfo ci) { - this.gensouHacks$minChunkX = this.firstPos.x; - this.gensouHacks$minChunkZ = this.firstPos.z; - this.gensouHacks$chunksArr = chunks.toArray(new ChunkAccess[0]); - } - - @Inject(method = "getChunk(II)Lnet/minecraft/world/level/chunk/ChunkAccess;", at = @At("HEAD"), cancellable = true) - public void getChunk(int chunkX, int chunkZ, CallbackInfoReturnable cir) { - int x = chunkX - this.gensouHacks$minChunkX; - int z = chunkZ - this.gensouHacks$minChunkZ; - int w = this.size; - - if (x >= 0 && z >= 0 && x < w && z < w) { - cir.setReturnValue(this.gensouHacks$chunksArr[x + z * w]); - cir.cancel(); - } else { - throw new NullPointerException("No chunk exists at " + new ChunkPos(chunkX, chunkZ)); - } - } - - @Inject(method = "getBlockState", at = @At("HEAD"), cancellable = true) - public void getBlockState(BlockPos pos, CallbackInfoReturnable cir) { - int x = (Pos.ChunkCoord.fromBlockCoord(pos.getX())) - this.gensouHacks$minChunkX; - int z = (Pos.ChunkCoord.fromBlockCoord(pos.getZ())) - this.gensouHacks$minChunkZ; - int w = this.size; - - if (x >= 0 && z >= 0 && x < w && z < w) { - cir.setReturnValue(this.gensouHacks$chunksArr[x + z * w].getBlockState(pos)); - cir.cancel(); - } else { - throw new NullPointerException("No chunk exists at " + new ChunkPos(pos)); - } - } -} +//@Mixin(WorldGenRegion.class) +//public class MixinWorldGenRegion { +// @Shadow @Final private ChunkPos firstPos; +// @Shadow @Final private int size; +// +// @Unique +// private ChunkAccess[] gensouHacks$chunksArr; +// @Unique +// private int gensouHacks$minChunkX; +// @Unique +// private int gensouHacks$minChunkZ; +// +// @Inject(method = "", at = @At("RETURN")) +// private void onInit(ServerLevel world, List chunks, ChunkStatus status, int placementRadius, CallbackInfo ci) { +// this.gensouHacks$minChunkX = this.firstPos.x; +// this.gensouHacks$minChunkZ = this.firstPos.z; +// this.gensouHacks$chunksArr = chunks.toArray(new ChunkAccess[0]); +// } +// +// @Inject(method = "getChunk(II)Lnet/minecraft/world/level/chunk/ChunkAccess;", at = @At("HEAD"), cancellable = true) +// public void getChunk(int chunkX, int chunkZ, CallbackInfoReturnable cir) { +// int x = chunkX - this.gensouHacks$minChunkX; +// int z = chunkZ - this.gensouHacks$minChunkZ; +// int w = this.size; +// +// if (x >= 0 && z >= 0 && x < w && z < w) { +// cir.setReturnValue(this.gensouHacks$chunksArr[x + z * w]); +// cir.cancel(); +// } else { +// throw new NullPointerException("No chunk exists at " + new ChunkPos(chunkX, chunkZ)); +// } +// } +// +// @Inject(method = "getBlockState", at = @At("HEAD"), cancellable = true) +// public void getBlockState(BlockPos pos, CallbackInfoReturnable cir) { +// int x = (Pos.ChunkCoord.fromBlockCoord(pos.getX())) - this.gensouHacks$minChunkX; +// int z = (Pos.ChunkCoord.fromBlockCoord(pos.getZ())) - this.gensouHacks$minChunkZ; +// int w = this.size; +// +// if (x >= 0 && z >= 0 && x < w && z < w) { +// cir.setReturnValue(this.gensouHacks$chunksArr[x + z * w].getBlockState(pos)); +// cir.cancel(); +// } else { +// throw new NullPointerException("No chunk exists at " + new ChunkPos(pos)); +// } +// } +//} diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/alloc/chunk_ticking/ServerChunkManagerMixin.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/alloc/chunk_ticking/ServerChunkManagerMixin.java index 80005d2..f0c3c8a 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/alloc/chunk_ticking/ServerChunkManagerMixin.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/alloc/chunk_ticking/ServerChunkManagerMixin.java @@ -14,40 +14,40 @@ // along with this program. If not, see . package net.gensokyoreimagined.nitori.mixin.alloc.chunk_ticking; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ServerChunkCache; -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.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.ArrayList; -import java.util.function.BooleanSupplier; - -@Mixin(ServerChunkCache.class) -public class ServerChunkManagerMixin { - private final ArrayList cachedChunkList = new ArrayList<>(); - - @Redirect( - method = "tickChunks()V", - at = @At( - value = "INVOKE", - target = "Lcom/google/common/collect/Lists;newArrayListWithCapacity(I)Ljava/util/ArrayList;", - remap = false - ) - ) - private ArrayList redirectChunksListClone(int initialArraySize) { - ArrayList list = this.cachedChunkList; - list.clear(); // Ensure the list is empty before re-using it - list.ensureCapacity(initialArraySize); - - return list; - } - - @Inject(method = "tick(Ljava/util/function/BooleanSupplier;Z)V", at = @At("HEAD")) - private void preTick(BooleanSupplier shouldKeepTicking, boolean tickChunks, CallbackInfo ci) { - // Ensure references aren't leaked through this list - this.cachedChunkList.clear(); - } -} \ No newline at end of file +//import net.minecraft.server.level.ChunkHolder; +//import net.minecraft.server.level.ServerChunkCache; +//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.Redirect; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +// +//import java.util.ArrayList; +//import java.util.function.BooleanSupplier; +// +//@Mixin(ServerChunkCache.class) +//public class ServerChunkManagerMixin { +// private final ArrayList cachedChunkList = new ArrayList<>(); +// +// @Redirect( +// method = "tickChunks", +// at = @At( +// value = "INVOKE", +// target = "Lcom/google/common/collect/Lists;newArrayListWithCapacity(I)Ljava/util/ArrayList;", +// remap = false +// ) +// ) +// private ArrayList redirectChunksListClone(int initialArraySize) { +// ArrayList list = this.cachedChunkList; +// list.clear(); // Ensure the list is empty before re-using it +// list.ensureCapacity(initialArraySize); +// +// return list; +// } +// +// @Inject(method = "tick(Ljava/util/function/BooleanSupplier;Z)V", at = @At("HEAD")) +// private void preTick(BooleanSupplier shouldKeepTicking, boolean tickChunks, CallbackInfo ci) { +// // Ensure references aren't leaked through this list +// this.cachedChunkList.clear(); +// } +//} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/collections/attributes/AttributeContainerMixin.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/collections/attributes/AttributeContainerMixin.java index 3f8ccca..c19b7ac 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/collections/attributes/AttributeContainerMixin.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/collections/attributes/AttributeContainerMixin.java @@ -1,40 +1,40 @@ package net.gensokyoreimagined.nitori.mixin.collections.attributes; -import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; -import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; -import net.minecraft.world.entity.ai.attributes.AttributeMap; -import net.minecraft.world.entity.ai.attributes.AttributeSupplier; -import net.minecraft.world.entity.ai.attributes.Attribute; -import net.minecraft.world.entity.ai.attributes.AttributeInstance; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -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 java.util.Map; -import java.util.Set; - -@Mixin(AttributeMap.class) -public class AttributeContainerMixin { - @Mutable - @Shadow - @Final - private Map attributes; - - @Mutable - @Shadow - @Final - private Set dirtyAttributes; - - @Inject( - method = "", - at = @At("RETURN") - ) - private void initCollections(AttributeSupplier defaultAttributes, CallbackInfo ci) { - this.attributes = new Reference2ReferenceOpenHashMap<>(0); - this.dirtyAttributes = new ReferenceOpenHashSet<>(0); - } -} \ No newline at end of file +//import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; +//import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; +//import net.minecraft.world.entity.ai.attributes.AttributeMap; +//import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +//import net.minecraft.world.entity.ai.attributes.Attribute; +//import net.minecraft.world.entity.ai.attributes.AttributeInstance; +//import org.spongepowered.asm.mixin.Final; +//import org.spongepowered.asm.mixin.Mixin; +//import org.spongepowered.asm.mixin.Mutable; +//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 java.util.Map; +//import java.util.Set; +// +//@Mixin(AttributeMap.class) +//public class AttributeContainerMixin { +// @Mutable +// @Shadow +// @Final +// private Map attributes; +// +// @Mutable +// @Shadow +// @Final +// private Set attributesToSync; +// +// @Inject( +// method = "", +// at = @At("RETURN") +// ) +// private void initCollections(AttributeSupplier defaultAttributes, CallbackInfo ci) { +// this.attributes = new Reference2ReferenceOpenHashMap<>(0); +// this.attributesToSync = new ReferenceOpenHashSet<>(0); +// } +//} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/needs_testing/util/block_tracking/ChunkSectionMixin.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/needs_testing/util/block_tracking/ChunkSectionMixin.java index b38c251..92feef0 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/needs_testing/util/block_tracking/ChunkSectionMixin.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/needs_testing/util/block_tracking/ChunkSectionMixin.java @@ -1,189 +1,189 @@ package net.gensokyoreimagined.nitori.mixin.needs_testing.util.block_tracking; -import net.gensokyoreimagined.nitori.common.block.*; -import net.gensokyoreimagined.nitori.common.entity.block_tracking.ChunkSectionChangeCallback; -import net.gensokyoreimagined.nitori.common.entity.block_tracking.SectionedBlockChangeTracker; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.core.SectionPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.chunk.LevelChunkSection; -import net.minecraft.world.level.chunk.PalettedContainer; -import org.spongepowered.asm.mixin.*; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -/** - * Keep track of how many blocks that meet certain criteria are in this chunk section. - * E.g. if no over-sized blocks are there, collision code can skip a few blocks. - * - * @author 2No2Name - */ -@Mixin(LevelChunkSection.class) -public abstract class ChunkSectionMixin implements BlockCountingSection, BlockListeningSection { - - @Shadow - @Final - public PalettedContainer states; - - @Unique - private short[] countsByFlag = null; - @Unique - private ChunkSectionChangeCallback changeListener; - @Unique - private short listeningMask; - - @Unique - private static void addToFlagCount(short[] countsByFlag, BlockState state, short change) { - int flags = ((BlockStateFlagHolder) state).lithium$getAllFlags(); - int i; - while ((i = Integer.numberOfTrailingZeros(flags)) < 32 && i < countsByFlag.length) { - //either count up by one (prevFlag not set) or down by one (prevFlag set) - countsByFlag[i] += change; - flags &= ~(1 << i); - } - } - - @Override - public boolean lithium$mayContainAny(TrackedBlockStatePredicate trackedBlockStatePredicate) { - if (this.countsByFlag == null) { - fastInitClientCounts(); - } - return this.countsByFlag[trackedBlockStatePredicate.getIndex()] != (short) 0; - } - - @Unique - private void fastInitClientCounts() { - this.countsByFlag = new short[BlockStateFlags.NUM_TRACKED_FLAGS]; - for (TrackedBlockStatePredicate trackedBlockStatePredicate : BlockStateFlags.TRACKED_FLAGS) { - if (this.states.maybeHas(trackedBlockStatePredicate)) { - //We haven't counted, so we just set the count so high that it never incorrectly reaches 0. - //For most situations, this overestimation does not hurt client performance compared to correct counting, - this.countsByFlag[trackedBlockStatePredicate.getIndex()] = 16 * 16 * 16; - } - } - } - -// @Redirect( -// method = "recalcBlockCounts()V", +//import net.gensokyoreimagined.nitori.common.block.*; +//import net.gensokyoreimagined.nitori.common.entity.block_tracking.ChunkSectionChangeCallback; +//import net.gensokyoreimagined.nitori.common.entity.block_tracking.SectionedBlockChangeTracker; +//import net.minecraft.world.level.block.state.BlockState; +//import net.minecraft.network.FriendlyByteBuf; +//import net.minecraft.core.SectionPos; +//import net.minecraft.world.level.Level; +//import net.minecraft.world.level.chunk.LevelChunkSection; +//import net.minecraft.world.level.chunk.PalettedContainer; +//import org.spongepowered.asm.mixin.*; +//import org.spongepowered.asm.mixin.injection.At; +//import org.spongepowered.asm.mixin.injection.Inject; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +//import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +// +///** +// * Keep track of how many blocks that meet certain criteria are in this chunk section. +// * E.g. if no over-sized blocks are there, collision code can skip a few blocks. +// * +// * @author 2No2Name +// */ +//@Mixin(LevelChunkSection.class) +//public abstract class ChunkSectionMixin implements BlockCountingSection, BlockListeningSection { +// +// @Shadow +// @Final +// public PalettedContainer states; +// +// @Unique +// private short[] countsByFlag = null; +// @Unique +// private ChunkSectionChangeCallback changeListener; +// @Unique +// private short listeningMask; +// +// @Unique +// private static void addToFlagCount(short[] countsByFlag, BlockState state, short change) { +// int flags = ((BlockStateFlagHolder) state).lithium$getAllFlags(); +// int i; +// while ((i = Integer.numberOfTrailingZeros(flags)) < 32 && i < countsByFlag.length) { +// //either count up by one (prevFlag not set) or down by one (prevFlag set) +// countsByFlag[i] += change; +// flags &= ~(1 << i); +// } +// } +// +// @Override +// public boolean lithium$mayContainAny(TrackedBlockStatePredicate trackedBlockStatePredicate) { +// if (this.countsByFlag == null) { +// fastInitClientCounts(); +// } +// return this.countsByFlag[trackedBlockStatePredicate.getIndex()] != (short) 0; +// } +// +// @Unique +// private void fastInitClientCounts() { +// this.countsByFlag = new short[BlockStateFlags.NUM_TRACKED_FLAGS]; +// for (TrackedBlockStatePredicate trackedBlockStatePredicate : BlockStateFlags.TRACKED_FLAGS) { +// if (this.states.maybeHas(trackedBlockStatePredicate)) { +// //We haven't counted, so we just set the count so high that it never incorrectly reaches 0. +// //For most situations, this overestimation does not hurt client performance compared to correct counting, +// this.countsByFlag[trackedBlockStatePredicate.getIndex()] = 16 * 16 * 16; +// } +// } +// } +// +//// @Redirect( +//// method = "recalcBlockCounts()V", +//// at = @At( +//// value = "INVOKE", +//// target = "Lnet/minecraft/world/chunk/PalettedContainer;count(Lnet/minecraft/world/chunk/PalettedContainer$Counter;)V" +//// ) +//// ) +//// private void initFlagCounters(PalettedContainer palettedContainer, PalettedContainer.Counter consumer) { +//// palettedContainer.count((state, count) -> { +//// consumer.accept(state, count); +//// addToFlagCount(this.countsByFlag, state, (short) count); +//// }); +//// } +// @Shadow +// short nonEmptyBlockCount; +// @Shadow +// private short tickingBlockCount; +// @Shadow +// private short tickingFluidCount; +// +// /** +// * @author DoggySazHi +// * @reason Replace the Paper implementation with Mojang + Lithium implementation +// */ +// @Overwrite +// public void recalcBlockCounts() { +// this.countsByFlag = new short[BlockStateFlags.NUM_TRACKED_FLAGS]; +// +// BlockStateCounter lv = new BlockStateCounter(); +// this.states.count((state, count) -> { +// lv.accept(state, count); +// addToFlagCount(this.countsByFlag, state, (short) count); +// }); +// +// this.nonEmptyBlockCount = (short)lv.nonEmptyBlockCount; +// this.tickingBlockCount = (short)lv.randomTickableBlockCount; +// this.tickingFluidCount = (short)lv.nonEmptyFluidCount; +// } +// +// @Inject( +// method = "read", +// at = @At(value = "HEAD") +// ) +// private void resetData(FriendlyByteBuf buf, CallbackInfo ci) { +// this.countsByFlag = null; +// } +// +// @Inject( +// method = "setBlockState(IIILnet/minecraft/world/level/block/state/BlockState;Z)Lnet/minecraft/world/level/block/state/BlockState;", // at = @At( // value = "INVOKE", -// target = "Lnet/minecraft/world/chunk/PalettedContainer;count(Lnet/minecraft/world/chunk/PalettedContainer$Counter;)V" -// ) +// target = "Lnet/minecraft/world/level/block/state/BlockState;getFluidState()Lnet/minecraft/world/level/material/FluidState;", +// ordinal = 0, +// shift = At.Shift.BEFORE +// ), +// locals = LocalCapture.CAPTURE_FAILHARD // ) -// private void initFlagCounters(PalettedContainer palettedContainer, PalettedContainer.Counter consumer) { -// palettedContainer.count((state, count) -> { -// consumer.accept(state, count); -// addToFlagCount(this.countsByFlag, state, (short) count); -// }); +// private void updateFlagCounters(int x, int y, int z, BlockState newState, boolean lock, CallbackInfoReturnable cir, BlockState oldState) { +// this.lithium$trackBlockStateChange(newState, oldState); // } - @Shadow - short nonEmptyBlockCount; - @Shadow - private short tickingBlockCount; - @Shadow - private short tickingFluidCount; - - /** - * @author DoggySazHi - * @reason Replace the Paper implementation with Mojang + Lithium implementation - */ - @Overwrite - public void recalcBlockCounts() { - this.countsByFlag = new short[BlockStateFlags.NUM_TRACKED_FLAGS]; - - BlockStateCounter lv = new BlockStateCounter(); - this.states.count((state, count) -> { - lv.accept(state, count); - addToFlagCount(this.countsByFlag, state, (short) count); - }); - - this.nonEmptyBlockCount = (short)lv.nonEmptyBlockCount; - this.tickingBlockCount = (short)lv.randomTickableBlockCount; - this.tickingFluidCount = (short)lv.nonEmptyFluidCount; - } - - @Inject( - method = "read", - at = @At(value = "HEAD") - ) - private void resetData(FriendlyByteBuf buf, CallbackInfo ci) { - this.countsByFlag = null; - } - - @Inject( - method = "setBlockState(IIILnet/minecraft/world/level/block/state/BlockState;Z)Lnet/minecraft/world/level/block/state/BlockState;", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/block/state/BlockState;getFluidState()Lnet/minecraft/world/level/material/FluidState;", - ordinal = 0, - shift = At.Shift.BEFORE - ), - locals = LocalCapture.CAPTURE_FAILHARD - ) - private void updateFlagCounters(int x, int y, int z, BlockState newState, boolean lock, CallbackInfoReturnable cir, BlockState oldState) { - this.lithium$trackBlockStateChange(newState, oldState); - } - - @Override - public void lithium$trackBlockStateChange(BlockState newState, BlockState oldState) { - short[] countsByFlag = this.countsByFlag; - if (countsByFlag == null) { - return; - } - int prevFlags = ((BlockStateFlagHolder) oldState).lithium$getAllFlags(); - int flags = ((BlockStateFlagHolder) newState).lithium$getAllFlags(); - - int flagsXOR = prevFlags ^ flags; - //we need to iterate over indices that changed or are in the listeningMask - //Some Listening Flags are sensitive to both the previous and the new block. Others are only sensitive to - //blocks that are different according to the predicate (XOR). For XOR, the block counting needs to be updated - //as well. - int iterateFlags = (~BlockStateFlags.LISTENING_MASK_OR & flagsXOR) | - (BlockStateFlags.LISTENING_MASK_OR & this.listeningMask & (prevFlags | flags)); - int flagIndex; - - while ((flagIndex = Integer.numberOfTrailingZeros(iterateFlags)) < 32 && flagIndex < countsByFlag.length) { - int flagBit = 1 << flagIndex; - //either count up by one (prevFlag not set) or down by one (prevFlag set) - if ((flagsXOR & flagBit) != 0) { - countsByFlag[flagIndex] += (short) (1 - (((prevFlags >>> flagIndex) & 1) << 1)); - } - if ((this.listeningMask & flagBit) != 0) { - this.listeningMask = this.changeListener.onBlockChange(flagIndex, this); - } - iterateFlags &= ~flagBit; - } - } - - @Override - public void lithium$addToCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker, long sectionPos, Level world) { - if (this.changeListener == null) { - if (sectionPos == Long.MIN_VALUE || world == null) { - throw new IllegalArgumentException("Expected world and section pos during intialization!"); - } - this.changeListener = ChunkSectionChangeCallback.create(sectionPos, world); - } - - this.listeningMask = this.changeListener.addTracker(tracker, blockGroup); - } - - @Override - public void lithium$removeFromCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker) { - if (this.changeListener != null) { - this.listeningMask = this.changeListener.removeTracker(tracker, blockGroup); - } - } - - @Override - @Unique - public void lithium$invalidateListeningSection(SectionPos sectionPos) { - if (this.listeningMask != 0) { - this.changeListener.onChunkSectionInvalidated(sectionPos); - this.listeningMask = 0; - } - } -} \ No newline at end of file +// +// @Override +// public void lithium$trackBlockStateChange(BlockState newState, BlockState oldState) { +// short[] countsByFlag = this.countsByFlag; +// if (countsByFlag == null) { +// return; +// } +// int prevFlags = ((BlockStateFlagHolder) oldState).lithium$getAllFlags(); +// int flags = ((BlockStateFlagHolder) newState).lithium$getAllFlags(); +// +// int flagsXOR = prevFlags ^ flags; +// //we need to iterate over indices that changed or are in the listeningMask +// //Some Listening Flags are sensitive to both the previous and the new block. Others are only sensitive to +// //blocks that are different according to the predicate (XOR). For XOR, the block counting needs to be updated +// //as well. +// int iterateFlags = (~BlockStateFlags.LISTENING_MASK_OR & flagsXOR) | +// (BlockStateFlags.LISTENING_MASK_OR & this.listeningMask & (prevFlags | flags)); +// int flagIndex; +// +// while ((flagIndex = Integer.numberOfTrailingZeros(iterateFlags)) < 32 && flagIndex < countsByFlag.length) { +// int flagBit = 1 << flagIndex; +// //either count up by one (prevFlag not set) or down by one (prevFlag set) +// if ((flagsXOR & flagBit) != 0) { +// countsByFlag[flagIndex] += (short) (1 - (((prevFlags >>> flagIndex) & 1) << 1)); +// } +// if ((this.listeningMask & flagBit) != 0) { +// this.listeningMask = this.changeListener.onBlockChange(flagIndex, this); +// } +// iterateFlags &= ~flagBit; +// } +// } +// +// @Override +// public void lithium$addToCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker, long sectionPos, Level world) { +// if (this.changeListener == null) { +// if (sectionPos == Long.MIN_VALUE || world == null) { +// throw new IllegalArgumentException("Expected world and section pos during intialization!"); +// } +// this.changeListener = ChunkSectionChangeCallback.create(sectionPos, world); +// } +// +// this.listeningMask = this.changeListener.addTracker(tracker, blockGroup); +// } +// +// @Override +// public void lithium$removeFromCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker) { +// if (this.changeListener != null) { +// this.listeningMask = this.changeListener.removeTracker(tracker, blockGroup); +// } +// } +// +// @Override +// @Unique +// public void lithium$invalidateListeningSection(SectionPos sectionPos) { +// if (this.listeningMask != 0) { +// this.changeListener.onChunkSectionInvalidated(sectionPos); +// this.listeningMask = 0; +// } +// } +//} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/util/accessors/ServerWorldAccessor.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/util/accessors/ServerWorldAccessor.java index e36e3d5..eeac7ba 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/util/accessors/ServerWorldAccessor.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/util/accessors/ServerWorldAccessor.java @@ -1,14 +1,14 @@ package net.gensokyoreimagined.nitori.mixin.util.accessors; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.entity.PersistentEntitySectionManager; -import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.Mixin; - -// Does not work on Paper... -@Mixin(ServerLevel.class) -public interface ServerWorldAccessor { - @Accessor - PersistentEntitySectionManager getEntityManager(); -} +//import net.minecraft.server.level.ServerLevel; +//import net.minecraft.world.entity.Entity; +//import net.minecraft.world.level.entity.PersistentEntitySectionManager; +//import org.spongepowered.asm.mixin.gen.Accessor; +//import org.spongepowered.asm.mixin.Mixin; +// +//// Does not work on Paper... +//@Mixin(ServerLevel.class) +//public interface ServerWorldAccessor { +// @Accessor +// PersistentEntitySectionManager getEntityManager(); +//} diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/world/block_entity_ticking/sleeping/campfire/CampfireBlockEntityMixin.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/world/block_entity_ticking/sleeping/campfire/CampfireBlockEntityMixin.java index 2fdfe32..cbe1e4c 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/world/block_entity_ticking/sleeping/campfire/CampfireBlockEntityMixin.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/world/block_entity_ticking/sleeping/campfire/CampfireBlockEntityMixin.java @@ -1,69 +1,69 @@ package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire; -import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity; -import net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.entity.CampfireBlockEntity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.core.HolderLookup; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.TickingBlockEntity; -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; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(CampfireBlockEntity.class) -public class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity { - - private WrappedBlockEntityTickInvokerAccessor tickWrapper = null; - private TickingBlockEntity sleepingTicker = null; - - public CampfireBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public WrappedBlockEntityTickInvokerAccessor lithium$getTickWrapper() { - return tickWrapper; - } - - @Override - public void lithium$setTickWrapper(WrappedBlockEntityTickInvokerAccessor tickWrapper) { - this.tickWrapper = tickWrapper; - this.lithium$setSleepingTicker(null); - } - - @Override - public TickingBlockEntity lithium$getSleepingTicker() { - return sleepingTicker; - } - - @Override - public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) { - this.sleepingTicker = sleepingTicker; - } - - - @Inject( - method = "placeFood", - at = @At(value = "INVOKE", target = "Lnet/minecraft/core/NonNullList;set(ILjava/lang/Object;)Ljava/lang/Object;") - ) - private void wakeUpOnAddItem(Entity user, ItemStack stack, int cookTime, CallbackInfoReturnable cir) { - this.wakeUpNow(); - } - - @Inject( - method = "loadAdditional", - at = @At(value = "RETURN") - ) - private void wakeUpOnReadNbt(CompoundTag nbt, HolderLookup.Provider registryLookup, CallbackInfo ci) { - this.wakeUpNow(); - } -} \ No newline at end of file +//import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity; +//import net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor; +//import net.minecraft.world.entity.Entity; +//import net.minecraft.world.level.block.state.BlockState; +//import net.minecraft.world.level.block.entity.BlockEntity; +//import net.minecraft.world.level.block.entity.BlockEntityType; +//import net.minecraft.world.level.block.entity.CampfireBlockEntity; +//import net.minecraft.world.entity.LivingEntity; +//import net.minecraft.world.item.ItemStack; +//import net.minecraft.nbt.CompoundTag; +//import net.minecraft.core.HolderLookup; +//import net.minecraft.core.BlockPos; +//import net.minecraft.world.level.block.entity.TickingBlockEntity; +//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; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +// +//@Mixin(CampfireBlockEntity.class) +//public class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity { +// +// private WrappedBlockEntityTickInvokerAccessor tickWrapper = null; +// private TickingBlockEntity sleepingTicker = null; +// +// public CampfireBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState state) { +// super(type, pos, state); +// } +// +// @Override +// public WrappedBlockEntityTickInvokerAccessor lithium$getTickWrapper() { +// return tickWrapper; +// } +// +// @Override +// public void lithium$setTickWrapper(WrappedBlockEntityTickInvokerAccessor tickWrapper) { +// this.tickWrapper = tickWrapper; +// this.lithium$setSleepingTicker(null); +// } +// +// @Override +// public TickingBlockEntity lithium$getSleepingTicker() { +// return sleepingTicker; +// } +// +// @Override +// public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) { +// this.sleepingTicker = sleepingTicker; +// } +// +// +// @Inject( +// method = "placeFood", +// at = @At(value = "INVOKE", target = "Lnet/minecraft/core/NonNullList;set(ILjava/lang/Object;)Ljava/lang/Object;") +// ) +// private void wakeUpOnAddItem(LivingEntity user, ItemStack stack, int cookTime, CallbackInfoReturnable cir) { +// this.wakeUpNow(); +// } +// +// @Inject( +// method = "loadAdditional", +// at = @At(value = "RETURN") +// ) +// private void wakeUpOnReadNbt(CompoundTag nbt, HolderLookup.Provider registryLookup, CallbackInfo ci) { +// this.wakeUpNow(); +// } +//} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/world/block_entity_ticking/sleeping/campfire/lit/CampfireBlockEntityMixin.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/world/block_entity_ticking/sleeping/campfire/lit/CampfireBlockEntityMixin.java index 53c3099..7457abd 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/world/block_entity_ticking/sleeping/campfire/lit/CampfireBlockEntityMixin.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/world/block_entity_ticking/sleeping/campfire/lit/CampfireBlockEntityMixin.java @@ -1,40 +1,40 @@ package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire.lit; -import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity; -import net.minecraft.core.BlockPos; -import net.minecraft.world.SimpleContainer; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.entity.CampfireBlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import org.bukkit.craftbukkit.inventory.CraftItemStack; -import org.bukkit.event.block.BlockCookEvent; -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; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import java.util.Optional; - -@Mixin(CampfireBlockEntity.class) -public abstract class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity { - - public CampfireBlockEntityMixin(BlockPos pos, BlockState state) { - super(BlockEntityType.CAMPFIRE, pos, state); - } - - @Inject( - method = "cookTick", - at = @At("RETURN"), - locals = LocalCapture.CAPTURE_FAILHARD - ) - private static void trySleepLit(Level world, BlockPos pos, BlockState state, CampfireBlockEntity campfire, CallbackInfo ci, boolean flag) { - if (!flag) { - CampfireBlockEntityMixin self = (CampfireBlockEntityMixin) (Object) campfire; - self.nitori$startSleeping(); - } - } -} +//import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity; +//import net.minecraft.core.BlockPos; +//import net.minecraft.world.SimpleContainer; +//import net.minecraft.world.item.ItemStack; +//import net.minecraft.world.level.Level; +//import net.minecraft.world.level.block.entity.BlockEntity; +//import net.minecraft.world.level.block.entity.BlockEntityType; +//import net.minecraft.world.level.block.entity.CampfireBlockEntity; +//import net.minecraft.world.level.block.state.BlockState; +//import org.bukkit.craftbukkit.inventory.CraftItemStack; +//import org.bukkit.event.block.BlockCookEvent; +//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; +//import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +// +//import java.util.Optional; +// +//@Mixin(CampfireBlockEntity.class) +//public abstract class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity { +// +// public CampfireBlockEntityMixin(BlockPos pos, BlockState state) { +// super(BlockEntityType.CAMPFIRE, pos, state); +// } +// +// @Inject( +// method = "cookTick", +// at = @At("RETURN"), +// locals = LocalCapture.CAPTURE_FAILHARD +// ) +// private static void trySleepLit(Level world, BlockPos pos, BlockState state, CampfireBlockEntity campfire, CallbackInfo ci, boolean flag) { +// if (!flag) { +// CampfireBlockEntityMixin self = (CampfireBlockEntityMixin) (Object) campfire; +// self.nitori$startSleeping(); +// } +// } +//} diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/world/block_entity_ticking/sleeping/campfire/unlit/CampfireBlockEntityMixin.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/world/block_entity_ticking/sleeping/campfire/unlit/CampfireBlockEntityMixin.java index c2cda7b..4f2ae1e 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/mixin/world/block_entity_ticking/sleeping/campfire/unlit/CampfireBlockEntityMixin.java +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/world/block_entity_ticking/sleeping/campfire/unlit/CampfireBlockEntityMixin.java @@ -1,34 +1,34 @@ package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire.unlit; -import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.entity.CampfireBlockEntity; -import net.minecraft.world.level.block.state.BlockState; -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; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -@Mixin(CampfireBlockEntity.class) -public abstract class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity { - - public CampfireBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Inject( - method = "cooldownTick", - at = @At("RETURN"), - locals = LocalCapture.CAPTURE_FAILHARD - ) - private static void trySleepLit(Level world, BlockPos pos, BlockState state, CampfireBlockEntity campfire, CallbackInfo ci, boolean flag) { - if (!flag) { - CampfireBlockEntityMixin self = (CampfireBlockEntityMixin) (Object) campfire; - self.nitori$startSleeping(); - } - } -} \ No newline at end of file +//import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity; +//import net.minecraft.core.BlockPos; +//import net.minecraft.world.level.Level; +//import net.minecraft.world.level.block.entity.BlockEntity; +//import net.minecraft.world.level.block.entity.BlockEntityType; +//import net.minecraft.world.level.block.entity.CampfireBlockEntity; +//import net.minecraft.world.level.block.state.BlockState; +//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; +//import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +// +//@Mixin(CampfireBlockEntity.class) +//public abstract class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity { +// +// public CampfireBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState state) { +// super(type, pos, state); +// } +// +// @Inject( +// method = "cooldownTick", +// at = @At("RETURN"), +// locals = LocalCapture.CAPTURE_FAILHARD +// ) +// private static void trySleepLit(Level world, BlockPos pos, BlockState state, CampfireBlockEntity campfire, CallbackInfo ci, boolean flag) { +// if (!flag) { +// CampfireBlockEntityMixin self = (CampfireBlockEntityMixin) (Object) campfire; +// self.nitori$startSleeping(); +// } +// } +//} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/tracker/MultithreadedTracker.java b/src/main/java/net/gensokyoreimagined/nitori/tracker/MultithreadedTracker.java index 0d688b8..301503a 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/tracker/MultithreadedTracker.java +++ b/src/main/java/net/gensokyoreimagined/nitori/tracker/MultithreadedTracker.java @@ -18,147 +18,147 @@ * Ported from Petal, derived from Airplane */ -import ca.spottedleaf.moonrise.common.list.ReferenceList; -import ca.spottedleaf.moonrise.common.misc.NearbyPlayers; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet; //io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet; -import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices; //io.papermc.paper.world.ChunkEntitySlices; -import net.gensokyoreimagined.nitori.access.IMixinChunkEntitySlicesAccess; -import net.gensokyoreimagined.nitori.access.IMixinChunkMap_TrackedEntityAccess; -import net.gensokyoreimagined.nitori.access.IMixinIteratorSafeOrderedReferenceSetAccess; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.chunk.LevelChunk; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicInteger; - -public class MultithreadedTracker { - - private enum TrackerStage { - UPDATE_PLAYERS, - SEND_CHANGES - } - - private static final int parallelism = Math.max(4, Runtime.getRuntime().availableProcessors()); - private static final Executor trackerExecutor = Executors.newFixedThreadPool(parallelism, new ThreadFactoryBuilder() - .setNameFormat("mirai-tracker-%d") - .setPriority(Thread.NORM_PRIORITY - 2) - .build()); - - private final ReferenceList entityTickingChunks; - private final AtomicInteger taskIndex = new AtomicInteger(); - - private final ConcurrentLinkedQueue mainThreadTasks; - private final AtomicInteger finishedTasks = new AtomicInteger(); - - public MultithreadedTracker(ReferenceList entityTickingChunks, ConcurrentLinkedQueue mainThreadTasks) { - this.entityTickingChunks = entityTickingChunks; - this.mainThreadTasks = mainThreadTasks; - } - - public void tick() { - this.taskIndex.set(0); - this.finishedTasks.set(0); - - for (int i = 0; i < parallelism; i++) { - trackerExecutor.execute(this::runUpdatePlayers); - } - - // start with updating players - while (this.taskIndex.get() < this.entityTickingChunks.size()) { - this.runMainThreadTasks(); - this.handleChunkUpdates(5); // assist - } - - // then send changes - while (this.finishedTasks.get() != parallelism) { - this.runMainThreadTasks(); - } - - this.runMainThreadTasks(); // finish any remaining tasks - - for (ServerChunkCache.ChunkAndHolder chunkAndHolder : this.entityTickingChunks) { - LevelChunk chunk = chunkAndHolder.chunk(); - - if (chunk != null) { - this.updateChunkEntities(chunk, TrackerStage.SEND_CHANGES); - } - } - } - - private void runMainThreadTasks() { - try { - Runnable task; - while ((task = this.mainThreadTasks.poll()) != null) { - task.run(); - } - } catch (Throwable throwable) { - MinecraftServer.LOGGER.warn("Tasks failed while ticking track queue", throwable); - } - } - - private void runUpdatePlayers() { - try { - while (handleChunkUpdates(10)); - } finally { - this.finishedTasks.incrementAndGet(); - } - } - - private boolean handleChunkUpdates(int tasks) { - int index; - while ((index = this.taskIndex.getAndAdd(tasks)) < this.entityTickingChunks.size()) { - for (int i = index; i < index + tasks && i < this.entityTickingChunks.size(); i++) { - LevelChunk chunk = this.entityTickingChunks.getChecked(i).chunk(); - if (chunk != null) { - try { - this.updateChunkEntities(chunk, TrackerStage.UPDATE_PLAYERS); - } catch (Throwable throwable) { - MinecraftServer.LOGGER.warn("Ticking tracker failed", throwable); - } - - } - } - - return true; - } - - return false; - } - - private void updateChunkEntities(LevelChunk chunk, TrackerStage trackerStage) { - final ChunkEntitySlices entitySlices = chunk.level.moonrise$getEntityLookup().getChunk(chunk.locX, chunk.locZ); - if (entitySlices == null) { - return; - } - - final Entity[] rawEntities = ((IMixinChunkEntitySlicesAccess) (Object) entitySlices).getEntities().getRawData(); - final ChunkMap chunkMap = chunk.level.chunkSource.chunkMap; - - for (int i = 0; i < rawEntities.length; i++) { - Entity entity = rawEntities[i]; - if (entity != null) { - ChunkMap.TrackedEntity entityTracker = chunkMap.entityMap.get(entity.getId()); - if (entityTracker != null) { - if (trackerStage == TrackerStage.SEND_CHANGES) { - entityTracker.serverEntity.sendChanges(); - } else if (trackerStage == TrackerStage.UPDATE_PLAYERS) { - ReferenceList nearbyPlayers = chunkMap.level.moonrise$getNearbyPlayers().getChunk(entity.chunkPosition()).getPlayers(NearbyPlayers.NearbyMapType.VIEW_DISTANCE); - List nearbyPlayersList = new ArrayList(nearbyPlayers.size()); // intentionally typed as List for requirement clarity - nearbyPlayers.forEach(nearbyPlayersList::add); - ((IMixinChunkMap_TrackedEntityAccess) (Object) entityTracker).callUpdatePlayers(nearbyPlayersList); - } - } - } - } - } - -} +//import ca.spottedleaf.moonrise.common.list.ReferenceList; +//import ca.spottedleaf.moonrise.common.misc.NearbyPlayers; +//import com.google.common.util.concurrent.ThreadFactoryBuilder; +//import ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet; //io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet; +//import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices; //io.papermc.paper.world.ChunkEntitySlices; +//import net.gensokyoreimagined.nitori.access.IMixinChunkEntitySlicesAccess; +//import net.gensokyoreimagined.nitori.access.IMixinChunkMap_TrackedEntityAccess; +//import net.gensokyoreimagined.nitori.access.IMixinIteratorSafeOrderedReferenceSetAccess; +//import net.minecraft.server.MinecraftServer; +//import net.minecraft.server.level.ChunkMap; +//import net.minecraft.server.level.ServerChunkCache; +//import net.minecraft.server.level.ServerPlayer; +//import net.minecraft.world.entity.Entity; +//import net.minecraft.world.level.chunk.LevelChunk; +// +//import java.util.ArrayList; +//import java.util.List; +//import java.util.concurrent.ConcurrentLinkedQueue; +//import java.util.concurrent.Executor; +//import java.util.concurrent.Executors; +//import java.util.concurrent.atomic.AtomicInteger; +// +//public class MultithreadedTracker { +// +// private enum TrackerStage { +// UPDATE_PLAYERS, +// SEND_CHANGES +// } +// +// private static final int parallelism = Math.max(4, Runtime.getRuntime().availableProcessors()); +// private static final Executor trackerExecutor = Executors.newFixedThreadPool(parallelism, new ThreadFactoryBuilder() +// .setNameFormat("mirai-tracker-%d") +// .setPriority(Thread.NORM_PRIORITY - 2) +// .build()); +// +// private final ReferenceList entityTickingChunks; +// private final AtomicInteger taskIndex = new AtomicInteger(); +// +// private final ConcurrentLinkedQueue mainThreadTasks; +// private final AtomicInteger finishedTasks = new AtomicInteger(); +// +// public MultithreadedTracker(ReferenceList entityTickingChunks, ConcurrentLinkedQueue mainThreadTasks) { +// this.entityTickingChunks = entityTickingChunks; +// this.mainThreadTasks = mainThreadTasks; +// } +// +// public void tick() { +// this.taskIndex.set(0); +// this.finishedTasks.set(0); +// +// for (int i = 0; i < parallelism; i++) { +// trackerExecutor.execute(this::runUpdatePlayers); +// } +// +// // start with updating players +// while (this.taskIndex.get() < this.entityTickingChunks.size()) { +// this.runMainThreadTasks(); +// this.handleChunkUpdates(5); // assist +// } +// +// // then send changes +// while (this.finishedTasks.get() != parallelism) { +// this.runMainThreadTasks(); +// } +// +// this.runMainThreadTasks(); // finish any remaining tasks +// +// for (ServerChunkCache.ChunkAndHolder chunkAndHolder : this.entityTickingChunks) { +// LevelChunk chunk = chunkAndHolder.chunk(); +// +// if (chunk != null) { +// this.updateChunkEntities(chunk, TrackerStage.SEND_CHANGES); +// } +// } +// } +// +// private void runMainThreadTasks() { +// try { +// Runnable task; +// while ((task = this.mainThreadTasks.poll()) != null) { +// task.run(); +// } +// } catch (Throwable throwable) { +// MinecraftServer.LOGGER.warn("Tasks failed while ticking track queue", throwable); +// } +// } +// +// private void runUpdatePlayers() { +// try { +// while (handleChunkUpdates(10)); +// } finally { +// this.finishedTasks.incrementAndGet(); +// } +// } +// +// private boolean handleChunkUpdates(int tasks) { +// int index; +// while ((index = this.taskIndex.getAndAdd(tasks)) < this.entityTickingChunks.size()) { +// for (int i = index; i < index + tasks && i < this.entityTickingChunks.size(); i++) { +// LevelChunk chunk = this.entityTickingChunks.getChecked(i).chunk(); +// if (chunk != null) { +// try { +// this.updateChunkEntities(chunk, TrackerStage.UPDATE_PLAYERS); +// } catch (Throwable throwable) { +// MinecraftServer.LOGGER.warn("Ticking tracker failed", throwable); +// } +// +// } +// } +// +// return true; +// } +// +// return false; +// } +// +// private void updateChunkEntities(LevelChunk chunk, TrackerStage trackerStage) { +// final ChunkEntitySlices entitySlices = chunk.level.moonrise$getEntityLookup().getChunk(chunk.locX, chunk.locZ); +// if (entitySlices == null) { +// return; +// } +// +// final Entity[] rawEntities = ((IMixinChunkEntitySlicesAccess) (Object) entitySlices).getEntities().getRawData(); +// final ChunkMap chunkMap = chunk.level.chunkSource.chunkMap; +// +// for (int i = 0; i < rawEntities.length; i++) { +// Entity entity = rawEntities[i]; +// if (entity != null) { +// ChunkMap.TrackedEntity entityTracker = chunkMap.entityMap.get(entity.getId()); +// if (entityTracker != null) { +// if (trackerStage == TrackerStage.SEND_CHANGES) { +// entityTracker.serverEntity.sendChanges(); +// } else if (trackerStage == TrackerStage.UPDATE_PLAYERS) { +// ReferenceList nearbyPlayers = chunkMap.level.moonrise$getNearbyPlayers().getChunk(entity.chunkPosition()).getPlayers(NearbyPlayers.NearbyMapType.VIEW_DISTANCE); +// List nearbyPlayersList = new ArrayList(nearbyPlayers.size()); // intentionally typed as List for requirement clarity +// nearbyPlayers.forEach(nearbyPlayersList::add); +// ((IMixinChunkMap_TrackedEntityAccess) (Object) entityTracker).callUpdatePlayers(nearbyPlayersList); +// } +// } +// } +// } +// } +// +//} diff --git a/src/main/resources/ignite.mod.json b/src/main/resources/ignite.mod.json index f3c5000..3900fff 100755 --- a/src/main/resources/ignite.mod.json +++ b/src/main/resources/ignite.mod.json @@ -1,6 +1,6 @@ { "id": "Nitori", - "version": "1.3-SNAPSHOT", + "version": "1.5-SNAPSHOT", "mixins": [ "mixins.core.json" ] diff --git a/src/main/resources/mixins.core.json b/src/main/resources/mixins.core.json index cacfd62..a2c20fc 100755 --- a/src/main/resources/mixins.core.json +++ b/src/main/resources/mixins.core.json @@ -6,8 +6,6 @@ "target": "@env(DEFAULT)", "compatibilityLevel": "JAVA_17", "server": [ - "ChunkMapMixin", - "ChunkMapMixin$TrackedEntity", "MixinBlock", "MixinBlockPos", "MixinChunkEntitySlices", @@ -23,17 +21,12 @@ "MixinPlayerList", "MixinReobfServer", "MixinServerBossEvent", - "MixinServerEntity", - "MixinSpongeSIMD", - "MixinWorldGenRegion", "alloc.blockstate.StateMixin", - "alloc.chunk_ticking.ServerChunkManagerMixin", "alloc.composter.ComposterMixin$ComposterBlockComposterInventoryMixin", "alloc.composter.ComposterMixin$ComposterBlockDummyInventoryMixin", "alloc.composter.ComposterMixin$ComposterBlockFullComposterInventoryMixin", "alloc.biome_temprature_leak.Biome_threadLocalMixin", "cached_hashcode.BlockNeighborGroupMixin", - "collections.attributes.AttributeContainerMixin", "collections.block_entity_tickers.WorldChunkMixin", "collections.chunk_tickets.SortedArraySetMixin", "collections.entity_by_type.TypeFilterableListMixin", @@ -82,9 +75,6 @@ "util.accessors.ServerEntityManagerAccessor", "util.block_tracking.AbstractBlockStateMixin", "world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor", - "world.block_entity_ticking.sleeping.campfire.CampfireBlockEntityMixin", - "world.block_entity_ticking.sleeping.campfire.lit.CampfireBlockEntityMixin", - "world.block_entity_ticking.sleeping.campfire.unlit.CampfireBlockEntityMixin", "world.block_entity_ticking.sleeping.furnace.AbstractFurnaceBlockEntityMixin", "world.block_entity_ticking.support_cache.BlockEntityMixin", "world.block_entity_ticking.support_cache.DirectBlockEntityTickInvokerMixin",