Merge pull request #5 from Gensokyo-Reimagined/1_21

1.21 update
This commit is contained in:
Taiyou06
2024-08-09 14:02:21 +03:00
committed by GitHub
40 changed files with 2022 additions and 1879 deletions

View File

@@ -1,6 +1,5 @@
group=net.gensokyoreimagined.nitori group=net.gensokyoreimagined.nitori
version=1.4-SNAPSHOT version=1.5-SNAPSHOT
description=Converting patches into mixins, for the Ignite Framework description=Converting patches into mixins, for the Ignite Framework
org.gradle.parallel=true org.gradle.parallel=true
org.gradle.caching=true

View File

@@ -9,7 +9,7 @@ mixinExtras = "0.3.5"
paperweight = "1.7.1" paperweight = "1.7.1"
shadow = "8.1.2" shadow = "8.1.2"
spotless = "6.25.0" spotless = "6.25.0"
paper = "1.20.6-R0.1-SNAPSHOT" paper = "1.21-R0.1-SNAPSHOT"
[libraries] [libraries]
jetbrains-annotations = { module = "org.jetbrains:annotations", version.ref = "jetbrains" } jetbrains-annotations = { module = "org.jetbrains:annotations", version.ref = "jetbrains" }

View File

@@ -14,7 +14,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.access; package net.gensokyoreimagined.nitori.access;
import com.destroystokyo.paper.util.maplist.EntityList; import ca.spottedleaf.moonrise.common.list.EntityList;
public interface IMixinChunkEntitySlicesAccess { public interface IMixinChunkEntitySlicesAccess {
@SuppressWarnings("EmptyMethod") @SuppressWarnings("EmptyMethod")

View File

@@ -14,6 +14,6 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.access; package net.gensokyoreimagined.nitori.access;
public interface IMixinChunkMapAccess { //public interface IMixinChunkMapAccess {
void gensouHacks$runOnTrackerMainThread(final Runnable runnable); // void gensouHacks$runOnTrackerMainThread(final Runnable runnable);
} //}

View File

@@ -14,14 +14,15 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.access; package net.gensokyoreimagined.nitori.access;
import com.destroystokyo.paper.util.misc.PooledLinkedHashSets; //import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.ServerPlayer; //import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Entity; //
//import java.util.List;
public interface IMixinChunkMap_TrackedEntityAccess { //
@SuppressWarnings("EmptyMethod") //public interface IMixinChunkMap_TrackedEntityAccess {
Entity getEntity(); // @SuppressWarnings("EmptyMethod")
// Entity getEntity();
@SuppressWarnings("EmptyMethod") //
void callUpdatePlayers(PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> newTrackerCandidates); // @SuppressWarnings("EmptyMethod")
} // void callUpdatePlayers(List<ServerPlayer> players);
//}

View File

@@ -5,27 +5,7 @@ import net.minecraft.world.entity.vehicle.ContainerEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; 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.
* <p>
* This interface should be implemented by your {@link net.minecraft.inventory.Inventory} or
* {@link net.minecraft.inventory.SidedInventory} type to access the stack list.
* <p>
* An inventory must not extend {@link net.minecraft.block.entity.BlockEntity} if it has a supporting block that
* implements {@link net.minecraft.block.InventoryProvider}.
* <p>
* 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 { public interface LithiumInventory extends ContainerEntity {
/** /**

View File

@@ -1,14 +1,14 @@
package net.gensokyoreimagined.nitori.common.block; package net.gensokyoreimagined.nitori.common.block;
import net.gensokyoreimagined.nitori.common.entity.block_tracking.SectionedBlockChangeTracker; //import net.gensokyoreimagined.nitori.common.entity.block_tracking.SectionedBlockChangeTracker;
import net.minecraft.core.SectionPos; //import net.minecraft.core.SectionPos;
import net.minecraft.world.level.Level; //import net.minecraft.world.level.Level;
//
public interface BlockListeningSection { //public interface BlockListeningSection {
//
void lithium$addToCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker, long sectionPos, Level world); // void lithium$addToCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker, long sectionPos, Level world);
//
void lithium$removeFromCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker); // void lithium$removeFromCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker);
//
void lithium$invalidateListeningSection(SectionPos sectionPos); // void lithium$invalidateListeningSection(SectionPos sectionPos);
} //}

View File

@@ -67,7 +67,7 @@ public class BlockStateFlags {
OVERSIZED_SHAPE = new TrackedBlockStatePredicate(countingFlags.size()) { OVERSIZED_SHAPE = new TrackedBlockStatePredicate(countingFlags.size()) {
@Override @Override
public boolean test(BlockState operand) { public boolean test(BlockState operand) {
return operand.shapeExceedsCube(); return operand.hasLargeCollisionShape();
} }
}; };
countingFlags.add(OVERSIZED_SHAPE); countingFlags.add(OVERSIZED_SHAPE);

View File

@@ -1,104 +1,104 @@
package net.gensokyoreimagined.nitori.common.entity.block_tracking; package net.gensokyoreimagined.nitori.common.entity.block_tracking;
import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; //import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap;
import net.gensokyoreimagined.nitori.common.block.BlockListeningSection; //import net.gensokyoreimagined.nitori.common.block.BlockListeningSection;
import net.gensokyoreimagined.nitori.common.block.BlockStateFlags; //import net.gensokyoreimagined.nitori.common.block.BlockStateFlags;
import net.gensokyoreimagined.nitori.common.block.ListeningBlockStatePredicate; //import net.gensokyoreimagined.nitori.common.block.ListeningBlockStatePredicate;
import net.gensokyoreimagined.nitori.common.util.Pos; //import net.gensokyoreimagined.nitori.common.util.Pos;
import net.gensokyoreimagined.nitori.common.world.LithiumData; //import net.gensokyoreimagined.nitori.common.world.LithiumData;
import net.gensokyoreimagined.nitori.common.world.chunk.ChunkStatusTracker; //import net.gensokyoreimagined.nitori.common.world.chunk.ChunkStatusTracker;
import net.minecraft.core.SectionPos; //import net.minecraft.core.SectionPos;
import net.minecraft.world.level.Level; //import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.LevelChunkSection; //import net.minecraft.world.level.chunk.LevelChunkSection;
//
import java.util.ArrayList; //import java.util.ArrayList;
//
public final class ChunkSectionChangeCallback { //public final class ChunkSectionChangeCallback {
private final ArrayList<SectionedBlockChangeTracker>[] trackers; // private final ArrayList<SectionedBlockChangeTracker>[] trackers;
private short listeningMask; // private short listeningMask;
//
static { // static {
if (BlockListeningSection.class.isAssignableFrom(LevelChunkSection.class)) { // if (BlockListeningSection.class.isAssignableFrom(LevelChunkSection.class)) {
ChunkStatusTracker.registerUnloadCallback((serverWorld, chunkPos) -> { // ChunkStatusTracker.registerUnloadCallback((serverWorld, chunkPos) -> {
Long2ReferenceOpenHashMap<ChunkSectionChangeCallback> changeCallbacks = ((LithiumData) serverWorld).lithium$getData().chunkSectionChangeCallbacks(); // Long2ReferenceOpenHashMap<ChunkSectionChangeCallback> changeCallbacks = ((LithiumData) serverWorld).lithium$getData().chunkSectionChangeCallbacks();
int x = chunkPos.x; // int x = chunkPos.x;
int z = chunkPos.z; // int z = chunkPos.z;
for (int y = Pos.SectionYCoord.getMinYSection(serverWorld); y <= Pos.SectionYCoord.getMaxYSectionInclusive(serverWorld); y++) { // for (int y = Pos.SectionYCoord.getMinYSection(serverWorld); y <= Pos.SectionYCoord.getMaxYSectionInclusive(serverWorld); y++) {
SectionPos chunkSectionPos = SectionPos.of(x, y, z); // SectionPos chunkSectionPos = SectionPos.of(x, y, z);
ChunkSectionChangeCallback chunkSectionChangeCallback = changeCallbacks.remove(chunkSectionPos.asLong()); // ChunkSectionChangeCallback chunkSectionChangeCallback = changeCallbacks.remove(chunkSectionPos.asLong());
if (chunkSectionChangeCallback != null) { // if (chunkSectionChangeCallback != null) {
chunkSectionChangeCallback.onChunkSectionInvalidated(chunkSectionPos); // chunkSectionChangeCallback.onChunkSectionInvalidated(chunkSectionPos);
} // }
} // }
}); // });
} // }
} // }
//
public ChunkSectionChangeCallback() { // public ChunkSectionChangeCallback() {
//noinspection unchecked // //noinspection unchecked
this.trackers = new ArrayList[BlockStateFlags.NUM_LISTENING_FLAGS]; // this.trackers = new ArrayList[BlockStateFlags.NUM_LISTENING_FLAGS];
this.listeningMask = 0; // this.listeningMask = 0;
} // }
//
public static ChunkSectionChangeCallback create(long sectionPos, Level world) { // public static ChunkSectionChangeCallback create(long sectionPos, Level world) {
ChunkSectionChangeCallback chunkSectionChangeCallback = new ChunkSectionChangeCallback(); // ChunkSectionChangeCallback chunkSectionChangeCallback = new ChunkSectionChangeCallback();
Long2ReferenceOpenHashMap<ChunkSectionChangeCallback> changeCallbacks = ((LithiumData) world).lithium$getData().chunkSectionChangeCallbacks(); // Long2ReferenceOpenHashMap<ChunkSectionChangeCallback> changeCallbacks = ((LithiumData) world).lithium$getData().chunkSectionChangeCallbacks();
ChunkSectionChangeCallback previous = changeCallbacks.put(sectionPos, chunkSectionChangeCallback); // ChunkSectionChangeCallback previous = changeCallbacks.put(sectionPos, chunkSectionChangeCallback);
if (previous != null) { // if (previous != null) {
previous.onChunkSectionInvalidated(SectionPos.of(sectionPos)); // previous.onChunkSectionInvalidated(SectionPos.of(sectionPos));
} // }
return chunkSectionChangeCallback; // return chunkSectionChangeCallback;
} // }
//
public short onBlockChange(int blockGroupIndex, BlockListeningSection section) { // public short onBlockChange(int blockGroupIndex, BlockListeningSection section) {
ArrayList<SectionedBlockChangeTracker> sectionedBlockChangeTrackers = this.trackers[blockGroupIndex]; // ArrayList<SectionedBlockChangeTracker> sectionedBlockChangeTrackers = this.trackers[blockGroupIndex];
this.trackers[blockGroupIndex] = null; // this.trackers[blockGroupIndex] = null;
if (sectionedBlockChangeTrackers != null) { // if (sectionedBlockChangeTrackers != null) {
//noinspection ForLoopReplaceableByForEach // //noinspection ForLoopReplaceableByForEach
for (int i = 0; i < sectionedBlockChangeTrackers.size(); i++) { // for (int i = 0; i < sectionedBlockChangeTrackers.size(); i++) {
sectionedBlockChangeTrackers.get(i).setChanged(section); // sectionedBlockChangeTrackers.get(i).setChanged(section);
} // }
} // }
this.listeningMask &= (short) ~(1 << blockGroupIndex); // this.listeningMask &= (short) ~(1 << blockGroupIndex);
//
return this.listeningMask; // return this.listeningMask;
} // }
//
public short addTracker(SectionedBlockChangeTracker tracker, ListeningBlockStatePredicate blockGroup) { // public short addTracker(SectionedBlockChangeTracker tracker, ListeningBlockStatePredicate blockGroup) {
int blockGroupIndex = blockGroup.getIndex(); // int blockGroupIndex = blockGroup.getIndex();
ArrayList<SectionedBlockChangeTracker> sectionedBlockChangeTrackers = this.trackers[blockGroupIndex]; // ArrayList<SectionedBlockChangeTracker> sectionedBlockChangeTrackers = this.trackers[blockGroupIndex];
if (sectionedBlockChangeTrackers == null) { // if (sectionedBlockChangeTrackers == null) {
this.trackers[blockGroupIndex] = (sectionedBlockChangeTrackers = new ArrayList<>()); // this.trackers[blockGroupIndex] = (sectionedBlockChangeTrackers = new ArrayList<>());
} // }
sectionedBlockChangeTrackers.add(tracker); // sectionedBlockChangeTrackers.add(tracker);
//
this.listeningMask |= (short) (1 << blockGroupIndex); // this.listeningMask |= (short) (1 << blockGroupIndex);
return this.listeningMask; // return this.listeningMask;
} // }
//
public short removeTracker(SectionedBlockChangeTracker tracker, ListeningBlockStatePredicate blockGroup) { // public short removeTracker(SectionedBlockChangeTracker tracker, ListeningBlockStatePredicate blockGroup) {
int blockGroupIndex = blockGroup.getIndex(); // int blockGroupIndex = blockGroup.getIndex();
ArrayList<SectionedBlockChangeTracker> sectionedBlockChangeTrackers = this.trackers[blockGroupIndex]; // ArrayList<SectionedBlockChangeTracker> sectionedBlockChangeTrackers = this.trackers[blockGroupIndex];
if (sectionedBlockChangeTrackers != null) { // if (sectionedBlockChangeTrackers != null) {
sectionedBlockChangeTrackers.remove(tracker); // sectionedBlockChangeTrackers.remove(tracker);
if (sectionedBlockChangeTrackers.isEmpty()) { // if (sectionedBlockChangeTrackers.isEmpty()) {
this.listeningMask &= (short) ~(1 << blockGroup.getIndex()); // this.listeningMask &= (short) ~(1 << blockGroup.getIndex());
} // }
} // }
return this.listeningMask; // return this.listeningMask;
} // }
//
public void onChunkSectionInvalidated(SectionPos sectionPos) { // public void onChunkSectionInvalidated(SectionPos sectionPos) {
for (int flagIndex = 0; flagIndex < this.trackers.length; flagIndex++) { // for (int flagIndex = 0; flagIndex < this.trackers.length; flagIndex++) {
ArrayList<SectionedBlockChangeTracker> sectionedBlockChangeTrackers = this.trackers[flagIndex]; // ArrayList<SectionedBlockChangeTracker> sectionedBlockChangeTrackers = this.trackers[flagIndex];
this.trackers[flagIndex] = null; // this.trackers[flagIndex] = null;
if (sectionedBlockChangeTrackers != null) { // if (sectionedBlockChangeTrackers != null) {
//noinspection ForLoopReplaceableByForEach // //noinspection ForLoopReplaceableByForEach
for (int i = 0; i < sectionedBlockChangeTrackers.size(); i++) { // for (int i = 0; i < sectionedBlockChangeTrackers.size(); i++) {
sectionedBlockChangeTrackers.get(i).onChunkSectionInvalidated(sectionPos); // sectionedBlockChangeTrackers.get(i).onChunkSectionInvalidated(sectionPos);
} // }
} // }
} // }
this.listeningMask = 0; // this.listeningMask = 0;
} // }
} //}

View File

@@ -1,211 +1,211 @@
package net.gensokyoreimagined.nitori.common.entity.block_tracking; package net.gensokyoreimagined.nitori.common.entity.block_tracking;
import net.gensokyoreimagined.nitori.common.block.BlockListeningSection; //import net.gensokyoreimagined.nitori.common.block.BlockListeningSection;
import net.gensokyoreimagined.nitori.common.block.ListeningBlockStatePredicate; //import net.gensokyoreimagined.nitori.common.block.ListeningBlockStatePredicate;
import net.gensokyoreimagined.nitori.common.util.Pos; //import net.gensokyoreimagined.nitori.common.util.Pos;
import net.gensokyoreimagined.nitori.common.util.deduplication.LithiumInterner; //import net.gensokyoreimagined.nitori.common.util.deduplication.LithiumInterner;
import net.gensokyoreimagined.nitori.common.util.tuples.WorldSectionBox; //import net.gensokyoreimagined.nitori.common.util.tuples.WorldSectionBox;
import net.gensokyoreimagined.nitori.common.world.LithiumData; //import net.gensokyoreimagined.nitori.common.world.LithiumData;
import net.minecraft.world.phys.AABB; //import net.minecraft.world.phys.AABB;
import net.minecraft.core.SectionPos; //import net.minecraft.core.SectionPos;
import net.minecraft.world.level.Level; //import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.ChunkAccess; //import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunkSection; //import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.status.ChunkStatus; //import net.minecraft.world.level.chunk.status.ChunkStatus;
//
import java.util.ArrayList; //import java.util.ArrayList;
import java.util.Objects; //import java.util.Objects;
//
public class SectionedBlockChangeTracker { //public class SectionedBlockChangeTracker {
public final WorldSectionBox trackedWorldSections; // public final WorldSectionBox trackedWorldSections;
public final ListeningBlockStatePredicate blockGroup; // public final ListeningBlockStatePredicate blockGroup;
//
private long maxChangeTime; // private long maxChangeTime;
//
private int timesRegistered; // 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) // //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; // boolean isListeningToAll = false;
private ArrayList<SectionPos> sectionsNotListeningTo = null; // private ArrayList<SectionPos> sectionsNotListeningTo = null;
private ArrayList<BlockListeningSection> sectionsUnsubscribed = null; // private ArrayList<BlockListeningSection> sectionsUnsubscribed = null;
//
public SectionedBlockChangeTracker(WorldSectionBox trackedWorldSections, ListeningBlockStatePredicate blockGroup) { // public SectionedBlockChangeTracker(WorldSectionBox trackedWorldSections, ListeningBlockStatePredicate blockGroup) {
this.trackedWorldSections = trackedWorldSections; // this.trackedWorldSections = trackedWorldSections;
this.blockGroup = blockGroup; // this.blockGroup = blockGroup;
//
this.maxChangeTime = 0; // this.maxChangeTime = 0;
} // }
//
public boolean matchesMovedBox(AABB box) { // public boolean matchesMovedBox(AABB box) {
return this.trackedWorldSections.matchesRelevantBlocksBox(box); // return this.trackedWorldSections.matchesRelevantBlocksBox(box);
} // }
//
public static SectionedBlockChangeTracker registerAt(Level world, AABB entityBoundingBox, ListeningBlockStatePredicate blockGroup) { // public static SectionedBlockChangeTracker registerAt(Level world, AABB entityBoundingBox, ListeningBlockStatePredicate blockGroup) {
WorldSectionBox worldSectionBox = WorldSectionBox.relevantExpandedBlocksBox(world, entityBoundingBox); // WorldSectionBox worldSectionBox = WorldSectionBox.relevantExpandedBlocksBox(world, entityBoundingBox);
SectionedBlockChangeTracker tracker = new SectionedBlockChangeTracker(worldSectionBox, blockGroup); // SectionedBlockChangeTracker tracker = new SectionedBlockChangeTracker(worldSectionBox, blockGroup);
//
LithiumInterner<SectionedBlockChangeTracker> blockChangeTrackers = ((LithiumData) world).lithium$getData().blockChangeTrackers(); // LithiumInterner<SectionedBlockChangeTracker> blockChangeTrackers = ((LithiumData) world).lithium$getData().blockChangeTrackers();
tracker = blockChangeTrackers.getCanonical(tracker); // tracker = blockChangeTrackers.getCanonical(tracker);
//
tracker.register(); // tracker.register();
return tracker; // return tracker;
} // }
//
long getWorldTime() { // long getWorldTime() {
return this.trackedWorldSections.world().getGameTime(); // return this.trackedWorldSections.world().getGameTime();
} // }
//
public void register() { // public void register() {
if (this.timesRegistered == 0) { // if (this.timesRegistered == 0) {
WorldSectionBox trackedSections = this.trackedWorldSections; // WorldSectionBox trackedSections = this.trackedWorldSections;
for (int x = trackedSections.chunkX1(); x < trackedSections.chunkX2(); x++) { // for (int x = trackedSections.chunkX1(); x < trackedSections.chunkX2(); x++) {
for (int z = trackedSections.chunkZ1(); z < trackedSections.chunkZ2(); z++) { // for (int z = trackedSections.chunkZ1(); z < trackedSections.chunkZ2(); z++) {
Level world = trackedSections.world(); // Level world = trackedSections.world();
ChunkAccess chunk = world.getChunk(x, z, ChunkStatus.FULL, false); // ChunkAccess chunk = world.getChunk(x, z, ChunkStatus.FULL, false);
LevelChunkSection[] sectionArray = chunk == null ? null : chunk.getSections(); // LevelChunkSection[] sectionArray = chunk == null ? null : chunk.getSections();
for (int y = trackedSections.chunkY1(); y < trackedSections.chunkY2(); y++) { // for (int y = trackedSections.chunkY1(); y < trackedSections.chunkY2(); y++) {
if (Pos.SectionYCoord.getMinYSection(world) > y || Pos.SectionYCoord.getMaxYSectionExclusive(world) <= y) { // if (Pos.SectionYCoord.getMinYSection(world) > y || Pos.SectionYCoord.getMaxYSectionExclusive(world) <= y) {
continue; // continue;
} // }
SectionPos sectionPos = SectionPos.of(x, y, z); // SectionPos sectionPos = SectionPos.of(x, y, z);
if (sectionArray == null) { // if (sectionArray == null) {
if (this.sectionsNotListeningTo == null) { // if (this.sectionsNotListeningTo == null) {
this.sectionsNotListeningTo = new ArrayList<>(); // this.sectionsNotListeningTo = new ArrayList<>();
} // }
this.sectionsNotListeningTo.add(sectionPos); // this.sectionsNotListeningTo.add(sectionPos);
continue; // continue;
} // }
LevelChunkSection section = sectionArray[Pos.SectionYIndex.fromSectionCoord(world, y)]; // LevelChunkSection section = sectionArray[Pos.SectionYIndex.fromSectionCoord(world, y)];
//
BlockListeningSection blockListeningSection = (BlockListeningSection) section; // BlockListeningSection blockListeningSection = (BlockListeningSection) section;
blockListeningSection.lithium$addToCallback(this.blockGroup, this, SectionPos.asLong(x, y, z), world); // blockListeningSection.lithium$addToCallback(this.blockGroup, this, SectionPos.asLong(x, y, z), world);
} // }
} // }
} // }
this.isListeningToAll = (this.sectionsNotListeningTo == null || this.sectionsNotListeningTo.isEmpty()) // this.isListeningToAll = (this.sectionsNotListeningTo == null || this.sectionsNotListeningTo.isEmpty())
&& (this.sectionsUnsubscribed == null || this.sectionsUnsubscribed.isEmpty()); // && (this.sectionsUnsubscribed == null || this.sectionsUnsubscribed.isEmpty());
this.setChanged(this.getWorldTime()); // this.setChanged(this.getWorldTime());
} // }
this.timesRegistered++; // this.timesRegistered++;
} // }
//
public void unregister() { // public void unregister() {
if (--this.timesRegistered > 0) { // if (--this.timesRegistered > 0) {
return; // return;
} // }
WorldSectionBox trackedSections = this.trackedWorldSections; // WorldSectionBox trackedSections = this.trackedWorldSections;
Level world = trackedSections.world(); // Level world = trackedSections.world();
for (int x = trackedSections.chunkX1(); x < trackedSections.chunkX2(); x++) { // for (int x = trackedSections.chunkX1(); x < trackedSections.chunkX2(); x++) {
for (int z = trackedSections.chunkZ1(); z < trackedSections.chunkZ2(); z++) { // for (int z = trackedSections.chunkZ1(); z < trackedSections.chunkZ2(); z++) {
ChunkAccess chunk = world.getChunk(x, z, ChunkStatus.FULL, false); // ChunkAccess chunk = world.getChunk(x, z, ChunkStatus.FULL, false);
LevelChunkSection[] sectionArray = chunk == null ? null : chunk.getSections(); // LevelChunkSection[] sectionArray = chunk == null ? null : chunk.getSections();
for (int y = trackedSections.chunkY1(); y < trackedSections.chunkY2(); y++) { // for (int y = trackedSections.chunkY1(); y < trackedSections.chunkY2(); y++) {
//
if (sectionArray == null) { // if (sectionArray == null) {
continue; // continue;
} // }
if (Pos.SectionYCoord.getMinYSection(world) > y || Pos.SectionYCoord.getMaxYSectionExclusive(world) <= y) { // if (Pos.SectionYCoord.getMinYSection(world) > y || Pos.SectionYCoord.getMaxYSectionExclusive(world) <= y) {
continue; // continue;
} // }
LevelChunkSection section = sectionArray[Pos.SectionYIndex.fromSectionCoord(world, y)]; // LevelChunkSection section = sectionArray[Pos.SectionYIndex.fromSectionCoord(world, y)];
//
BlockListeningSection blockListeningSection = (BlockListeningSection) section; // BlockListeningSection blockListeningSection = (BlockListeningSection) section;
blockListeningSection.lithium$removeFromCallback(this.blockGroup, this); // blockListeningSection.lithium$removeFromCallback(this.blockGroup, this);
} // }
} // }
} // }
this.sectionsNotListeningTo = null; // this.sectionsNotListeningTo = null;
LithiumInterner<SectionedBlockChangeTracker> blockChangeTrackers = ((LithiumData) world).lithium$getData().blockChangeTrackers(); // LithiumInterner<SectionedBlockChangeTracker> blockChangeTrackers = ((LithiumData) world).lithium$getData().blockChangeTrackers();
blockChangeTrackers.deleteCanonical(this); // blockChangeTrackers.deleteCanonical(this);
} // }
//
public void listenToAllSections() { // public void listenToAllSections() {
boolean changed = false; // boolean changed = false;
ArrayList<SectionPos> notListeningTo = this.sectionsNotListeningTo; // ArrayList<SectionPos> notListeningTo = this.sectionsNotListeningTo;
if (notListeningTo != null) { // if (notListeningTo != null) {
for (int i = notListeningTo.size() - 1; i >= 0; i--) { // for (int i = notListeningTo.size() - 1; i >= 0; i--) {
changed = true; // changed = true;
SectionPos chunkSectionPos = notListeningTo.get(i); // SectionPos chunkSectionPos = notListeningTo.get(i);
Level world = this.trackedWorldSections.world(); // Level world = this.trackedWorldSections.world();
ChunkAccess chunk = world.getChunk(chunkSectionPos.getX(), chunkSectionPos.getZ(), ChunkStatus.FULL, false); // ChunkAccess chunk = world.getChunk(chunkSectionPos.getX(), chunkSectionPos.getZ(), ChunkStatus.FULL, false);
if (chunk != null) { // if (chunk != null) {
notListeningTo.remove(i); // notListeningTo.remove(i);
} else { // } else {
//Chunk not loaded, cannot listen to all sections. // //Chunk not loaded, cannot listen to all sections.
return; // return;
} // }
LevelChunkSection section = chunk.getSections()[Pos.SectionYIndex.fromSectionCoord(world, chunkSectionPos.getY())]; // LevelChunkSection section = chunk.getSections()[Pos.SectionYIndex.fromSectionCoord(world, chunkSectionPos.getY())];
BlockListeningSection blockListeningSection = (BlockListeningSection) section; // BlockListeningSection blockListeningSection = (BlockListeningSection) section;
blockListeningSection.lithium$addToCallback(this.blockGroup, this, chunkSectionPos.asLong(), world); // blockListeningSection.lithium$addToCallback(this.blockGroup, this, chunkSectionPos.asLong(), world);
} // }
} // }
if (this.sectionsUnsubscribed != null) { // if (this.sectionsUnsubscribed != null) {
ArrayList<BlockListeningSection> unsubscribed = this.sectionsUnsubscribed; // ArrayList<BlockListeningSection> unsubscribed = this.sectionsUnsubscribed;
for (int i = unsubscribed.size() - 1; i >= 0; i--) { // for (int i = unsubscribed.size() - 1; i >= 0; i--) {
changed = true; // changed = true;
BlockListeningSection blockListeningSection = unsubscribed.remove(i); // BlockListeningSection blockListeningSection = unsubscribed.remove(i);
blockListeningSection.lithium$addToCallback(this.blockGroup, this, Long.MIN_VALUE, null); // blockListeningSection.lithium$addToCallback(this.blockGroup, this, Long.MIN_VALUE, null);
} // }
} // }
this.isListeningToAll = true; // this.isListeningToAll = true;
if (changed) { // if (changed) {
this.setChanged(this.getWorldTime()); // this.setChanged(this.getWorldTime());
} // }
} // }
//
public void setChanged(BlockListeningSection section) { // public void setChanged(BlockListeningSection section) {
if (this.sectionsUnsubscribed == null) { // if (this.sectionsUnsubscribed == null) {
this.sectionsUnsubscribed = new ArrayList<>(); // this.sectionsUnsubscribed = new ArrayList<>();
} // }
this.sectionsUnsubscribed.add(section); // this.sectionsUnsubscribed.add(section);
this.setChanged(this.getWorldTime()); // this.setChanged(this.getWorldTime());
this.isListeningToAll = false; // this.isListeningToAll = false;
} // }
//
public void setChanged(long atTime) { // public void setChanged(long atTime) {
if (atTime > this.maxChangeTime) { // if (atTime > this.maxChangeTime) {
this.maxChangeTime = atTime; // this.maxChangeTime = atTime;
} // }
} // }
//
/** // /**
* Method to quickly check whether any relevant blocks changed inside the relevant chunk sections after // * Method to quickly check whether any relevant blocks changed inside the relevant chunk sections after
* the last test. // * the last test.
* // *
* @param lastCheckedTime time of the last interaction attempt // * @param lastCheckedTime time of the last interaction attempt
* @return whether any relevant entity moved in the tracked area // * @return whether any relevant entity moved in the tracked area
*/ // */
public boolean isUnchangedSince(long lastCheckedTime) { // public boolean isUnchangedSince(long lastCheckedTime) {
if (lastCheckedTime <= this.maxChangeTime) { // if (lastCheckedTime <= this.maxChangeTime) {
return false; // return false;
} // }
if (!this.isListeningToAll) { // if (!this.isListeningToAll) {
this.listenToAllSections(); // this.listenToAllSections();
return this.isListeningToAll && lastCheckedTime > this.maxChangeTime; // return this.isListeningToAll && lastCheckedTime > this.maxChangeTime;
} // }
return true; // return true;
} // }
//
//Do not modify, used for deduplication of instances // //Do not modify, used for deduplication of instances
@Override // @Override
public boolean equals(Object obj) { // public boolean equals(Object obj) {
if (obj == this) return true; // if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false; // if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (SectionedBlockChangeTracker) obj; // var that = (SectionedBlockChangeTracker) obj;
return Objects.equals(this.trackedWorldSections, that.trackedWorldSections) && // return Objects.equals(this.trackedWorldSections, that.trackedWorldSections) &&
Objects.equals(this.blockGroup, that.blockGroup); // Objects.equals(this.blockGroup, that.blockGroup);
} // }
//Do not modify, used for deduplication of instances // //Do not modify, used for deduplication of instances
@Override // @Override
public int hashCode() { // public int hashCode() {
return this.getClass().hashCode() ^ this.trackedWorldSections.hashCode() ^ this.blockGroup.hashCode(); // return this.getClass().hashCode() ^ this.trackedWorldSections.hashCode() ^ this.blockGroup.hashCode();
} // }
//
public void onChunkSectionInvalidated(SectionPos sectionPos) { // public void onChunkSectionInvalidated(SectionPos sectionPos) {
if (this.sectionsNotListeningTo == null) { // if (this.sectionsNotListeningTo == null) {
this.sectionsNotListeningTo = new ArrayList<>(); // this.sectionsNotListeningTo = new ArrayList<>();
} // }
this.sectionsNotListeningTo.add(sectionPos); // this.sectionsNotListeningTo.add(sectionPos);
this.setChanged(this.getWorldTime()); // this.setChanged(this.getWorldTime());
this.isListeningToAll = false; // this.isListeningToAll = false;
} // }
} //}

View File

@@ -1,18 +1,18 @@
package net.gensokyoreimagined.nitori.common.entity.movement_tracker; package net.gensokyoreimagined.nitori.common.entity.movement_tracker;
import net.minecraft.world.level.entity.EntityAccess; //import net.minecraft.world.level.entity.EntityAccess;
import net.minecraft.world.level.entity.EntitySectionStorage; //import net.minecraft.world.level.entity.EntitySectionStorage;
//
public interface EntityMovementTrackerSection { //public interface EntityMovementTrackerSection {
void lithium$addListener(SectionedEntityMovementTracker<?, ?> listener); // void lithium$addListener(SectionedEntityMovementTracker<?, ?> listener);
//
void lithium$removeListener(EntitySectionStorage<?> sectionedEntityCache, SectionedEntityMovementTracker<?, ?> listener); // void lithium$removeListener(EntitySectionStorage<?> sectionedEntityCache, SectionedEntityMovementTracker<?, ?> listener);
//
void lithium$trackEntityMovement(int notificationMask, long time); // void lithium$trackEntityMovement(int notificationMask, long time);
//
long lithium$getChangeTime(int trackedClass); // long lithium$getChangeTime(int trackedClass);
//
<S, E extends EntityAccess> void lithium$listenToMovementOnce(SectionedEntityMovementTracker<E, S> listener, int trackedClass); // <S, E extends EntityAccess> void lithium$listenToMovementOnce(SectionedEntityMovementTracker<E, S> listener, int trackedClass);
//
<S, E extends EntityAccess> void lithium$removeListenToMovementOnce(SectionedEntityMovementTracker<E, S> listener, int trackedClass); // <S, E extends EntityAccess> void lithium$removeListenToMovementOnce(SectionedEntityMovementTracker<E, S> listener, int trackedClass);
} //}

View File

@@ -1,197 +1,197 @@
package net.gensokyoreimagined.nitori.common.entity.movement_tracker; package net.gensokyoreimagined.nitori.common.entity.movement_tracker;
import it.unimi.dsi.fastutil.HashCommon; //import it.unimi.dsi.fastutil.HashCommon;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; //import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import net.gensokyoreimagined.nitori.common.util.tuples.WorldSectionBox; //import net.gensokyoreimagined.nitori.common.util.tuples.WorldSectionBox;
import net.gensokyoreimagined.nitori.common.world.LithiumData; //import net.gensokyoreimagined.nitori.common.world.LithiumData;
import net.gensokyoreimagined.nitori.mixin.util.accessors.ServerEntityManagerAccessor; //import net.gensokyoreimagined.nitori.mixin.util.accessors.ServerEntityManagerAccessor;
import net.gensokyoreimagined.nitori.mixin.util.accessors.ServerWorldAccessor; //import net.gensokyoreimagined.nitori.mixin.util.accessors.ServerWorldAccessor;
import net.minecraft.server.level.ServerLevel; //import net.minecraft.server.level.ServerLevel;
import net.minecraft.core.SectionPos; //import net.minecraft.core.SectionPos;
import net.minecraft.world.level.Level; //import net.minecraft.world.level.Level;
import net.minecraft.world.level.entity.EntityAccess; //import net.minecraft.world.level.entity.EntityAccess;
import net.minecraft.world.level.entity.EntitySection; //import net.minecraft.world.level.entity.EntitySection;
import net.minecraft.world.level.entity.EntitySectionStorage; //import net.minecraft.world.level.entity.EntitySectionStorage;
//
import java.util.ArrayList; //import java.util.ArrayList;
//
public abstract class SectionedEntityMovementTracker<E extends EntityAccess, S> { //public abstract class SectionedEntityMovementTracker<E extends EntityAccess, S> {
final WorldSectionBox trackedWorldSections; // final WorldSectionBox trackedWorldSections;
final Class<S> clazz; // final Class<S> clazz;
private final int trackedClass; // private final int trackedClass;
ArrayList<EntitySection<E>> sortedSections; // ArrayList<EntitySection<E>> sortedSections;
boolean[] sectionVisible; // boolean[] sectionVisible;
private int timesRegistered; // private int timesRegistered;
private final ArrayList<EntityMovementTrackerSection> sectionsNotListeningTo; // private final ArrayList<EntityMovementTrackerSection> sectionsNotListeningTo;
//
private long maxChangeTime; // private long maxChangeTime;
//
private ReferenceOpenHashSet<SectionedEntityMovementListener> sectionedEntityMovementListeners; // private ReferenceOpenHashSet<SectionedEntityMovementListener> sectionedEntityMovementListeners;
//
public SectionedEntityMovementTracker(WorldSectionBox interactionChunks, Class<S> clazz) { // public SectionedEntityMovementTracker(WorldSectionBox interactionChunks, Class<S> clazz) {
this.clazz = clazz; // this.clazz = clazz;
this.trackedWorldSections = interactionChunks; // this.trackedWorldSections = interactionChunks;
this.trackedClass = MovementTrackerHelper.MOVEMENT_NOTIFYING_ENTITY_CLASSES.indexOf(clazz); // this.trackedClass = MovementTrackerHelper.MOVEMENT_NOTIFYING_ENTITY_CLASSES.indexOf(clazz);
assert this.trackedClass != -1; // assert this.trackedClass != -1;
this.sectionedEntityMovementListeners = null; // this.sectionedEntityMovementListeners = null;
this.sectionsNotListeningTo = new ArrayList<>(); // this.sectionsNotListeningTo = new ArrayList<>();
} // }
//
@Override // @Override
public int hashCode() { // public int hashCode() {
return HashCommon.mix(this.trackedWorldSections.hashCode()) ^ HashCommon.mix(this.trackedClass) ^ this.getClass().hashCode(); // return HashCommon.mix(this.trackedWorldSections.hashCode()) ^ HashCommon.mix(this.trackedClass) ^ this.getClass().hashCode();
} // }
//
@Override // @Override
public boolean equals(Object obj) { // public boolean equals(Object obj) {
return obj.getClass() == this.getClass() && // return obj.getClass() == this.getClass() &&
this.clazz == ((SectionedEntityMovementTracker<?, ?>) obj).clazz && // this.clazz == ((SectionedEntityMovementTracker<?, ?>) obj).clazz &&
this.trackedWorldSections.equals(((SectionedEntityMovementTracker<?, ?>) obj).trackedWorldSections); // this.trackedWorldSections.equals(((SectionedEntityMovementTracker<?, ?>) obj).trackedWorldSections);
} // }
//
/** // /**
* Method to quickly check whether any relevant entities moved inside the relevant entity sections after // * Method to quickly check whether any relevant entities moved inside the relevant entity sections after
* the last interaction attempt. // * the last interaction attempt.
* // *
* @param lastCheckedTime time of the last interaction attempt // * @param lastCheckedTime time of the last interaction attempt
* @return whether any relevant entity moved in the tracked area // * @return whether any relevant entity moved in the tracked area
*/ // */
public boolean isUnchangedSince(long lastCheckedTime) { // public boolean isUnchangedSince(long lastCheckedTime) {
if (lastCheckedTime <= this.maxChangeTime) { // if (lastCheckedTime <= this.maxChangeTime) {
return false; // return false;
} // }
if (!this.sectionsNotListeningTo.isEmpty()) { // if (!this.sectionsNotListeningTo.isEmpty()) {
this.setChanged(this.listenToAllSectionsAndGetMaxChangeTime()); // this.setChanged(this.listenToAllSectionsAndGetMaxChangeTime());
return lastCheckedTime > this.maxChangeTime; // return lastCheckedTime > this.maxChangeTime;
} // }
return true; // return true;
} // }
//
private long listenToAllSectionsAndGetMaxChangeTime() { // private long listenToAllSectionsAndGetMaxChangeTime() {
long maxChangeTime = Long.MIN_VALUE; // long maxChangeTime = Long.MIN_VALUE;
ArrayList<EntityMovementTrackerSection> notListeningTo = this.sectionsNotListeningTo; // ArrayList<EntityMovementTrackerSection> notListeningTo = this.sectionsNotListeningTo;
for (int i = notListeningTo.size() - 1; i >= 0; i--) { // for (int i = notListeningTo.size() - 1; i >= 0; i--) {
EntityMovementTrackerSection entityMovementTrackerSection = notListeningTo.remove(i); // EntityMovementTrackerSection entityMovementTrackerSection = notListeningTo.remove(i);
entityMovementTrackerSection.lithium$listenToMovementOnce(this, this.trackedClass); // entityMovementTrackerSection.lithium$listenToMovementOnce(this, this.trackedClass);
maxChangeTime = Math.max(maxChangeTime, entityMovementTrackerSection.lithium$getChangeTime(this.trackedClass)); // maxChangeTime = Math.max(maxChangeTime, entityMovementTrackerSection.lithium$getChangeTime(this.trackedClass));
} // }
return maxChangeTime; // return maxChangeTime;
} // }
//
public void register(ServerLevel world) { // public void register(ServerLevel world) {
assert world == this.trackedWorldSections.world(); // assert world == this.trackedWorldSections.world();
//
if (this.timesRegistered == 0) { // if (this.timesRegistered == 0) {
//noinspection unchecked // //noinspection unchecked
EntitySectionStorage<E> cache = ((ServerEntityManagerAccessor<E>) ((ServerWorldAccessor) world).getEntityManager()).getSectionStorage(); // EntitySectionStorage<E> cache = ((ServerEntityManagerAccessor<E>) ((ServerWorldAccessor) world).getEntityManager()).getSectionStorage();
//
WorldSectionBox trackedSections = this.trackedWorldSections; // WorldSectionBox trackedSections = this.trackedWorldSections;
int size = trackedSections.numSections(); // int size = trackedSections.numSections();
assert size > 0; // assert size > 0;
this.sortedSections = new ArrayList<>(size); // this.sortedSections = new ArrayList<>(size);
this.sectionVisible = new boolean[size]; // this.sectionVisible = new boolean[size];
//
//vanilla iteration order in EntitySectionStorage is xzy // //vanilla iteration order in EntitySectionStorage is xzy
//WorldSectionBox upper coordinates are exclusive // //WorldSectionBox upper coordinates are exclusive
for (int x = trackedSections.chunkX1(); x < trackedSections.chunkX2(); x++) { // for (int x = trackedSections.chunkX1(); x < trackedSections.chunkX2(); x++) {
for (int z = trackedSections.chunkZ1(); z < trackedSections.chunkZ2(); z++) { // for (int z = trackedSections.chunkZ1(); z < trackedSections.chunkZ2(); z++) {
for (int y = trackedSections.chunkY1(); y < trackedSections.chunkY2(); y++) { // for (int y = trackedSections.chunkY1(); y < trackedSections.chunkY2(); y++) {
EntitySection<E> section = cache.getSection(SectionPos.asLong(x, y, z)); // EntitySection<E> section = cache.getSection(SectionPos.asLong(x, y, z));
EntityMovementTrackerSection sectionAccess = (EntityMovementTrackerSection) section; // EntityMovementTrackerSection sectionAccess = (EntityMovementTrackerSection) section;
this.sortedSections.add(section); // this.sortedSections.add(section);
sectionAccess.lithium$addListener(this); // sectionAccess.lithium$addListener(this);
} // }
} // }
} // }
this.setChanged(world.getGameTime()); // this.setChanged(world.getGameTime());
} // }
//
this.timesRegistered++; // this.timesRegistered++;
} // }
//
public void unRegister(Level world) { // public void unRegister(Level world) {
assert world == this.trackedWorldSections.world(); // assert world == this.trackedWorldSections.world();
if (--this.timesRegistered > 0) { // if (--this.timesRegistered > 0) {
return; // return;
} // }
assert this.timesRegistered == 0; // assert this.timesRegistered == 0;
//noinspection unchecked // //noinspection unchecked
EntitySectionStorage<E> cache = ((ServerEntityManagerAccessor<E>) ((ServerWorldAccessor) world).getEntityManager()).getSectionStorage(); // EntitySectionStorage<E> cache = ((ServerEntityManagerAccessor<E>) ((ServerWorldAccessor) world).getEntityManager()).getSectionStorage();
((LithiumData) world).lithium$getData().entityMovementTrackers().deleteCanonical(this); // ((LithiumData) world).lithium$getData().entityMovementTrackers().deleteCanonical(this);
//
ArrayList<EntitySection<E>> sections = this.sortedSections; // ArrayList<EntitySection<E>> sections = this.sortedSections;
for (int i = sections.size() - 1; i >= 0; i--) { // for (int i = sections.size() - 1; i >= 0; i--) {
EntitySection<E> section = sections.get(i); // EntitySection<E> section = sections.get(i);
EntityMovementTrackerSection sectionAccess = (EntityMovementTrackerSection) section; // EntityMovementTrackerSection sectionAccess = (EntityMovementTrackerSection) section;
sectionAccess.lithium$removeListener(cache, this); // sectionAccess.lithium$removeListener(cache, this);
if (!this.sectionsNotListeningTo.remove(section)) { // if (!this.sectionsNotListeningTo.remove(section)) {
((EntityMovementTrackerSection) section).lithium$removeListenToMovementOnce(this, this.trackedClass); // ((EntityMovementTrackerSection) section).lithium$removeListenToMovementOnce(this, this.trackedClass);
} // }
} // }
this.setChanged(world.getGameTime()); // this.setChanged(world.getGameTime());
} // }
//
/** // /**
* Register an entity section to this listener, so this listener can look for changes in the section. // * Register an entity section to this listener, so this listener can look for changes in the section.
*/ // */
public void onSectionEnteredRange(EntityMovementTrackerSection section) { // public void onSectionEnteredRange(EntityMovementTrackerSection section) {
this.setChanged(this.trackedWorldSections.world().getGameTime()); // this.setChanged(this.trackedWorldSections.world().getGameTime());
//noinspection SuspiciousMethodCalls // //noinspection SuspiciousMethodCalls
int sectionIndex = this.sortedSections.lastIndexOf(section); // int sectionIndex = this.sortedSections.lastIndexOf(section);
this.sectionVisible[sectionIndex] = true; // this.sectionVisible[sectionIndex] = true;
//
this.sectionsNotListeningTo.add(section); // this.sectionsNotListeningTo.add(section);
this.notifyAllListeners(); // this.notifyAllListeners();
} // }
//
public void onSectionLeftRange(EntityMovementTrackerSection section) { // public void onSectionLeftRange(EntityMovementTrackerSection section) {
this.setChanged(this.trackedWorldSections.world().getGameTime()); // this.setChanged(this.trackedWorldSections.world().getGameTime());
//noinspection SuspiciousMethodCalls // //noinspection SuspiciousMethodCalls
int sectionIndex = this.sortedSections.lastIndexOf(section); // int sectionIndex = this.sortedSections.lastIndexOf(section);
//
this.sectionVisible[sectionIndex] = false; // this.sectionVisible[sectionIndex] = false;
//
if (!this.sectionsNotListeningTo.remove(section)) { // if (!this.sectionsNotListeningTo.remove(section)) {
section.lithium$removeListenToMovementOnce(this, this.trackedClass); // section.lithium$removeListenToMovementOnce(this, this.trackedClass);
this.notifyAllListeners(); // this.notifyAllListeners();
} // }
} // }
//
/** // /**
* Method that marks that new entities might have appeared or moved in the tracked chunk sections. // * Method that marks that new entities might have appeared or moved in the tracked chunk sections.
*/ // */
private void setChanged(long atTime) { // private void setChanged(long atTime) {
if (atTime > this.maxChangeTime) { // if (atTime > this.maxChangeTime) {
this.maxChangeTime = atTime; // this.maxChangeTime = atTime;
} // }
} // }
//
public void listenToEntityMovementOnce(SectionedEntityMovementListener listener) { // public void listenToEntityMovementOnce(SectionedEntityMovementListener listener) {
if (this.sectionedEntityMovementListeners == null) { // if (this.sectionedEntityMovementListeners == null) {
this.sectionedEntityMovementListeners = new ReferenceOpenHashSet<>(); // this.sectionedEntityMovementListeners = new ReferenceOpenHashSet<>();
} // }
this.sectionedEntityMovementListeners.add(listener); // this.sectionedEntityMovementListeners.add(listener);
//
if (!this.sectionsNotListeningTo.isEmpty()) { // if (!this.sectionsNotListeningTo.isEmpty()) {
this.setChanged(this.listenToAllSectionsAndGetMaxChangeTime()); // this.setChanged(this.listenToAllSectionsAndGetMaxChangeTime());
} // }
//
} // }
//
public void emitEntityMovement(int classMask, EntityMovementTrackerSection section) { // public void emitEntityMovement(int classMask, EntityMovementTrackerSection section) {
if ((classMask & (1 << this.trackedClass)) != 0) { // if ((classMask & (1 << this.trackedClass)) != 0) {
this.notifyAllListeners(); // this.notifyAllListeners();
this.sectionsNotListeningTo.add(section); // this.sectionsNotListeningTo.add(section);
} // }
} // }
//
private void notifyAllListeners() { // private void notifyAllListeners() {
ReferenceOpenHashSet<SectionedEntityMovementListener> listeners = this.sectionedEntityMovementListeners; // ReferenceOpenHashSet<SectionedEntityMovementListener> listeners = this.sectionedEntityMovementListeners;
if (listeners != null && !listeners.isEmpty()) { // if (listeners != null && !listeners.isEmpty()) {
for (SectionedEntityMovementListener listener : listeners) { // for (SectionedEntityMovementListener listener : listeners) {
listener.lithium$handleEntityMovement(this.clazz); // listener.lithium$handleEntityMovement(this.clazz);
} // }
listeners.clear(); // listeners.clear();
} // }
} // }
} //}

View File

@@ -94,6 +94,11 @@ public class RandomGeneratorRandom implements BitRandomSource {
return new RandomGeneratorRandom((long) seed.hashCode() ^ this.seed); return new RandomGeneratorRandom((long) seed.hashCode() ^ this.seed);
} }
@Override
public RandomSource fromSeed(long seed) {
return new RandomGeneratorRandom(seed ^ this.seed);
}
/* /*
@Override @Override
public Random split(long seed) { public Random split(long seed) {

View File

@@ -1,55 +1,55 @@
package net.gensokyoreimagined.nitori.common.world; package net.gensokyoreimagined.nitori.common.world;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; //import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; //import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; //import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import net.gensokyoreimagined.nitori.common.entity.block_tracking.ChunkSectionChangeCallback; //import net.gensokyoreimagined.nitori.common.entity.block_tracking.ChunkSectionChangeCallback;
import net.gensokyoreimagined.nitori.common.entity.block_tracking.SectionedBlockChangeTracker; //import net.gensokyoreimagined.nitori.common.entity.block_tracking.SectionedBlockChangeTracker;
import net.gensokyoreimagined.nitori.common.entity.movement_tracker.SectionedEntityMovementTracker; //import net.gensokyoreimagined.nitori.common.entity.movement_tracker.SectionedEntityMovementTracker;
import net.gensokyoreimagined.nitori.common.util.deduplication.LithiumInterner; //import net.gensokyoreimagined.nitori.common.util.deduplication.LithiumInterner;
import net.minecraft.world.entity.ai.navigation.PathNavigation; //import net.minecraft.world.entity.ai.navigation.PathNavigation;
import net.minecraft.world.item.ItemStack; //import net.minecraft.world.item.ItemStack;
import net.minecraft.core.registries.Registries; //import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.raid.Raid; //import net.minecraft.world.entity.raid.Raid;
import net.minecraft.world.level.Level; //import net.minecraft.world.level.Level;
import net.minecraft.world.level.gameevent.GameEventDispatcher; //import net.minecraft.world.level.gameevent.GameEventDispatcher;
import net.minecraft.world.level.gameevent.GameEventListenerRegistry; //import net.minecraft.world.level.gameevent.GameEventListenerRegistry;
//
public interface LithiumData { //public interface LithiumData {
//
record Data( // record Data(
// Map of chunk position -> y section -> game event dispatcher // // 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 // // 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) // // 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. // // All Int2ObjectMap objects are also stored in a field of the corresponding WorldChunk.
Long2ReferenceOpenHashMap<Int2ObjectMap<GameEventDispatcher>> gameEventDispatchersByChunk, // Long2ReferenceOpenHashMap<Int2ObjectMap<GameEventDispatcher>> gameEventDispatchersByChunk,
//
// Cached ominous banner, must not be mutated. // // Cached ominous banner, must not be mutated.
ItemStack ominousBanner, // ItemStack ominousBanner,
//
// Set of active mob navigations (active = have a path) // // Set of active mob navigations (active = have a path)
ReferenceOpenHashSet<PathNavigation> activeNavigations, // ReferenceOpenHashSet<PathNavigation> activeNavigations,
//
// Block change tracker deduplication // // Block change tracker deduplication
LithiumInterner<SectionedBlockChangeTracker> blockChangeTrackers, // LithiumInterner<SectionedBlockChangeTracker> blockChangeTrackers,
//
// Entity movement tracker deduplication // // Entity movement tracker deduplication
LithiumInterner<SectionedEntityMovementTracker<?, ?>> entityMovementTrackers, // LithiumInterner<SectionedEntityMovementTracker<?, ?>> entityMovementTrackers,
//
// Block ChunkSection listeners // // Block ChunkSection listeners
Long2ReferenceOpenHashMap<ChunkSectionChangeCallback> chunkSectionChangeCallbacks // Long2ReferenceOpenHashMap<ChunkSectionChangeCallback> chunkSectionChangeCallbacks
) { // ) {
public Data(Level world) { // public Data(Level world) {
this( // this(
new Long2ReferenceOpenHashMap<>(), // new Long2ReferenceOpenHashMap<>(),
world.registryAccess().lookup(Registries.BANNER_PATTERN).map(Raid::getLeaderBannerInstance).orElse(null), // world.registryAccess().lookup(Registries.BANNER_PATTERN).map(Raid::getLeaderBannerInstance).orElse(null),
new ReferenceOpenHashSet<>(), // new ReferenceOpenHashSet<>(),
new LithiumInterner<>(), // new LithiumInterner<>(),
new LithiumInterner<>(), // new LithiumInterner<>(),
new Long2ReferenceOpenHashMap<>() // new Long2ReferenceOpenHashMap<>()
); // );
} // }
} // }
//
LithiumData.Data lithium$getData(); // LithiumData.Data lithium$getData();
} //}

View File

@@ -2,11 +2,8 @@ package net.gensokyoreimagined.nitori.common.world;
import net.gensokyoreimagined.nitori.common.entity.EntityClassGroup; import net.gensokyoreimagined.nitori.common.entity.EntityClassGroup;
import net.gensokyoreimagined.nitori.common.entity.pushable.EntityPushablePredicate; import net.gensokyoreimagined.nitori.common.entity.pushable.EntityPushablePredicate;
import net.gensokyoreimagined.nitori.mixin.util.accessors.ClientEntityManagerAccessor;
import net.gensokyoreimagined.nitori.mixin.util.accessors.EntityTrackingSectionAccessor; import net.gensokyoreimagined.nitori.mixin.util.accessors.EntityTrackingSectionAccessor;
import net.gensokyoreimagined.nitori.mixin.util.accessors.ServerEntityManagerAccessor;
import net.gensokyoreimagined.nitori.common.world.chunk.ClassGroupFilterableList; import net.gensokyoreimagined.nitori.common.world.chunk.ClassGroupFilterableList;
import net.gensokyoreimagined.nitori.mixin.util.accessors.ServerWorldAccessor;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.ClassInstanceMultiMap; import net.minecraft.util.ClassInstanceMultiMap;
import net.minecraft.util.AbortableIterationConsumer; import net.minecraft.util.AbortableIterationConsumer;

View File

@@ -1,199 +1,199 @@
package net.gensokyoreimagined.nitori.common.world.chunk; package net.gensokyoreimagined.nitori.common.world.chunk;
import com.google.common.collect.ImmutableList; //import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.HashCommon; //import it.unimi.dsi.fastutil.HashCommon;
import it.unimi.dsi.fastutil.objects.Reference2IntMap; //import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; //import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import net.gensokyoreimagined.nitori.mixin.needs_testing.chunk.palette.PaletteResizeAccessor; //import net.gensokyoreimagined.nitori.mixin.needs_testing.chunk.palette.PaletteResizeAccessor;
import net.minecraft.network.FriendlyByteBuf; //import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.VarInt; //import net.minecraft.network.VarInt;
import net.minecraft.core.IdMap; //import net.minecraft.core.IdMap;
import net.minecraft.world.level.chunk.MissingPaletteEntryException; //import net.minecraft.world.level.chunk.MissingPaletteEntryException;
import net.minecraft.world.level.chunk.Palette; //import net.minecraft.world.level.chunk.Palette;
import org.jetbrains.annotations.NotNull; //import org.jetbrains.annotations.NotNull;
//
import java.util.Arrays; //import java.util.Arrays;
import java.util.List; //import java.util.List;
import java.util.function.Predicate; //import java.util.function.Predicate;
//
import static it.unimi.dsi.fastutil.Hash.FAST_LOAD_FACTOR; //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 //* 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. //* {@link LithiumHashPalette#idFor(Object)} through using a faster backing map and reducing pointer chasing.
*/ //*/
public class LithiumHashPalette<T> implements Palette<T> { //public class LithiumHashPalette<T> implements Palette<T> {
private static final int ABSENT_VALUE = -1; // private static final int ABSENT_VALUE = -1;
//
private final IdMap<T> idList; // private final IdMap<T> idList;
// private final PaletteResize<T> resizeHandler; // // private final PaletteResize<T> resizeHandler;
private final PaletteResizeAccessor<T> resizeHandler; // private final PaletteResizeAccessor<T> resizeHandler;
private final int indexBits; // private final int indexBits;
//
private final Reference2IntMap<T> table; // private final Reference2IntMap<T> table;
private T[] entries; // private T[] entries;
private int size = 0; // private int size = 0;
//
public LithiumHashPalette(IdMap<T> idList, PaletteResizeAccessor<T> resizeHandler, int indexBits, T[] entries, Reference2IntMap<T> table, int size) { // public LithiumHashPalette(IdMap<T> idList, PaletteResizeAccessor<T> resizeHandler, int indexBits, T[] entries, Reference2IntMap<T> table, int size) {
this.idList = idList; // this.idList = idList;
this.resizeHandler = resizeHandler; // this.resizeHandler = resizeHandler;
this.indexBits = indexBits; // this.indexBits = indexBits;
this.entries = entries; // this.entries = entries;
this.table = table; // this.table = table;
this.size = size; // this.size = size;
} // }
//
public LithiumHashPalette(IdMap<T> idList, int bits, PaletteResizeAccessor<T> resizeHandler, List<T> list) { // public LithiumHashPalette(IdMap<T> idList, int bits, PaletteResizeAccessor<T> resizeHandler, List<T> list) {
this(idList, bits, resizeHandler); // this(idList, bits, resizeHandler);
//
for (T t : list) { // for (T t : list) {
this.addEntry(t); // this.addEntry(t);
} // }
} // }
//
@SuppressWarnings("unchecked") // @SuppressWarnings("unchecked")
public LithiumHashPalette(IdMap<T> idList, int bits, PaletteResizeAccessor<T> resizeHandler) { // public LithiumHashPalette(IdMap<T> idList, int bits, PaletteResizeAccessor<T> resizeHandler) {
this.idList = idList; // this.idList = idList;
this.indexBits = bits; // this.indexBits = bits;
this.resizeHandler = resizeHandler; // this.resizeHandler = resizeHandler;
//
int capacity = 1 << bits; // int capacity = 1 << bits;
//
this.entries = (T[]) new Object[capacity]; // this.entries = (T[]) new Object[capacity];
this.table = new Reference2IntOpenHashMap<>(capacity, FAST_LOAD_FACTOR); // this.table = new Reference2IntOpenHashMap<>(capacity, FAST_LOAD_FACTOR);
this.table.defaultReturnValue(ABSENT_VALUE); // this.table.defaultReturnValue(ABSENT_VALUE);
} // }
//
@Override // @Override
public int idFor(T obj) { // public int idFor(T obj) {
int id = this.table.getInt(obj); // int id = this.table.getInt(obj);
//
if (id == ABSENT_VALUE) { // if (id == ABSENT_VALUE) {
id = this.computeEntry(obj); // id = this.computeEntry(obj);
} // }
//
return id; // return id;
} // }
//
@Override // @Override
public boolean maybeHas(Predicate<T> predicate) { // public boolean maybeHas(Predicate<T> predicate) {
for (int i = 0; i < this.size; ++i) { // for (int i = 0; i < this.size; ++i) {
if (predicate.test(this.entries[i])) { // if (predicate.test(this.entries[i])) {
return true; // return true;
} // }
} // }
//
return false; // return false;
} // }
//
private int computeEntry(T obj) { // private int computeEntry(T obj) {
int id = this.addEntry(obj); // int id = this.addEntry(obj);
//
if (id >= 1 << this.indexBits) { // if (id >= 1 << this.indexBits) {
if (this.resizeHandler == null) { // if (this.resizeHandler == null) {
throw new IllegalStateException("Cannot grow"); // throw new IllegalStateException("Cannot grow");
} else { // } else {
id = this.resizeHandler.callOnResize(this.indexBits + 1, obj); // id = this.resizeHandler.callOnResize(this.indexBits + 1, obj);
} // }
} // }
//
return id; // return id;
} // }
//
private int addEntry(T obj) { // private int addEntry(T obj) {
int nextId = this.size; // int nextId = this.size;
//
if (nextId >= this.entries.length) { // if (nextId >= this.entries.length) {
this.resize(this.size); // this.resize(this.size);
} // }
//
this.table.put(obj, nextId); // this.table.put(obj, nextId);
this.entries[nextId] = obj; // this.entries[nextId] = obj;
//
this.size++; // this.size++;
//
return nextId; // return nextId;
} // }
//
private void resize(int neededCapacity) { // private void resize(int neededCapacity) {
this.entries = Arrays.copyOf(this.entries, HashCommon.nextPowerOfTwo(neededCapacity + 1)); // this.entries = Arrays.copyOf(this.entries, HashCommon.nextPowerOfTwo(neededCapacity + 1));
} // }
//
@Override // @Override
public @NotNull T valueFor(int id) { // public @NotNull T valueFor(int id) {
T[] entries = this.entries; // T[] entries = this.entries;
//
T entry = null; // T entry = null;
if (id >= 0 && id < entries.length) { // if (id >= 0 && id < entries.length) {
entry = entries[id]; // entry = entries[id];
} // }
//
if (entry != null) { // if (entry != null) {
return entry; // return entry;
} else { // } else {
throw new MissingPaletteEntryException(id); // throw new MissingPaletteEntryException(id);
} // }
} // }
//
@Override // @Override
public void read(FriendlyByteBuf buf) { // public void read(FriendlyByteBuf buf) {
this.clear(); // this.clear();
//
int entryCount = buf.readVarInt(); // int entryCount = buf.readVarInt();
//
for (int i = 0; i < entryCount; ++i) { // for (int i = 0; i < entryCount; ++i) {
this.addEntry(this.idList.byId(buf.readVarInt())); // this.addEntry(this.idList.byId(buf.readVarInt()));
} // }
} // }
//
@Override // @Override
public void write(FriendlyByteBuf buf) { // public void write(FriendlyByteBuf buf) {
int size = this.size; // int size = this.size;
buf.writeVarInt(size); // buf.writeVarInt(size);
//
for (int i = 0; i < size; ++i) { // for (int i = 0; i < size; ++i) {
buf.writeVarInt(this.idList.getId(this.valueFor(i))); // buf.writeVarInt(this.idList.getId(this.valueFor(i)));
} // }
} // }
//
@Override // @Override
public int getSerializedSize() { // public int getSerializedSize() {
int size = VarInt.getByteSize(this.size); // int size = VarInt.getByteSize(this.size);
//
for (int i = 0; i < this.size; ++i) { // for (int i = 0; i < this.size; ++i) {
size += VarInt.getByteSize(this.idList.getId(this.valueFor(i))); // size += VarInt.getByteSize(this.idList.getId(this.valueFor(i)));
} // }
//
return size; // return size;
} // }
//
@Override // @Override
public int getSize() { // public int getSize() {
return this.size; // return this.size;
} // }
//
@Override // @Override
public Palette<T> copy() { // public Palette<T> copy() {
return new LithiumHashPalette<>(this.idList, this.resizeHandler, this.indexBits, this.entries.clone(), new Reference2IntOpenHashMap<>(this.table), this.size); // return new LithiumHashPalette<>(this.idList, this.resizeHandler, this.indexBits, this.entries.clone(), new Reference2IntOpenHashMap<>(this.table), this.size);
} // }
//
private void clear() { // private void clear() {
Arrays.fill(this.entries, null); // Arrays.fill(this.entries, null);
this.table.clear(); // this.table.clear();
this.size = 0; // this.size = 0;
} // }
//
public List<T> getElements() { // public List<T> getElements() {
ImmutableList.Builder<T> builder = new ImmutableList.Builder<>(); // ImmutableList.Builder<T> builder = new ImmutableList.Builder<>();
for (T entry : this.entries) { // for (T entry : this.entries) {
if (entry != null) { // if (entry != null) {
builder.add(entry); // builder.add(entry);
} // }
} // }
return builder.build(); // return builder.build();
} // }
//
public static <A> Palette<A> create(int bits, IdMap<A> idList, PaletteResizeAccessor<A> listener, List<A> list) { // public static <A> Palette<A> create(int bits, IdMap<A> idList, PaletteResizeAccessor<A> listener, List<A> list) {
return new LithiumHashPalette<>(idList, bits, listener, list); // return new LithiumHashPalette<>(idList, bits, listener, list);
} // }
} //}

View File

@@ -14,157 +14,158 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.mixin; 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.Int2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; //import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; //import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import it.unimi.dsi.fastutil.objects.ReferenceSets; //import it.unimi.dsi.fastutil.objects.ReferenceSets;
//import net.gensokyoreimagined.nitori.config.NitoriConfig; ////import net.gensokyoreimagined.nitori.config.NitoriConfig;
import net.gensokyoreimagined.nitori.access.IMixinChunkMapAccess; //import net.gensokyoreimagined.nitori.access.IMixinChunkMapAccess;
import net.gensokyoreimagined.nitori.access.IMixinChunkMap_TrackedEntityAccess; //import net.gensokyoreimagined.nitori.access.IMixinChunkMap_TrackedEntityAccess;
import net.gensokyoreimagined.nitori.compatibility.PluginCompatibilityRegistry; //import net.gensokyoreimagined.nitori.compatibility.PluginCompatibilityRegistry;
import net.gensokyoreimagined.nitori.tracker.MultithreadedTracker; //import net.gensokyoreimagined.nitori.tracker.MultithreadedTracker;
import net.minecraft.server.level.ChunkMap; //import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerEntity; //import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerLevel; //import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; //import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerPlayerConnection; //import net.minecraft.server.network.ServerPlayerConnection;
import net.minecraft.world.entity.Entity; //import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Final; //import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable; //import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow; //import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique; //import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.gen.Accessor; //import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker; //import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At; //import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; //import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect; //import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; //import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//
import java.util.Set; //import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue; //import java.util.Set;
import javax.annotation.Nullable; //import java.util.concurrent.ConcurrentLinkedQueue;
//import javax.annotation.Nullable;
@Mixin(ChunkMap.class) //
public class ChunkMapMixin implements IMixinChunkMapAccess { //@Mixin(ChunkMap.class)
//public class ChunkMapMixin implements IMixinChunkMapAccess {
@Mutable //
@Shadow @Final public Int2ObjectMap<ChunkMap.TrackedEntity> entityMap; // @Mutable
// @Shadow @Final public Int2ObjectMap<ChunkMap.TrackedEntity> entityMap;
// Implementation of 0107-Multithreaded-Tracker.patch //
@Final // // Implementation of 0107-Multithreaded-Tracker.patch
@Shadow // @Final
public ServerLevel level; // @Shadow
// public ServerLevel level;
// Implementation of 0107-Multithreaded-Tracker.patch //
@Unique // // Implementation of 0107-Multithreaded-Tracker.patch
private @Nullable MultithreadedTracker gensouHacks$multithreadedTracker; // @Unique
// private @Nullable MultithreadedTracker gensouHacks$multithreadedTracker;
// Implementation of 0107-Multithreaded-Tracker.patch //
@Final // // Implementation of 0107-Multithreaded-Tracker.patch
@Unique // @Final
private final ConcurrentLinkedQueue<Runnable> gensouHacks$trackerMainThreadTasks = new ConcurrentLinkedQueue<>(); // @Unique
// private final ConcurrentLinkedQueue<Runnable> gensouHacks$trackerMainThreadTasks = new ConcurrentLinkedQueue<>();
// Implementation of 0107-Multithreaded-Tracker.patch //
@Unique // // Implementation of 0107-Multithreaded-Tracker.patch
private boolean gensouHacks$tracking = false; // @Unique
// private boolean gensouHacks$tracking = false;
@Inject(method = "<init>", at = @At("RETURN")) //
private void reassignEntityTrackers(CallbackInfo ci) { // @Inject(method = "<init>", at = @At("RETURN"))
this.entityMap = new Int2ObjectLinkedOpenHashMap<>(); // private void reassignEntityTrackers(CallbackInfo ci) {
} // this.entityMap = new Int2ObjectLinkedOpenHashMap<>();
// }
// Implementation of 0107-Multithreaded-Tracker.patch //
@Override // // Implementation of 0107-Multithreaded-Tracker.patch
@Unique // @Override
public void gensouHacks$runOnTrackerMainThread(final Runnable runnable) { // @Unique
if (this.gensouHacks$tracking) { // public void gensouHacks$runOnTrackerMainThread(final Runnable runnable) {
this.gensouHacks$trackerMainThreadTasks.add(runnable); // if (this.gensouHacks$tracking) {
} else { // this.gensouHacks$trackerMainThreadTasks.add(runnable);
runnable.run(); // } else {
} // runnable.run();
} // }
// }
@Inject(method = "processTrackQueue", at = @At("HEAD"), cancellable = true) //
private void atProcessTrackQueueHead(CallbackInfo callbackInfo) { // @Inject(method = "newTrackerTick", at = @At("HEAD"), cancellable = true)
// Implementation of 0107-Multithreaded-Tracker.patch // private void atProcessTrackQueueHead(CallbackInfo callbackInfo) {
//TODO: Restore config condition // // Implementation of 0107-Multithreaded-Tracker.patch
//if (NitoriConfig.enableAsyncEntityTracker) { // //TODO: Restore config condition
if (this.gensouHacks$multithreadedTracker == null) { // //if (NitoriConfig.enableAsyncEntityTracker) {
this.gensouHacks$multithreadedTracker = new MultithreadedTracker(this.level.chunkSource.entityTickingChunks, this.gensouHacks$trackerMainThreadTasks); // 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$tracking = true;
this.gensouHacks$multithreadedTracker.tick(); // try {
} finally { // this.gensouHacks$multithreadedTracker.tick();
this.gensouHacks$tracking = false; // } finally {
} // this.gensouHacks$tracking = false;
callbackInfo.cancel(); // }
//} // callbackInfo.cancel();
// Mirai end // //}
} // // Mirai end
// }
@Mixin(ChunkMap.TrackedEntity.class) //
public static abstract class TrackedEntity implements IMixinChunkMap_TrackedEntityAccess { // @Mixin(ChunkMap.TrackedEntity.class)
// Implementation of 0107-Multithreaded-Tracker.patch // public static abstract class TrackedEntity implements IMixinChunkMap_TrackedEntityAccess {
@Override // // Implementation of 0107-Multithreaded-Tracker.patch
@Final // @Override
@Accessor // @Final
public abstract Entity getEntity(); // Mirai -> public // @Accessor
// public abstract Entity getEntity(); // Mirai -> public
@Final //
@Mutable // @Final
@Shadow // @Mutable
public Set<ServerPlayerConnection> seenBy; // @Shadow
// public Set<ServerPlayerConnection> seenBy;
@Shadow //
public abstract void updatePlayer(ServerPlayer player); // @Shadow
// public abstract void updatePlayer(ServerPlayer player);
@Inject(method = "<init>", at = @At("RETURN")) //
private void reassignSeenBy(CallbackInfo ci) { // @Inject(method = "<init>", at = @At("RETURN"))
// Implementation of 0107-Multithreaded-Tracker.patch // private void reassignSeenBy(CallbackInfo ci) {
this.seenBy = ReferenceSets.synchronize(new ReferenceOpenHashSet<>()); // Mirai - sync // // Implementation of 0107-Multithreaded-Tracker.patch
} // this.seenBy = ReferenceSets.synchronize(new ReferenceOpenHashSet<>()); // Mirai - sync
// }
// Implementation of 0107-Multithreaded-Tracker.patch //
@Override // // Implementation of 0107-Multithreaded-Tracker.patch
@Final // @Override
@Invoker // @Final
public abstract void callUpdatePlayers(PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> newTrackerCandidates); // Mirai -> public // @Invoker
// public abstract void callUpdatePlayers(List<ServerPlayer> 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")) //
private void handleCitizensPluginTracking(ChunkMap.TrackedEntity self, ServerPlayer serverPlayer) { // @Redirect(method = "updatePlayers", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkMap$TrackedEntity;updatePlayer(Lnet/minecraft/server/level/ServerPlayer;)V"))
// Nitori - Citizens tracker must run on the main thread to avoid cyclic wait // private void handleCitizensPluginTracking(ChunkMap.TrackedEntity self, ServerPlayer serverPlayer) {
if (PluginCompatibilityRegistry.CITIZENS.shouldRedirectToMainThread(self, serverPlayer)) { // // Nitori - Citizens tracker must run on the main thread to avoid cyclic wait
((IMixinChunkMapAccess) (Object) ((ServerLevel) serverPlayer.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> // if (PluginCompatibilityRegistry.CITIZENS.shouldRedirectToMainThread(self, serverPlayer)) {
this.updatePlayer(serverPlayer) // ((IMixinChunkMapAccess) (Object) ((ServerLevel) serverPlayer.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() ->
); // this.updatePlayer(serverPlayer)
} else { // );
this.updatePlayer(serverPlayer); // } else {
} // this.updatePlayer(serverPlayer);
} // }
// }
// Implementation of 0107-Multithreaded-Tracker.patch //
@SuppressWarnings("EmptyMethod") // // Implementation of 0107-Multithreaded-Tracker.patch
@Redirect(method = "removePlayer", at = @At(value = "INVOKE", target = "Lorg/spigotmc/AsyncCatcher;catchOp(Ljava/lang/String;)V")) // @SuppressWarnings("EmptyMethod")
private void skipSpigotAsyncPlayerTrackerClear(String reason) {} // Mirai - we can remove async too // @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") // // Implementation of 0107-Multithreaded-Tracker.patch
@Redirect(method = "updatePlayer", at = @At(value = "INVOKE", target = "Lorg/spigotmc/AsyncCatcher;catchOp(Ljava/lang/String;)V")) // @SuppressWarnings("EmptyMethod")
private void skipSpigotAsyncPlayerTrackerUpdate(String reason) {} // Mirai - we can update async // @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) { // @Redirect(method = "updatePlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerEntity;addPairing(Lnet/minecraft/server/level/ServerPlayer;)V"))
if (PluginCompatibilityRegistry.TRAIN_CARTS.shouldRedirectToMainThread((ChunkMap.TrackedEntity) (Object) this)) { // private void handleTrainCartsPluginAddPairing(ServerEntity self, ServerPlayer serverPlayer) {
((IMixinChunkMapAccess) (Object) ((ServerLevel) serverPlayer.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> // if (PluginCompatibilityRegistry.TRAIN_CARTS.shouldRedirectToMainThread((ChunkMap.TrackedEntity) (Object) this)) {
self.addPairing(serverPlayer) // ((IMixinChunkMapAccess) (Object) ((ServerLevel) serverPlayer.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() ->
); // self.addPairing(serverPlayer)
} else { // );
self.addPairing(serverPlayer); // } else {
} // self.addPairing(serverPlayer);
} // }
} // }
} // }
//}

View File

@@ -14,8 +14,8 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.mixin; package net.gensokyoreimagined.nitori.mixin;
import com.destroystokyo.paper.util.maplist.EntityList; import ca.spottedleaf.moonrise.common.list.EntityList;
import io.papermc.paper.world.ChunkEntitySlices; import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices;
import net.gensokyoreimagined.nitori.access.IMixinChunkEntitySlicesAccess; import net.gensokyoreimagined.nitori.access.IMixinChunkEntitySlicesAccess;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;

View File

@@ -14,7 +14,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.mixin; 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 net.gensokyoreimagined.nitori.access.IMixinIteratorSafeOrderedReferenceSetAccess;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Accessor;

View File

@@ -14,116 +14,116 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.mixin; package net.gensokyoreimagined.nitori.mixin;
import com.google.common.collect.Lists; //import com.google.common.collect.Lists;
import com.llamalad7.mixinextras.sugar.Local; //import com.llamalad7.mixinextras.sugar.Local;
import net.gensokyoreimagined.nitori.access.IMixinChunkMapAccess; //import net.gensokyoreimagined.nitori.access.IMixinChunkMapAccess;
import net.minecraft.network.protocol.Packet; //import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener; //import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBundlePacket; //import net.minecraft.network.protocol.game.ClientboundBundlePacket;
import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket; //import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; //import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket; //import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket;
import net.minecraft.network.syncher.SynchedEntityData; //import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerEntity; //import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerLevel; //import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; //import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerGamePacketListenerImpl; //import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.world.entity.Entity; //import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.ai.attributes.AttributeInstance; //import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import org.objectweb.asm.Opcodes; //import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Final; //import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; //import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; //import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; //import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect; //import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; //import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; //import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
//
import java.util.List; //import java.util.List;
import java.util.Set; //import java.util.Set;
import java.util.function.Consumer; //import java.util.function.Consumer;
//
@Mixin(ServerEntity.class) //@Mixin(ServerEntity.class)
public abstract class MixinServerEntity { //public abstract class MixinServerEntity {
@Final // @Final
@Shadow // @Shadow
private Entity entity; // private Entity entity;
//
@Shadow // @Shadow
public void sendPairingData(ServerPlayer serverplayer, Consumer<Packet<ClientGamePacketListener>> consumer) { // public void sendPairingData(ServerPlayer serverplayer, Consumer<Packet<ClientGamePacketListener>> consumer) {
throw new AssertionError("Mixin failed to apply!"); // throw new AssertionError("Mixin failed to apply!");
} // }
//
// Implementation of 0107-Multithreaded-Tracker.patch // // Implementation of 0107-Multithreaded-Tracker.patch
@SuppressWarnings("EmptyMethod") // @SuppressWarnings("EmptyMethod")
@Redirect(method = "removePairing", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V")) // @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) {} // private void skipSendForOriginalRemovePairing(ServerGamePacketListenerImpl self, Packet<?> packet) {}
//
// Implementation of 0107-Multithreaded-Tracker.patch // // Implementation of 0107-Multithreaded-Tracker.patch
@Inject(method = "removePairing", at = @At(value = "TAIL")) // @Inject(method = "removePairing", at = @At(value = "TAIL"))
private void invokeRemovePairingSendOnMain(ServerPlayer serverplayer, CallbackInfo callbackInfo) { // private void invokeRemovePairingSendOnMain(ServerPlayer serverplayer, CallbackInfo callbackInfo) {
// Mirai start - ensure main thread // // Mirai start - ensure main thread
((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> // ((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() ->
serverplayer.connection.send(new ClientboundRemoveEntitiesPacket(this.entity.getId())) // serverplayer.connection.send(new ClientboundRemoveEntitiesPacket(this.entity.getId()))
); // );
// Mirai end // // Mirai end
} // }
//
// Implementation of 0107-Multithreaded-Tracker.patch // // Implementation of 0107-Multithreaded-Tracker.patch
@SuppressWarnings("EmptyMethod") // @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")) // @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<Packet<ClientGamePacketListener>> consumer) {} // private void skipSendPrepForOriginalAddPairing(ServerEntity self, ServerPlayer serverplayer, Consumer<Packet<ClientGamePacketListener>> consumer) {}
//
// Implementation of 0107-Multithreaded-Tracker.patch // // Implementation of 0107-Multithreaded-Tracker.patch
@SuppressWarnings("EmptyMethod") // @SuppressWarnings("EmptyMethod")
@Redirect(method = "addPairing", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V")) // @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) {} // private void skipSendForOriginalAddPairing(ServerGamePacketListenerImpl self, Packet<?> packet) {}
//
// Implementation of 0107-Multithreaded-Tracker.patch // // 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)) // @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<Packet<? super ClientGamePacketListener>> list) { // private void invokeAddPairingSendOnMain(ServerPlayer serverplayer, CallbackInfo callbackInfo, @Local List<Packet<? super ClientGamePacketListener>> list) {
((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> { // Mirai - main thread // ((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> { // Mirai - main thread
this.sendPairingData(serverplayer, list::add); // this.sendPairingData(serverplayer, list::add);
serverplayer.connection.send(new ClientboundBundlePacket(list)); // serverplayer.connection.send(new ClientboundBundlePacket(list));
}); // });
} // }
//
// Implementation of 0107-Multithreaded-Tracker.patch // // Implementation of 0107-Multithreaded-Tracker.patch
@SuppressWarnings("EmptyMethod") // @SuppressWarnings("EmptyMethod")
@Redirect(method = "sendDirtyEntityData", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerEntity;broadcastAndSend(Lnet/minecraft/network/protocol/Packet;)V")) // @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) {} // private void skipTrasmitForNonDefault(ServerEntity self, Packet<?> packet) {}
//
// Implementation of 0107-Multithreaded-Tracker.patch // // 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)) // @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<SynchedEntityData.DataValue<?>> list) { // private void invokeSendForGenericDirtyEntityDataOnMain(CallbackInfo callbackInfo, @Local SynchedEntityData synchedentitydata, @Local List<SynchedEntityData.DataValue<?>> list) {
// Mirai start - sync // // Mirai start - sync
((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> // ((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() ->
this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), list)) // this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), list))
); // );
// Mirai end // // Mirai end
} // }
//
// stubbing of broadcastAndSend in if (this.entity instanceof LivingEntity) handled in skipTrasmitForNonDefault // // stubbing of broadcastAndSend in if (this.entity instanceof LivingEntity) handled in skipTrasmitForNonDefault
//
// Implementation of 0107-Multithreaded-Tracker.patch // // 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)) // @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<AttributeInstance> set) { // private void invokeSendForLivingDirtyEntityDataOnMain(CallbackInfo callbackInfo, @Local Set<AttributeInstance> set) {
// Mirai start - sync // // Mirai start - sync
final var copy = Lists.newArrayList(set); // final var copy = Lists.newArrayList(set);
((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> { // ((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> {
// CraftBukkit start - Send scaled max health // // CraftBukkit start - Send scaled max health
if (this.entity instanceof ServerPlayer) { // if (this.entity instanceof ServerPlayer) {
((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(copy, false); // ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(copy, false);
} // }
// CraftBukkit end // // CraftBukkit end
this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), copy)); // this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), copy));
}); // });
// Mirai end // // Mirai end
} // }
//
@Shadow // @Shadow
private void broadcastAndSend(Packet<?> packet) { // private void broadcastAndSend(Packet<?> packet) {
throw new AssertionError("Mixin failed to apply!"); // throw new AssertionError("Mixin failed to apply!");
} // }
} //}

View File

@@ -27,38 +27,38 @@ import org.spongepowered.asm.mixin.injection.Redirect;
// Taken from Lithium // 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 // 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) //@Mixin(ServerLevel.class)
public abstract class MixinServerWorld { //public abstract class MixinServerWorld {
@Unique // @Unique
private final BlockPos.MutableBlockPos nitori$randomPosInChunkCachedPos = new BlockPos.MutableBlockPos(); // private final BlockPos.MutableBlockPos nitori$randomPosInChunkCachedPos = new BlockPos.MutableBlockPos();
//
/** // /**
* @reason Avoid allocating BlockPos every invocation through using our allocation-free variant // * @reason Avoid allocating BlockPos every invocation through using our allocation-free variant
*/ // */
@Redirect( // @Redirect(
method = "tickChunk", // method = "tickChunk",
at = @At( // at = @At(
value = "INVOKE", // value = "INVOKE",
target = "Lnet/minecraft/server/level/ServerLevel;getBlockRandomPos(IIII)Lnet/minecraft/core/BlockPos;" // 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) { // private BlockPos redirectTickGetRandomPosInChunk(ServerLevel serverWorld, int x, int y, int z, int mask) {
((ChunkRandomSource) serverWorld).nitori$getRandomPosInChunk(x, y, z, mask, this.nitori$randomPosInChunkCachedPos); // ((ChunkRandomSource) serverWorld).nitori$getRandomPosInChunk(x, y, z, mask, this.nitori$randomPosInChunkCachedPos);
//
return this.nitori$randomPosInChunkCachedPos; // return this.nitori$randomPosInChunkCachedPos;
} // }
//
/** // /**
* @reason Ensure an immutable block position is passed on block tick // * @reason Ensure an immutable block position is passed on block tick
*/ // */
@Redirect( // @Redirect(
method = "tickChunk", // method = "tickChunk",
at = @At( // at = @At(
value = "INVOKE", // 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" // 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) { // private void redirectBlockStateTick(BlockState blockState, ServerLevel world, BlockPos pos, RandomSource rand) {
blockState.randomTick(world, pos.immutable(), rand); // blockState.randomTick(world, pos.immutable(), rand);
} // }
} //}

View File

@@ -14,20 +14,20 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.mixin; package net.gensokyoreimagined.nitori.mixin;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; //import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; //import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; //import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
//
@Mixin(targets = "gg.pufferfish.pufferfish.simd.SIMDDetection") //@Mixin(targets = "gg.pufferfish.pufferfish.simd.SIMDDetection")
public abstract class MixinSpongeSIMD { //public abstract class MixinSpongeSIMD {
@Inject(method = "getJavaVersion", at = @At("RETURN"), cancellable = true) // @Inject(method = "getJavaVersion", at = @At("RETURN"), cancellable = true)
private static void loadPufferfishConfig(CallbackInfoReturnable<Integer> callback) { // private static void loadPufferfishConfig(CallbackInfoReturnable<Integer> callback) {
// We troll the Pufferfish developers by changing the return value of the method // // 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"); // // System.out.println("Thought that it was " + callback.getReturnValue() + " for java version");
if (callback.getReturnValue() == 21) { // if (callback.getReturnValue() == 21) {
System.out.println("Successfully trolled Pufferfish into thinking we're on Java 19!"); // System.out.println("Successfully trolled Pufferfish into thinking we're on Java 19!");
callback.setReturnValue(19); // callback.setReturnValue(19);
} // }
} // }
} //}

View File

@@ -33,50 +33,50 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List; import java.util.List;
@Mixin(WorldGenRegion.class) //@Mixin(WorldGenRegion.class)
public class MixinWorldGenRegion { //public class MixinWorldGenRegion {
@Shadow @Final private ChunkPos firstPos; // @Shadow @Final private ChunkPos firstPos;
@Shadow @Final private int size; // @Shadow @Final private int size;
//
@Unique // @Unique
private ChunkAccess[] gensouHacks$chunksArr; // private ChunkAccess[] gensouHacks$chunksArr;
@Unique // @Unique
private int gensouHacks$minChunkX; // private int gensouHacks$minChunkX;
@Unique // @Unique
private int gensouHacks$minChunkZ; // private int gensouHacks$minChunkZ;
//
@Inject(method = "<init>", at = @At("RETURN")) // @Inject(method = "<init>", at = @At("RETURN"))
private void onInit(ServerLevel world, List<ChunkAccess> chunks, ChunkStatus status, int placementRadius, CallbackInfo ci) { // private void onInit(ServerLevel world, List<ChunkAccess> chunks, ChunkStatus status, int placementRadius, CallbackInfo ci) {
this.gensouHacks$minChunkX = this.firstPos.x; // this.gensouHacks$minChunkX = this.firstPos.x;
this.gensouHacks$minChunkZ = this.firstPos.z; // this.gensouHacks$minChunkZ = this.firstPos.z;
this.gensouHacks$chunksArr = chunks.toArray(new ChunkAccess[0]); // this.gensouHacks$chunksArr = chunks.toArray(new ChunkAccess[0]);
} // }
//
@Inject(method = "getChunk(II)Lnet/minecraft/world/level/chunk/ChunkAccess;", at = @At("HEAD"), cancellable = true) // @Inject(method = "getChunk(II)Lnet/minecraft/world/level/chunk/ChunkAccess;", at = @At("HEAD"), cancellable = true)
public void getChunk(int chunkX, int chunkZ, CallbackInfoReturnable<ChunkAccess> cir) { // public void getChunk(int chunkX, int chunkZ, CallbackInfoReturnable<ChunkAccess> cir) {
int x = chunkX - this.gensouHacks$minChunkX; // int x = chunkX - this.gensouHacks$minChunkX;
int z = chunkZ - this.gensouHacks$minChunkZ; // int z = chunkZ - this.gensouHacks$minChunkZ;
int w = this.size; // int w = this.size;
//
if (x >= 0 && z >= 0 && x < w && z < w) { // if (x >= 0 && z >= 0 && x < w && z < w) {
cir.setReturnValue(this.gensouHacks$chunksArr[x + z * w]); // cir.setReturnValue(this.gensouHacks$chunksArr[x + z * w]);
cir.cancel(); // cir.cancel();
} else { // } else {
throw new NullPointerException("No chunk exists at " + new ChunkPos(chunkX, chunkZ)); // throw new NullPointerException("No chunk exists at " + new ChunkPos(chunkX, chunkZ));
} // }
} // }
//
@Inject(method = "getBlockState", at = @At("HEAD"), cancellable = true) // @Inject(method = "getBlockState", at = @At("HEAD"), cancellable = true)
public void getBlockState(BlockPos pos, CallbackInfoReturnable<BlockState> cir) { // public void getBlockState(BlockPos pos, CallbackInfoReturnable<BlockState> cir) {
int x = (Pos.ChunkCoord.fromBlockCoord(pos.getX())) - this.gensouHacks$minChunkX; // int x = (Pos.ChunkCoord.fromBlockCoord(pos.getX())) - this.gensouHacks$minChunkX;
int z = (Pos.ChunkCoord.fromBlockCoord(pos.getZ())) - this.gensouHacks$minChunkZ; // int z = (Pos.ChunkCoord.fromBlockCoord(pos.getZ())) - this.gensouHacks$minChunkZ;
int w = this.size; // int w = this.size;
//
if (x >= 0 && z >= 0 && x < w && z < w) { // if (x >= 0 && z >= 0 && x < w && z < w) {
cir.setReturnValue(this.gensouHacks$chunksArr[x + z * w].getBlockState(pos)); // cir.setReturnValue(this.gensouHacks$chunksArr[x + z * w].getBlockState(pos));
cir.cancel(); // cir.cancel();
} else { // } else {
throw new NullPointerException("No chunk exists at " + new ChunkPos(pos)); // throw new NullPointerException("No chunk exists at " + new ChunkPos(pos));
} // }
} // }
} //}

View File

@@ -1,46 +1,46 @@
package net.gensokyoreimagined.nitori.mixin.alloc.chunk_random; package net.gensokyoreimagined.nitori.mixin.alloc.chunk_random;
import net.gensokyoreimagined.nitori.common.world.ChunkRandomSource; //import net.gensokyoreimagined.nitori.common.world.ChunkRandomSource;
import net.minecraft.world.level.block.state.BlockState; //import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.server.level.ServerLevel; //import net.minecraft.server.level.ServerLevel;
import net.minecraft.core.BlockPos; //import net.minecraft.core.BlockPos;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; //import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; //import org.spongepowered.asm.mixin.injection.Redirect;
//
@Mixin(ServerLevel.class) //@Mixin(ServerLevel.class)
public abstract class ServerWorldMixin { //public abstract class ServerWorldMixin {
private final BlockPos.MutableBlockPos nitori$randomPosInChunkCachedPos = new BlockPos.MutableBlockPos(); // private final BlockPos.MutableBlockPos nitori$randomPosInChunkCachedPos = new BlockPos.MutableBlockPos();
//
/** // /**
* @reason Avoid allocating BlockPos every invocation through using our allocation-free variant // * @reason Avoid allocating BlockPos every invocation through using our allocation-free variant
*/ // */
@Redirect( // @Redirect(
method = "tickChunk", // method = "tickChunk",
at = @At( // at = @At(
value = "INVOKE", // value = "INVOKE",
target = "Lnet/minecraft/server/level/ServerLevel;getBlockRandomPos(IIII)Lnet/minecraft/core/BlockPos;" // 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) { // private BlockPos redirectTickGetRandomPosInChunk(ServerLevel serverWorld, int x, int y, int z, int mask) {
((ChunkRandomSource) serverWorld).nitori$getRandomPosInChunk(x, y, z, mask, this.nitori$randomPosInChunkCachedPos); // ((ChunkRandomSource) serverWorld).nitori$getRandomPosInChunk(x, y, z, mask, this.nitori$randomPosInChunkCachedPos);
//
return this.nitori$randomPosInChunkCachedPos; // return this.nitori$randomPosInChunkCachedPos;
} // }
//
/** // /**
* @reason Ensure an immutable block position is passed on block tick // * @reason Ensure an immutable block position is passed on block tick
*/ // */
@Redirect( // @Redirect(
method = "tickChunk", // method = "tickChunk",
at = @At( // at = @At(
value = "INVOKE", // 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" // 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, net.minecraft.util.RandomSource rand) { // private void redirectBlockStateTick(BlockState blockState, ServerLevel world, BlockPos pos, net.minecraft.util.RandomSource rand) {
blockState.randomTick(world, pos.immutable(), rand); // blockState.randomTick(world, pos.immutable(), rand);
} // }
// /** // /**
// * @reason Ensure an immutable block position is passed on fluid tick // * @reason Ensure an immutable block position is passed on fluid tick
@@ -55,6 +55,6 @@ public abstract class ServerWorldMixin {
// private void redirectFluidStateTick(FluidState fluidState, ServerLevel world, BlockPos pos, net.minecraft.util.RandomSource rand) { // private void redirectFluidStateTick(FluidState fluidState, ServerLevel world, BlockPos pos, net.minecraft.util.RandomSource rand) {
// fluidState.randomTick(world, pos.immutable(), rand); // fluidState.randomTick(world, pos.immutable(), rand);
// } // }
} //}
// couldn't figure it out.... // couldn't figure it out....

View File

@@ -14,40 +14,40 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.mixin.alloc.chunk_ticking; package net.gensokyoreimagined.nitori.mixin.alloc.chunk_ticking;
import net.minecraft.server.level.ChunkHolder; //import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerChunkCache; //import net.minecraft.server.level.ServerChunkCache;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; //import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; //import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect; //import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; //import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//
import java.util.ArrayList; //import java.util.ArrayList;
import java.util.function.BooleanSupplier; //import java.util.function.BooleanSupplier;
//
@Mixin(ServerChunkCache.class) //@Mixin(ServerChunkCache.class)
public class ServerChunkManagerMixin { //public class ServerChunkManagerMixin {
private final ArrayList<ChunkHolder> cachedChunkList = new ArrayList<>(); // private final ArrayList<ChunkHolder> cachedChunkList = new ArrayList<>();
//
@Redirect( // @Redirect(
method = "tickChunks()V", // method = "tickChunks",
at = @At( // at = @At(
value = "INVOKE", // value = "INVOKE",
target = "Lcom/google/common/collect/Lists;newArrayListWithCapacity(I)Ljava/util/ArrayList;", // target = "Lcom/google/common/collect/Lists;newArrayListWithCapacity(I)Ljava/util/ArrayList;",
remap = false // remap = false
) // )
) // )
private ArrayList<ChunkHolder> redirectChunksListClone(int initialArraySize) { // private ArrayList<ChunkHolder> redirectChunksListClone(int initialArraySize) {
ArrayList<ChunkHolder> list = this.cachedChunkList; // ArrayList<ChunkHolder> list = this.cachedChunkList;
list.clear(); // Ensure the list is empty before re-using it // list.clear(); // Ensure the list is empty before re-using it
list.ensureCapacity(initialArraySize); // list.ensureCapacity(initialArraySize);
//
return list; // return list;
} // }
//
@Inject(method = "tick(Ljava/util/function/BooleanSupplier;Z)V", at = @At("HEAD")) // @Inject(method = "tick(Ljava/util/function/BooleanSupplier;Z)V", at = @At("HEAD"))
private void preTick(BooleanSupplier shouldKeepTicking, boolean tickChunks, CallbackInfo ci) { // private void preTick(BooleanSupplier shouldKeepTicking, boolean tickChunks, CallbackInfo ci) {
// Ensure references aren't leaked through this list // // Ensure references aren't leaked through this list
this.cachedChunkList.clear(); // this.cachedChunkList.clear();
} // }
} //}

View File

@@ -1,40 +1,40 @@
package net.gensokyoreimagined.nitori.mixin.collections.attributes; package net.gensokyoreimagined.nitori.mixin.collections.attributes;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; //import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; //import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import net.minecraft.world.entity.ai.attributes.AttributeMap; //import net.minecraft.world.entity.ai.attributes.AttributeMap;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier; //import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.ai.attributes.Attribute; //import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.AttributeInstance; //import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import org.spongepowered.asm.mixin.Final; //import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable; //import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow; //import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; //import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; //import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; //import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//
import java.util.Map; //import java.util.Map;
import java.util.Set; //import java.util.Set;
//
@Mixin(AttributeMap.class) //@Mixin(AttributeMap.class)
public class AttributeContainerMixin { //public class AttributeContainerMixin {
@Mutable // @Mutable
@Shadow // @Shadow
@Final // @Final
private Map<Attribute, AttributeInstance> attributes; // private Map<Attribute, AttributeInstance> attributes;
//
@Mutable // @Mutable
@Shadow // @Shadow
@Final // @Final
private Set<AttributeInstance> dirtyAttributes; // private Set<AttributeInstance> attributesToSync;
//
@Inject( // @Inject(
method = "<init>", // method = "<init>",
at = @At("RETURN") // at = @At("RETURN")
) // )
private void initCollections(AttributeSupplier defaultAttributes, CallbackInfo ci) { // private void initCollections(AttributeSupplier defaultAttributes, CallbackInfo ci) {
this.attributes = new Reference2ReferenceOpenHashMap<>(0); // this.attributes = new Reference2ReferenceOpenHashMap<>(0);
this.dirtyAttributes = new ReferenceOpenHashSet<>(0); // this.attributesToSync = new ReferenceOpenHashSet<>(0);
} // }
} //}

View File

@@ -1,29 +1,29 @@
package net.gensokyoreimagined.nitori.mixin.logic.recipe_manager; package net.gensokyoreimagined.nitori.mixin.logic.recipe_manager;
import net.minecraft.world.Container; //import net.minecraft.world.Container;
import net.minecraft.world.item.crafting.Recipe; //import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeHolder; //import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeManager; //import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.item.crafting.RecipeType; //import net.minecraft.world.item.crafting.RecipeType;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite; //import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow; //import org.spongepowered.asm.mixin.Shadow;
//
import java.util.ArrayList; //import java.util.ArrayList;
import java.util.Collection; //import java.util.Collection;
import java.util.List; //import java.util.List;
import java.util.Map; //import java.util.Map;
@Mixin(RecipeManager.class) //@Mixin(RecipeManager.class)
public abstract class RecipeManagerMixin { //public abstract class RecipeManagerMixin {
//
@Shadow protected abstract <C extends Container, T extends Recipe<C>> Collection<RecipeHolder<T>> byType(RecipeType<T> type); // @Shadow protected abstract <C extends Container, T extends Recipe<C>> Collection<RecipeHolder<T>> byType(RecipeType<T> type);
//
/** // /**
* @author QPCrummer & Leaf Patch #0023 // * @author QPCrummer & Leaf Patch #0023
* @reason Optimize RecipeManager List Creation // * @reason Optimize RecipeManager List Creation
*/ // */
@Overwrite // @Overwrite
public <C extends Container, T extends Recipe<C>> List<RecipeHolder<T>> getAllRecipesFor(RecipeType<T> type) { // public <C extends Container, T extends Recipe<C>> List<RecipeHolder<T>> getAllRecipesFor(RecipeType<T> type) {
return new ArrayList<>(this.byType(type)); // return new ArrayList<>(this.byType(type));
} // }
} //}

View File

@@ -1,20 +1,20 @@
package net.gensokyoreimagined.nitori.mixin.math.random.creation; package net.gensokyoreimagined.nitori.mixin.math.random.creation;
import net.minecraft.server.level.ServerPlayer; //import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.ServerLevel; //import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource; //import net.minecraft.util.RandomSource;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; //import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; //import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; //import org.spongepowered.asm.mixin.injection.Redirect;
//
@Mixin(ServerPlayer.class) //@Mixin(ServerPlayer.class)
public abstract class ServerPlayerEntityRandomMixin { //public abstract class ServerPlayerEntityRandomMixin {
//
@Shadow public abstract ServerLevel serverLevel(); // @Shadow public abstract ServerLevel serverLevel();
//
@Redirect(method = "fudgeSpawnLocation", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/RandomSource;create()Lnet/minecraft/util/RandomSource;")) // @Redirect(method = "fudgeSpawnLocation", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/RandomSource;create()Lnet/minecraft/util/RandomSource;"))
private RandomSource redirectCreatedRandom() { // private RandomSource redirectCreatedRandom() {
return serverLevel().random; // return serverLevel().random;
} // }
} //}

View File

@@ -0,0 +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<BlockState> 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<BlockState> palettedContainer, PalettedContainer.Counter<BlockState> 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/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<BlockState> 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;
// }
// }
//}

View File

@@ -1,13 +1,13 @@
package net.gensokyoreimagined.nitori.mixin.util.accessors; package net.gensokyoreimagined.nitori.mixin.util.accessors;
import net.minecraft.world.level.entity.EntityAccess; //import net.minecraft.world.level.entity.EntityAccess;
import net.minecraft.world.level.entity.EntitySectionStorage; //import net.minecraft.world.level.entity.EntitySectionStorage;
import net.minecraft.world.level.entity.TransientEntitySectionManager; //import net.minecraft.world.level.entity.TransientEntitySectionManager;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor; //import org.spongepowered.asm.mixin.gen.Accessor;
//
@Mixin(TransientEntitySectionManager.class) //@Mixin(TransientEntitySectionManager.class)
public interface ClientEntityManagerAccessor<T extends EntityAccess> { //public interface ClientEntityManagerAccessor<T extends EntityAccess> {
@Accessor // @Accessor
EntitySectionStorage<T> getSectionStorage(); // EntitySectionStorage<T> getSectionStorage();
} //}

View File

@@ -1,13 +1,13 @@
package net.gensokyoreimagined.nitori.mixin.util.accessors; package net.gensokyoreimagined.nitori.mixin.util.accessors;
import net.minecraft.world.level.entity.EntityAccess; //import net.minecraft.world.level.entity.EntityAccess;
import net.minecraft.world.level.entity.EntitySectionStorage; //import net.minecraft.world.level.entity.EntitySectionStorage;
import net.minecraft.world.level.entity.PersistentEntitySectionManager; //import net.minecraft.world.level.entity.PersistentEntitySectionManager;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor; //import org.spongepowered.asm.mixin.gen.Accessor;
//
@Mixin(PersistentEntitySectionManager.class) //@Mixin(PersistentEntitySectionManager.class)
public interface ServerEntityManagerAccessor<T extends EntityAccess> { //public interface ServerEntityManagerAccessor<T extends EntityAccess> {
@Accessor // @Accessor
EntitySectionStorage<T> getSectionStorage(); // EntitySectionStorage<T> getSectionStorage();
} //}

View File

@@ -1,14 +1,14 @@
package net.gensokyoreimagined.nitori.mixin.util.accessors; package net.gensokyoreimagined.nitori.mixin.util.accessors;
import net.minecraft.server.level.ServerLevel; //import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity; //import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.entity.PersistentEntitySectionManager; //import net.minecraft.world.level.entity.PersistentEntitySectionManager;
import org.spongepowered.asm.mixin.gen.Accessor; //import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
//
// Does not work on Paper... //// Does not work on Paper...
@Mixin(ServerLevel.class) //@Mixin(ServerLevel.class)
public interface ServerWorldAccessor { //public interface ServerWorldAccessor {
@Accessor // @Accessor
PersistentEntitySectionManager<Entity> getEntityManager(); // PersistentEntitySectionManager<Entity> getEntityManager();
} //}

View File

@@ -1,158 +1,158 @@
package net.gensokyoreimagined.nitori.mixin.util.block_tracking; package net.gensokyoreimagined.nitori.mixin.util.block_tracking;
import net.gensokyoreimagined.nitori.common.block.*; //import net.gensokyoreimagined.nitori.common.block.*;
import net.gensokyoreimagined.nitori.common.entity.block_tracking.ChunkSectionChangeCallback; //import net.gensokyoreimagined.nitori.common.entity.block_tracking.ChunkSectionChangeCallback;
import net.gensokyoreimagined.nitori.common.entity.block_tracking.SectionedBlockChangeTracker; //import net.gensokyoreimagined.nitori.common.entity.block_tracking.SectionedBlockChangeTracker;
import net.minecraft.core.SectionPos; //import net.minecraft.core.SectionPos;
import net.minecraft.network.FriendlyByteBuf; //import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.level.Level; //import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState; //import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.LevelChunkSection; //import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.PalettedContainer; //import net.minecraft.world.level.chunk.PalettedContainer;
import org.spongepowered.asm.mixin.Final; //import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; //import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique; //import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; //import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; //import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; //import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; //import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; //import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
//
/** ///**
* Keep track of how many blocks that meet certain criteria are in this chunk section. // * 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. // * E.g. if no over-sized blocks are there, collision code can skip a few blocks.
* // *
* @author 2No2Name // * @author 2No2Name
*/ // */
@Mixin(LevelChunkSection.class) //@Mixin(LevelChunkSection.class)
public abstract class ChunkSectionMixin implements BlockCountingSection, BlockListeningSection { //public abstract class ChunkSectionMixin implements BlockCountingSection, BlockListeningSection {
//
@Shadow // @Shadow
@Final // @Final
public PalettedContainer<BlockState> states; // public PalettedContainer<BlockState> states;
//
@Unique // @Unique
private short[] nitori$countsByFlag = null; // private short[] nitori$countsByFlag = null;
@Unique // @Unique
private ChunkSectionChangeCallback nitori$changeListener; // private ChunkSectionChangeCallback nitori$changeListener;
@Unique // @Unique
private short nitori$listeningMask; // private short nitori$listeningMask;
//
@Unique // @Unique
private static void nitori$addToFlagCount(short[] countsByFlag, BlockState state, short change) { // private static void nitori$addToFlagCount(short[] countsByFlag, BlockState state, short change) {
int flags = ((BlockStateFlagHolder) state).lithium$getAllFlags(); // int flags = ((BlockStateFlagHolder) state).lithium$getAllFlags();
int i; // int i;
while ((i = Integer.numberOfTrailingZeros(flags)) < 32 && i < countsByFlag.length) { // while ((i = Integer.numberOfTrailingZeros(flags)) < 32 && i < countsByFlag.length) {
//either count up by one (prevFlag not set) or down by one (prevFlag set) // //either count up by one (prevFlag not set) or down by one (prevFlag set)
countsByFlag[i] += change; // countsByFlag[i] += change;
flags &= ~(1 << i); // flags &= ~(1 << i);
} // }
} // }
//
@Override // @Override
public boolean lithium$mayContainAny(TrackedBlockStatePredicate trackedBlockStatePredicate) { // public boolean lithium$mayContainAny(TrackedBlockStatePredicate trackedBlockStatePredicate) {
if (this.nitori$countsByFlag == null) { // if (this.nitori$countsByFlag == null) {
nitori$fastInitClientCounts(); // nitori$fastInitClientCounts();
} // }
return this.nitori$countsByFlag[trackedBlockStatePredicate.getIndex()] != (short) 0; // return this.nitori$countsByFlag[trackedBlockStatePredicate.getIndex()] != (short) 0;
} // }
//
@Unique // @Unique
private void nitori$fastInitClientCounts() { // private void nitori$fastInitClientCounts() {
this.nitori$countsByFlag = new short[BlockStateFlags.NUM_TRACKED_FLAGS]; // this.nitori$countsByFlag = new short[BlockStateFlags.NUM_TRACKED_FLAGS];
for (TrackedBlockStatePredicate trackedBlockStatePredicate : BlockStateFlags.TRACKED_FLAGS) { // for (TrackedBlockStatePredicate trackedBlockStatePredicate : BlockStateFlags.TRACKED_FLAGS) {
if (this.states.maybeHas(trackedBlockStatePredicate)) { // if (this.states.maybeHas(trackedBlockStatePredicate)) {
//We haven't counted, so we just set the count so high that it never incorrectly reaches 0. // //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, // //For most situations, this overestimation does not hurt client performance compared to correct counting,
this.nitori$countsByFlag[trackedBlockStatePredicate.getIndex()] = 16 * 16 * 16; // this.nitori$countsByFlag[trackedBlockStatePredicate.getIndex()] = 16 * 16 * 16;
} // }
} // }
} // }
//
@Inject(method = "recalcBlockCounts()V", at = @At("HEAD")) // @Inject(method = "recalcBlockCounts()V", at = @At("HEAD"))
private void createFlagCounters(CallbackInfo ci) { // private void createFlagCounters(CallbackInfo ci) {
this.nitori$countsByFlag = new short[BlockStateFlags.NUM_TRACKED_FLAGS]; // this.nitori$countsByFlag = new short[BlockStateFlags.NUM_TRACKED_FLAGS];
} // }
//
@Inject( // @Inject(
method = "read", // method = "read",
at = @At(value = "HEAD") // at = @At(value = "HEAD")
) // )
private void resetData(FriendlyByteBuf buf, CallbackInfo ci) { // private void resetData(FriendlyByteBuf buf, CallbackInfo ci) {
this.nitori$countsByFlag = null; // this.nitori$countsByFlag = null;
} // }
//
@Inject( // @Inject(
method = "setBlockState(IIILnet/minecraft/world/level/block/state/BlockState;Z)Lnet/minecraft/world/level/block/state/BlockState;", // method = "setBlockState(IIILnet/minecraft/world/level/block/state/BlockState;Z)Lnet/minecraft/world/level/block/state/BlockState;",
at = @At( // at = @At(
value = "INVOKE", // value = "INVOKE",
target = "Lnet/minecraft/world/level/block/state/BlockState;getFluidState()Lnet/minecraft/world/level/material/FluidState;", // target = "Lnet/minecraft/world/level/block/state/BlockState;getFluidState()Lnet/minecraft/world/level/material/FluidState;",
ordinal = 0, // ordinal = 0,
shift = At.Shift.BEFORE // shift = At.Shift.BEFORE
), // ),
locals = LocalCapture.CAPTURE_FAILHARD // locals = LocalCapture.CAPTURE_FAILHARD
) // )
private void updateFlagCounters(int x, int y, int z, BlockState newState, boolean lock, CallbackInfoReturnable<BlockState> cir, BlockState oldState) { // private void updateFlagCounters(int x, int y, int z, BlockState newState, boolean lock, CallbackInfoReturnable<BlockState> cir, BlockState oldState) {
this.lithium$trackBlockStateChange(newState, oldState); // this.lithium$trackBlockStateChange(newState, oldState);
} // }
//
@Override // @Override
public void lithium$trackBlockStateChange(BlockState newState, BlockState oldState) { // public void lithium$trackBlockStateChange(BlockState newState, BlockState oldState) {
short[] countsByFlag = this.nitori$countsByFlag; // short[] countsByFlag = this.nitori$countsByFlag;
if (countsByFlag == null) { // if (countsByFlag == null) {
return; // return;
} // }
int prevFlags = ((BlockStateFlagHolder) oldState).lithium$getAllFlags(); // int prevFlags = ((BlockStateFlagHolder) oldState).lithium$getAllFlags();
int flags = ((BlockStateFlagHolder) newState).lithium$getAllFlags(); // int flags = ((BlockStateFlagHolder) newState).lithium$getAllFlags();
//
int flagsXOR = prevFlags ^ flags; // int flagsXOR = prevFlags ^ flags;
//we need to iterate over indices that changed or are in the listeningMask // //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 // //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 // //blocks that are different according to the predicate (XOR). For XOR, the block counting needs to be updated
//as well. // //as well.
int iterateFlags = (~BlockStateFlags.LISTENING_MASK_OR & flagsXOR) | // int iterateFlags = (~BlockStateFlags.LISTENING_MASK_OR & flagsXOR) |
(BlockStateFlags.LISTENING_MASK_OR & this.nitori$listeningMask & (prevFlags | flags)); // (BlockStateFlags.LISTENING_MASK_OR & this.nitori$listeningMask & (prevFlags | flags));
int flagIndex; // int flagIndex;
//
while ((flagIndex = Integer.numberOfTrailingZeros(iterateFlags)) < 32 && flagIndex < countsByFlag.length) { // while ((flagIndex = Integer.numberOfTrailingZeros(iterateFlags)) < 32 && flagIndex < countsByFlag.length) {
int flagBit = 1 << flagIndex; // int flagBit = 1 << flagIndex;
//either count up by one (prevFlag not set) or down by one (prevFlag set) // //either count up by one (prevFlag not set) or down by one (prevFlag set)
if ((flagsXOR & flagBit) != 0) { // if ((flagsXOR & flagBit) != 0) {
countsByFlag[flagIndex] += (short) (1 - (((prevFlags >>> flagIndex) & 1) << 1)); // countsByFlag[flagIndex] += (short) (1 - (((prevFlags >>> flagIndex) & 1) << 1));
} // }
if ((this.nitori$listeningMask & flagBit) != 0) { // if ((this.nitori$listeningMask & flagBit) != 0) {
this.nitori$listeningMask = this.nitori$changeListener.onBlockChange(flagIndex, this); // this.nitori$listeningMask = this.nitori$changeListener.onBlockChange(flagIndex, this);
} // }
iterateFlags &= ~flagBit; // iterateFlags &= ~flagBit;
} // }
} // }
//
@Override // @Override
public void lithium$addToCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker, long sectionPos, Level world) { // public void lithium$addToCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker, long sectionPos, Level world) {
if (this.nitori$changeListener == null) { // if (this.nitori$changeListener == null) {
if (sectionPos == Long.MIN_VALUE || world == null) { // if (sectionPos == Long.MIN_VALUE || world == null) {
throw new IllegalArgumentException("Expected world and section pos during intialization!"); // throw new IllegalArgumentException("Expected world and section pos during intialization!");
} // }
this.nitori$changeListener = ChunkSectionChangeCallback.create(sectionPos, world); // this.nitori$changeListener = ChunkSectionChangeCallback.create(sectionPos, world);
} // }
//
this.nitori$listeningMask = this.nitori$changeListener.addTracker(tracker, blockGroup); // this.nitori$listeningMask = this.nitori$changeListener.addTracker(tracker, blockGroup);
} // }
//
@Override // @Override
public void lithium$removeFromCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker) { // public void lithium$removeFromCallback(ListeningBlockStatePredicate blockGroup, SectionedBlockChangeTracker tracker) {
if (this.nitori$changeListener != null) { // if (this.nitori$changeListener != null) {
this.nitori$listeningMask = this.nitori$changeListener.removeTracker(tracker, blockGroup); // this.nitori$listeningMask = this.nitori$changeListener.removeTracker(tracker, blockGroup);
} // }
} // }
//
@Override // @Override
@Unique // @Unique
public void lithium$invalidateListeningSection(SectionPos sectionPos) { // public void lithium$invalidateListeningSection(SectionPos sectionPos) {
if (this.nitori$listeningMask != 0) { // if (this.nitori$listeningMask != 0) {
this.nitori$changeListener.onChunkSectionInvalidated(sectionPos); // this.nitori$changeListener.onChunkSectionInvalidated(sectionPos);
this.nitori$listeningMask = 0; // this.nitori$listeningMask = 0;
} // }
} // }
} //}

View File

@@ -1,22 +1,22 @@
package net.gensokyoreimagined.nitori.mixin.util.block_tracking.block_listening; package net.gensokyoreimagined.nitori.mixin.util.block_tracking.block_listening;
import net.gensokyoreimagined.nitori.common.entity.block_tracking.SectionedBlockChangeTracker; //import net.gensokyoreimagined.nitori.common.entity.block_tracking.SectionedBlockChangeTracker;
import net.gensokyoreimagined.nitori.common.util.deduplication.LithiumInterner; //import net.gensokyoreimagined.nitori.common.util.deduplication.LithiumInterner;
import net.gensokyoreimagined.nitori.common.util.deduplication.LithiumInternerWrapper; //import net.gensokyoreimagined.nitori.common.util.deduplication.LithiumInternerWrapper;
import net.minecraft.world.level.Level; //import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
//
@Mixin(Level.class) //@Mixin(Level.class)
public class WorldMixin implements LithiumInternerWrapper<SectionedBlockChangeTracker> { //public class WorldMixin implements LithiumInternerWrapper<SectionedBlockChangeTracker> {
private final LithiumInterner<SectionedBlockChangeTracker> blockChangeTrackers = new LithiumInterner<>(); // private final LithiumInterner<SectionedBlockChangeTracker> blockChangeTrackers = new LithiumInterner<>();
//
@Override // @Override
public SectionedBlockChangeTracker lithium$getCanonical(SectionedBlockChangeTracker value) { // public SectionedBlockChangeTracker lithium$getCanonical(SectionedBlockChangeTracker value) {
return this.blockChangeTrackers.getCanonical(value); // return this.blockChangeTrackers.getCanonical(value);
} // }
//
@Override // @Override
public void lithium$deleteCanonical(SectionedBlockChangeTracker value) { // public void lithium$deleteCanonical(SectionedBlockChangeTracker value) {
this.blockChangeTrackers.deleteCanonical(value); // this.blockChangeTrackers.deleteCanonical(value);
} // }
} //}

View File

@@ -1,69 +1,69 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire; package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire;
import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity; //import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity;
import net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor; //import net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor;
import net.minecraft.world.entity.Entity; //import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.state.BlockState; //import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.entity.BlockEntity; //import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType; //import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.entity.CampfireBlockEntity; //import net.minecraft.world.level.block.entity.CampfireBlockEntity;
import net.minecraft.world.entity.LivingEntity; //import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack; //import net.minecraft.world.item.ItemStack;
import net.minecraft.nbt.CompoundTag; //import net.minecraft.nbt.CompoundTag;
import net.minecraft.core.HolderLookup; //import net.minecraft.core.HolderLookup;
import net.minecraft.core.BlockPos; //import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.TickingBlockEntity; //import net.minecraft.world.level.block.entity.TickingBlockEntity;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; //import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; //import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; //import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; //import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
//
@Mixin(CampfireBlockEntity.class) //@Mixin(CampfireBlockEntity.class)
public class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity { //public class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity {
//
private WrappedBlockEntityTickInvokerAccessor tickWrapper = null; // private WrappedBlockEntityTickInvokerAccessor tickWrapper = null;
private TickingBlockEntity sleepingTicker = null; // private TickingBlockEntity sleepingTicker = null;
//
public CampfireBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) { // public CampfireBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state); // super(type, pos, state);
} // }
//
@Override // @Override
public WrappedBlockEntityTickInvokerAccessor lithium$getTickWrapper() { // public WrappedBlockEntityTickInvokerAccessor lithium$getTickWrapper() {
return tickWrapper; // return tickWrapper;
} // }
//
@Override // @Override
public void lithium$setTickWrapper(WrappedBlockEntityTickInvokerAccessor tickWrapper) { // public void lithium$setTickWrapper(WrappedBlockEntityTickInvokerAccessor tickWrapper) {
this.tickWrapper = tickWrapper; // this.tickWrapper = tickWrapper;
this.lithium$setSleepingTicker(null); // this.lithium$setSleepingTicker(null);
} // }
//
@Override // @Override
public TickingBlockEntity lithium$getSleepingTicker() { // public TickingBlockEntity lithium$getSleepingTicker() {
return sleepingTicker; // return sleepingTicker;
} // }
//
@Override // @Override
public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) { // public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) {
this.sleepingTicker = sleepingTicker; // this.sleepingTicker = sleepingTicker;
} // }
//
//
@Inject( // @Inject(
method = "placeFood", // method = "placeFood",
at = @At(value = "INVOKE", target = "Lnet/minecraft/core/NonNullList;set(ILjava/lang/Object;)Ljava/lang/Object;") // 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<Boolean> cir) { // private void wakeUpOnAddItem(LivingEntity user, ItemStack stack, int cookTime, CallbackInfoReturnable<Boolean> cir) {
this.wakeUpNow(); // this.wakeUpNow();
} // }
//
@Inject( // @Inject(
method = "loadAdditional", // method = "loadAdditional",
at = @At(value = "RETURN") // at = @At(value = "RETURN")
) // )
private void wakeUpOnReadNbt(CompoundTag nbt, HolderLookup.Provider registryLookup, CallbackInfo ci) { // private void wakeUpOnReadNbt(CompoundTag nbt, HolderLookup.Provider registryLookup, CallbackInfo ci) {
this.wakeUpNow(); // this.wakeUpNow();
} // }
} //}

View File

@@ -1,40 +1,40 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire.lit; package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire.lit;
import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity; //import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity;
import net.minecraft.core.BlockPos; //import net.minecraft.core.BlockPos;
import net.minecraft.world.SimpleContainer; //import net.minecraft.world.SimpleContainer;
import net.minecraft.world.item.ItemStack; //import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; //import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity; //import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType; //import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.entity.CampfireBlockEntity; //import net.minecraft.world.level.block.entity.CampfireBlockEntity;
import net.minecraft.world.level.block.state.BlockState; //import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.craftbukkit.inventory.CraftItemStack; //import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.event.block.BlockCookEvent; //import org.bukkit.event.block.BlockCookEvent;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; //import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; //import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; //import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; //import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
//
import java.util.Optional; //import java.util.Optional;
//
@Mixin(CampfireBlockEntity.class) //@Mixin(CampfireBlockEntity.class)
public abstract class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity { //public abstract class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity {
//
public CampfireBlockEntityMixin(BlockPos pos, BlockState state) { // public CampfireBlockEntityMixin(BlockPos pos, BlockState state) {
super(BlockEntityType.CAMPFIRE, pos, state); // super(BlockEntityType.CAMPFIRE, pos, state);
} // }
//
@Inject( // @Inject(
method = "cookTick", // method = "cookTick",
at = @At("RETURN"), // at = @At("RETURN"),
locals = LocalCapture.CAPTURE_FAILHARD // locals = LocalCapture.CAPTURE_FAILHARD
) // )
private static void trySleepLit(Level world, BlockPos pos, BlockState state, CampfireBlockEntity campfire, CallbackInfo ci, boolean flag) { // private static void trySleepLit(Level world, BlockPos pos, BlockState state, CampfireBlockEntity campfire, CallbackInfo ci, boolean flag) {
if (!flag) { // if (!flag) {
CampfireBlockEntityMixin self = (CampfireBlockEntityMixin) (Object) campfire; // CampfireBlockEntityMixin self = (CampfireBlockEntityMixin) (Object) campfire;
self.nitori$startSleeping(); // self.nitori$startSleeping();
} // }
} // }
} //}

View File

@@ -1,34 +1,34 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire.unlit; package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire.unlit;
import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity; //import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity;
import net.minecraft.core.BlockPos; //import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level; //import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity; //import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType; //import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.entity.CampfireBlockEntity; //import net.minecraft.world.level.block.entity.CampfireBlockEntity;
import net.minecraft.world.level.block.state.BlockState; //import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Mixin; //import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; //import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; //import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; //import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; //import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
//
@Mixin(CampfireBlockEntity.class) //@Mixin(CampfireBlockEntity.class)
public abstract class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity { //public abstract class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity {
//
public CampfireBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) { // public CampfireBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state); // super(type, pos, state);
} // }
//
@Inject( // @Inject(
method = "cooldownTick", // method = "cooldownTick",
at = @At("RETURN"), // at = @At("RETURN"),
locals = LocalCapture.CAPTURE_FAILHARD // locals = LocalCapture.CAPTURE_FAILHARD
) // )
private static void trySleepLit(Level world, BlockPos pos, BlockState state, CampfireBlockEntity campfire, CallbackInfo ci, boolean flag) { // private static void trySleepLit(Level world, BlockPos pos, BlockState state, CampfireBlockEntity campfire, CallbackInfo ci, boolean flag) {
if (!flag) { // if (!flag) {
CampfireBlockEntityMixin self = (CampfireBlockEntityMixin) (Object) campfire; // CampfireBlockEntityMixin self = (CampfireBlockEntityMixin) (Object) campfire;
self.nitori$startSleeping(); // self.nitori$startSleeping();
} // }
} // }
} //}

View File

@@ -18,158 +18,147 @@ package net.gensokyoreimagined.nitori.tracker;
* Ported from Petal, derived from Airplane * Ported from Petal, derived from Airplane
*/ */
import com.google.common.util.concurrent.ThreadFactoryBuilder; //import ca.spottedleaf.moonrise.common.list.ReferenceList;
import io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet; //import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
import io.papermc.paper.world.ChunkEntitySlices; //import com.google.common.util.concurrent.ThreadFactoryBuilder;
import net.gensokyoreimagined.nitori.access.IMixinChunkEntitySlicesAccess; //import ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet; //io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet;
import net.gensokyoreimagined.nitori.access.IMixinChunkMap_TrackedEntityAccess; //import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices; //io.papermc.paper.world.ChunkEntitySlices;
import net.gensokyoreimagined.nitori.access.IMixinIteratorSafeOrderedReferenceSetAccess; //import net.gensokyoreimagined.nitori.access.IMixinChunkEntitySlicesAccess;
import net.minecraft.server.MinecraftServer; //import net.gensokyoreimagined.nitori.access.IMixinChunkMap_TrackedEntityAccess;
import net.minecraft.server.level.ChunkMap; //import net.gensokyoreimagined.nitori.access.IMixinIteratorSafeOrderedReferenceSetAccess;
import net.minecraft.world.entity.Entity; //import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.chunk.LevelChunk; //import net.minecraft.server.level.ChunkMap;
//import net.minecraft.server.level.ServerChunkCache;
import java.util.concurrent.ConcurrentLinkedQueue; //import net.minecraft.server.level.ServerPlayer;
import java.util.concurrent.Executor; //import net.minecraft.world.entity.Entity;
import java.util.concurrent.Executors; //import net.minecraft.world.level.chunk.LevelChunk;
import java.util.concurrent.atomic.AtomicInteger; //
//import java.util.ArrayList;
public class MultithreadedTracker { //import java.util.List;
//import java.util.concurrent.ConcurrentLinkedQueue;
private enum TrackerStage { //import java.util.concurrent.Executor;
UPDATE_PLAYERS, //import java.util.concurrent.Executors;
SEND_CHANGES //import java.util.concurrent.atomic.AtomicInteger;
} //
//public class MultithreadedTracker {
private static final int parallelism = Math.max(4, Runtime.getRuntime().availableProcessors()); //
private static final Executor trackerExecutor = Executors.newFixedThreadPool(parallelism, new ThreadFactoryBuilder() // private enum TrackerStage {
.setNameFormat("mirai-tracker-%d") // UPDATE_PLAYERS,
.setPriority(Thread.NORM_PRIORITY - 2) // SEND_CHANGES
.build()); // }
//
private final IteratorSafeOrderedReferenceSet<LevelChunk> entityTickingChunks; // private static final int parallelism = Math.max(4, Runtime.getRuntime().availableProcessors());
private final AtomicInteger taskIndex = new AtomicInteger(); // private static final Executor trackerExecutor = Executors.newFixedThreadPool(parallelism, new ThreadFactoryBuilder()
// .setNameFormat("mirai-tracker-%d")
private final ConcurrentLinkedQueue<Runnable> mainThreadTasks; // .setPriority(Thread.NORM_PRIORITY - 2)
private final AtomicInteger finishedTasks = new AtomicInteger(); // .build());
//
public MultithreadedTracker(IteratorSafeOrderedReferenceSet<LevelChunk> entityTickingChunks, ConcurrentLinkedQueue<Runnable> mainThreadTasks) { // private final ReferenceList<ServerChunkCache.ChunkAndHolder> entityTickingChunks;
this.entityTickingChunks = entityTickingChunks; // private final AtomicInteger taskIndex = new AtomicInteger();
this.mainThreadTasks = mainThreadTasks; //
} // private final ConcurrentLinkedQueue<Runnable> mainThreadTasks;
// private final AtomicInteger finishedTasks = new AtomicInteger();
public void tick() { //
int iterator = this.entityTickingChunks.createRawIterator(); // public MultithreadedTracker(ReferenceList<ServerChunkCache.ChunkAndHolder> entityTickingChunks, ConcurrentLinkedQueue<Runnable> mainThreadTasks) {
// this.entityTickingChunks = entityTickingChunks;
if (iterator == -1) { // this.mainThreadTasks = mainThreadTasks;
return; // }
} //
// public void tick() {
// start with updating players // this.taskIndex.set(0);
try { // this.finishedTasks.set(0);
this.taskIndex.set(iterator); //
this.finishedTasks.set(0); // for (int i = 0; i < parallelism; i++) {
// trackerExecutor.execute(this::runUpdatePlayers);
for (int i = 0; i < parallelism; i++) { // }
trackerExecutor.execute(this::runUpdatePlayers); //
} // // start with updating players
// while (this.taskIndex.get() < this.entityTickingChunks.size()) {
while (this.taskIndex.get() < ((IMixinIteratorSafeOrderedReferenceSetAccess) (Object) this.entityTickingChunks).getListSize()) { // this.runMainThreadTasks();
this.runMainThreadTasks(); // this.handleChunkUpdates(5); // assist
this.handleChunkUpdates(5); // assist // }
} //
// // then send changes
while (this.finishedTasks.get() != parallelism) { // while (this.finishedTasks.get() != parallelism) {
this.runMainThreadTasks(); // this.runMainThreadTasks();
} // }
//
this.runMainThreadTasks(); // finish any remaining tasks // this.runMainThreadTasks(); // finish any remaining tasks
} finally { //
this.entityTickingChunks.finishRawIterator(); // for (ServerChunkCache.ChunkAndHolder chunkAndHolder : this.entityTickingChunks) {
} // LevelChunk chunk = chunkAndHolder.chunk();
//
// then send changes // if (chunk != null) {
iterator = this.entityTickingChunks.createRawIterator(); // this.updateChunkEntities(chunk, TrackerStage.SEND_CHANGES);
// }
if (iterator == -1) { // }
return; // }
} //
// private void runMainThreadTasks() {
try { // try {
do { // Runnable task;
LevelChunk chunk = this.entityTickingChunks.rawGet(iterator); // while ((task = this.mainThreadTasks.poll()) != null) {
// task.run();
if (chunk != null) { // }
this.updateChunkEntities(chunk, TrackerStage.SEND_CHANGES); // } catch (Throwable throwable) {
} // MinecraftServer.LOGGER.warn("Tasks failed while ticking track queue", throwable);
} while (++iterator < ((IMixinIteratorSafeOrderedReferenceSetAccess) (Object) this.entityTickingChunks).getListSize()); // }
} finally { // }
this.entityTickingChunks.finishRawIterator(); //
} // private void runUpdatePlayers() {
} // try {
// while (handleChunkUpdates(10));
private void runMainThreadTasks() { // } finally {
try { // this.finishedTasks.incrementAndGet();
Runnable task; // }
while ((task = this.mainThreadTasks.poll()) != null) { // }
task.run(); //
} // private boolean handleChunkUpdates(int tasks) {
} catch (Throwable throwable) { // int index;
MinecraftServer.LOGGER.warn("Tasks failed while ticking track queue", throwable); // 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) {
private void runUpdatePlayers() { // try {
try { // this.updateChunkEntities(chunk, TrackerStage.UPDATE_PLAYERS);
while (handleChunkUpdates(10)); // } catch (Throwable throwable) {
} finally { // MinecraftServer.LOGGER.warn("Ticking tracker failed", throwable);
this.finishedTasks.incrementAndGet(); // }
} //
} // }
// }
private boolean handleChunkUpdates(int tasks) { //
int index; // return true;
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); // return false;
if (chunk != null) { // }
try { //
this.updateChunkEntities(chunk, TrackerStage.UPDATE_PLAYERS); // private void updateChunkEntities(LevelChunk chunk, TrackerStage trackerStage) {
} catch (Throwable throwable) { // final ChunkEntitySlices entitySlices = chunk.level.moonrise$getEntityLookup().getChunk(chunk.locX, chunk.locZ);
MinecraftServer.LOGGER.warn("Ticking tracker failed", throwable); // if (entitySlices == null) {
} // return;
// }
} //
} // final Entity[] rawEntities = ((IMixinChunkEntitySlicesAccess) (Object) entitySlices).getEntities().getRawData();
// final ChunkMap chunkMap = chunk.level.chunkSource.chunkMap;
return true; //
} // for (int i = 0; i < rawEntities.length; i++) {
// Entity entity = rawEntities[i];
return false; // if (entity != null) {
} // ChunkMap.TrackedEntity entityTracker = chunkMap.entityMap.get(entity.getId());
// if (entityTracker != null) {
private void updateChunkEntities(LevelChunk chunk, TrackerStage trackerStage) { // if (trackerStage == TrackerStage.SEND_CHANGES) {
final ChunkEntitySlices entitySlices = chunk.level.getEntityLookup().getChunk(chunk.locX, chunk.locZ); // entityTracker.serverEntity.sendChanges();
if (entitySlices == null) { // } else if (trackerStage == TrackerStage.UPDATE_PLAYERS) {
return; // ReferenceList<ServerPlayer> nearbyPlayers = chunkMap.level.moonrise$getNearbyPlayers().getChunk(entity.chunkPosition()).getPlayers(NearbyPlayers.NearbyMapType.VIEW_DISTANCE);
} // List<ServerPlayer> nearbyPlayersList = new ArrayList<ServerPlayer>(nearbyPlayers.size()); // intentionally typed as List for requirement clarity
// nearbyPlayers.forEach(nearbyPlayersList::add);
final Entity[] rawEntities = ((IMixinChunkEntitySlicesAccess) (Object) entitySlices).getEntities().getRawData(); // ((IMixinChunkMap_TrackedEntityAccess) (Object) entityTracker).callUpdatePlayers(nearbyPlayersList);
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) {
((IMixinChunkMap_TrackedEntityAccess) (Object) entityTracker).callUpdatePlayers(((IMixinChunkMap_TrackedEntityAccess) (Object) entityTracker).getEntity().getPlayersInTrackRange());
}
}
}
}
}
}

View File

@@ -1,6 +1,6 @@
{ {
"id": "Nitori", "id": "Nitori",
"version": "1.4-SNAPSHOT", "version": "1.5-SNAPSHOT",
"mixins": [ "mixins": [
"mixins.core.json" "mixins.core.json"
] ]

View File

@@ -6,25 +6,18 @@
"target": "@env(DEFAULT)", "target": "@env(DEFAULT)",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_17",
"server": [ "server": [
"ChunkMapMixin",
"ChunkMapMixin$TrackedEntity",
"MixinBlockPos", "MixinBlockPos",
"MixinChunkEntitySlices", "MixinChunkEntitySlices",
"MixinCraftPlayer", "MixinCraftPlayer",
"MixinEntity", "MixinEntity",
"MixinEntitySectionStorage", "MixinEntitySectionStorage",
"collections.gamerules.MixinGameRules",
"MixinIteratorSafeOrderedReferenceSet", "MixinIteratorSafeOrderedReferenceSet",
"MixinLevelStorageAccess", "MixinLevelStorageAccess",
"entity.micro_opts.MixinMob",
"MixinNoiseBasedChunkGenerator", "MixinNoiseBasedChunkGenerator",
"MixinPlayer", "MixinPlayer",
"MixinPlayerList", "MixinPlayerList",
"MixinReobfServer", "MixinReobfServer",
"MixinServerBossEvent", "MixinServerBossEvent",
"MixinServerEntity",
"MixinSpongeSIMD",
"MixinWorldGenRegion",
"ai.sensor.secondary_poi.SecondaryPointsOfInterestSensorMixin", "ai.sensor.secondary_poi.SecondaryPointsOfInterestSensorMixin",
"ai.pathing.PathContextAccessor", "ai.pathing.PathContextAccessor",
"ai.poi.PointOfInterestSetMixin", "ai.poi.PointOfInterestSetMixin",
@@ -38,14 +31,11 @@
"ai.pathing.ChunkCacheMixin", "ai.pathing.ChunkCacheMixin",
"ai.pathing.TargetPredicateMixin", "ai.pathing.TargetPredicateMixin",
"alloc.blockstate.StateMixin", "alloc.blockstate.StateMixin",
"alloc.chunk_ticking.ServerChunkManagerMixin",
"alloc.composter.ComposterMixin$ComposterBlockComposterInventoryMixin", "alloc.composter.ComposterMixin$ComposterBlockComposterInventoryMixin",
"alloc.composter.ComposterMixin$ComposterBlockDummyInventoryMixin", "alloc.composter.ComposterMixin$ComposterBlockDummyInventoryMixin",
"alloc.composter.ComposterMixin$ComposterBlockFullComposterInventoryMixin", "alloc.composter.ComposterMixin$ComposterBlockFullComposterInventoryMixin",
"alloc.biome_temprature_leak.Biome_threadLocalMixin", "alloc.biome_temprature_leak.Biome_threadLocalMixin",
"alloc.MixinIdentifier",
"cached_hashcode.BlockNeighborGroupMixin", "cached_hashcode.BlockNeighborGroupMixin",
"collections.attributes.AttributeContainerMixin",
"collections.block_entity_tickers.WorldChunkMixin", "collections.block_entity_tickers.WorldChunkMixin",
"collections.chunk_tickets.SortedArraySetMixin", "collections.chunk_tickets.SortedArraySetMixin",
"collections.entity_by_type.TypeFilterableListMixin", "collections.entity_by_type.TypeFilterableListMixin",
@@ -71,7 +61,6 @@
"logic.fast_bits_blockpos.OptimizedBlockPosBitsMixin", "logic.fast_bits_blockpos.OptimizedBlockPosBitsMixin",
"logic.fast_rotations.EulerAngleMixin", "logic.fast_rotations.EulerAngleMixin",
"logic.reduce_ray_casting.BlockViewCastingMixin", "logic.reduce_ray_casting.BlockViewCastingMixin",
"logic.recipe_manager.RecipeManagerMixin",
"math.fast_blockops.BlockPosMixin", "math.fast_blockops.BlockPosMixin",
"math.fast_blockops.DirectionMixin", "math.fast_blockops.DirectionMixin",
"math.fast_util.AxisCycleDirectionMixin$BackwardMixin", "math.fast_util.AxisCycleDirectionMixin$BackwardMixin",
@@ -88,7 +77,6 @@
"math.sine_lut.MixinMth", "math.sine_lut.MixinMth",
"math.vec.FastMathVec3DMixin", "math.vec.FastMathVec3DMixin",
"math.random.RandomMixin", "math.random.RandomMixin",
"math.random.creation.ServerPlayerEntityRandomMixin",
"network.microopt.VarIntsMixin", "network.microopt.VarIntsMixin",
"network.microopt.StringEncodingMixin", "network.microopt.StringEncodingMixin",
"network.block_breaking.CacheBlockBreakPacketMixin", "network.block_breaking.CacheBlockBreakPacketMixin",
@@ -103,16 +91,10 @@
"shapes.precompute_shape_arrays.SimpleVoxelShapeMixin", "shapes.precompute_shape_arrays.SimpleVoxelShapeMixin",
"shapes.specialized_shapes.VoxelShapeMixin", "shapes.specialized_shapes.VoxelShapeMixin",
"util.MixinLevelBlockEntityRetrieval", "util.MixinLevelBlockEntityRetrieval",
"util.accessors.ClientEntityManagerAccessor",
"util.accessors.EntityTrackingSectionAccessor", "util.accessors.EntityTrackingSectionAccessor",
"util.accessors.ServerEntityManagerAccessor",
"util.block_tracking.AbstractBlockStateMixin", "util.block_tracking.AbstractBlockStateMixin",
"util.block_tracking.block_listening.WorldMixin",
"util.block_entity_retrieval.WorldMixin", "util.block_entity_retrieval.WorldMixin",
"world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor", "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.sleeping.furnace.AbstractFurnaceBlockEntityMixin",
"world.block_entity_ticking.support_cache.BlockEntityMixin", "world.block_entity_ticking.support_cache.BlockEntityMixin",
"world.block_entity_ticking.support_cache.DirectBlockEntityTickInvokerMixin", "world.block_entity_ticking.support_cache.DirectBlockEntityTickInvokerMixin",