1.21 "works"
This commit is contained in:
@@ -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
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -14,15 +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 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;
|
//import java.util.List;
|
||||||
|
//
|
||||||
public interface IMixinChunkMap_TrackedEntityAccess {
|
//public interface IMixinChunkMap_TrackedEntityAccess {
|
||||||
@SuppressWarnings("EmptyMethod")
|
// @SuppressWarnings("EmptyMethod")
|
||||||
Entity getEntity();
|
// Entity getEntity();
|
||||||
|
//
|
||||||
@SuppressWarnings("EmptyMethod")
|
// @SuppressWarnings("EmptyMethod")
|
||||||
void callUpdatePlayers(List<ServerPlayer> players);
|
// void callUpdatePlayers(List<ServerPlayer> players);
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
//}
|
||||||
@@ -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;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
@@ -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;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
@@ -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);
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
@@ -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();
|
||||||
}
|
//}
|
||||||
@@ -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);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
@@ -14,158 +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 ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
//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.List;
|
//import java.util.List;
|
||||||
import java.util.Set;
|
//import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
//import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import javax.annotation.Nullable;
|
//import javax.annotation.Nullable;
|
||||||
|
//
|
||||||
@Mixin(ChunkMap.class)
|
//@Mixin(ChunkMap.class)
|
||||||
public class ChunkMapMixin implements IMixinChunkMapAccess {
|
//public class ChunkMapMixin implements IMixinChunkMapAccess {
|
||||||
|
//
|
||||||
@Mutable
|
// @Mutable
|
||||||
@Shadow @Final public Int2ObjectMap<ChunkMap.TrackedEntity> entityMap;
|
// @Shadow @Final public Int2ObjectMap<ChunkMap.TrackedEntity> entityMap;
|
||||||
|
//
|
||||||
// Implementation of 0107-Multithreaded-Tracker.patch
|
// // Implementation of 0107-Multithreaded-Tracker.patch
|
||||||
@Final
|
// @Final
|
||||||
@Shadow
|
// @Shadow
|
||||||
public ServerLevel level;
|
// public ServerLevel level;
|
||||||
|
//
|
||||||
// Implementation of 0107-Multithreaded-Tracker.patch
|
// // Implementation of 0107-Multithreaded-Tracker.patch
|
||||||
@Unique
|
// @Unique
|
||||||
private @Nullable MultithreadedTracker gensouHacks$multithreadedTracker;
|
// private @Nullable MultithreadedTracker gensouHacks$multithreadedTracker;
|
||||||
|
//
|
||||||
// Implementation of 0107-Multithreaded-Tracker.patch
|
// // Implementation of 0107-Multithreaded-Tracker.patch
|
||||||
@Final
|
// @Final
|
||||||
@Unique
|
// @Unique
|
||||||
private final ConcurrentLinkedQueue<Runnable> gensouHacks$trackerMainThreadTasks = new ConcurrentLinkedQueue<>();
|
// private final ConcurrentLinkedQueue<Runnable> gensouHacks$trackerMainThreadTasks = new ConcurrentLinkedQueue<>();
|
||||||
|
//
|
||||||
// Implementation of 0107-Multithreaded-Tracker.patch
|
// // Implementation of 0107-Multithreaded-Tracker.patch
|
||||||
@Unique
|
// @Unique
|
||||||
private boolean gensouHacks$tracking = false;
|
// private boolean gensouHacks$tracking = false;
|
||||||
|
//
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
// @Inject(method = "<init>", at = @At("RETURN"))
|
||||||
private void reassignEntityTrackers(CallbackInfo ci) {
|
// private void reassignEntityTrackers(CallbackInfo ci) {
|
||||||
this.entityMap = new Int2ObjectLinkedOpenHashMap<>();
|
// this.entityMap = new Int2ObjectLinkedOpenHashMap<>();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Implementation of 0107-Multithreaded-Tracker.patch
|
// // Implementation of 0107-Multithreaded-Tracker.patch
|
||||||
@Override
|
// @Override
|
||||||
@Unique
|
// @Unique
|
||||||
public void gensouHacks$runOnTrackerMainThread(final Runnable runnable) {
|
// public void gensouHacks$runOnTrackerMainThread(final Runnable runnable) {
|
||||||
if (this.gensouHacks$tracking) {
|
// if (this.gensouHacks$tracking) {
|
||||||
this.gensouHacks$trackerMainThreadTasks.add(runnable);
|
// this.gensouHacks$trackerMainThreadTasks.add(runnable);
|
||||||
} else {
|
// } else {
|
||||||
runnable.run();
|
// runnable.run();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Inject(method = "newTrackerTick", at = @At("HEAD"), cancellable = true)
|
// @Inject(method = "newTrackerTick", at = @At("HEAD"), cancellable = true)
|
||||||
private void atProcessTrackQueueHead(CallbackInfo callbackInfo) {
|
// private void atProcessTrackQueueHead(CallbackInfo callbackInfo) {
|
||||||
// Implementation of 0107-Multithreaded-Tracker.patch
|
// // Implementation of 0107-Multithreaded-Tracker.patch
|
||||||
//TODO: Restore config condition
|
// //TODO: Restore config condition
|
||||||
//if (NitoriConfig.enableAsyncEntityTracker) {
|
// //if (NitoriConfig.enableAsyncEntityTracker) {
|
||||||
if (this.gensouHacks$multithreadedTracker == null) {
|
// if (this.gensouHacks$multithreadedTracker == null) {
|
||||||
this.gensouHacks$multithreadedTracker = new MultithreadedTracker(((ChunkSystemServerLevel) this.level).moonrise$getEntityTickingChunks(), this.gensouHacks$trackerMainThreadTasks);
|
// this.gensouHacks$multithreadedTracker = new MultithreadedTracker(((ChunkSystemServerLevel) this.level).moonrise$getEntityTickingChunks(), this.gensouHacks$trackerMainThreadTasks);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
this.gensouHacks$tracking = true;
|
// this.gensouHacks$tracking = true;
|
||||||
try {
|
// try {
|
||||||
this.gensouHacks$multithreadedTracker.tick();
|
// this.gensouHacks$multithreadedTracker.tick();
|
||||||
} finally {
|
// } finally {
|
||||||
this.gensouHacks$tracking = false;
|
// this.gensouHacks$tracking = false;
|
||||||
}
|
// }
|
||||||
callbackInfo.cancel();
|
// callbackInfo.cancel();
|
||||||
//}
|
// //}
|
||||||
// Mirai end
|
// // Mirai end
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Mixin(ChunkMap.TrackedEntity.class)
|
// @Mixin(ChunkMap.TrackedEntity.class)
|
||||||
public static abstract class TrackedEntity implements IMixinChunkMap_TrackedEntityAccess {
|
// public static abstract class TrackedEntity implements IMixinChunkMap_TrackedEntityAccess {
|
||||||
// Implementation of 0107-Multithreaded-Tracker.patch
|
// // Implementation of 0107-Multithreaded-Tracker.patch
|
||||||
@Override
|
// @Override
|
||||||
@Final
|
// @Final
|
||||||
@Accessor
|
// @Accessor
|
||||||
public abstract Entity getEntity(); // Mirai -> public
|
// public abstract Entity getEntity(); // Mirai -> public
|
||||||
|
//
|
||||||
@Final
|
// @Final
|
||||||
@Mutable
|
// @Mutable
|
||||||
@Shadow
|
// @Shadow
|
||||||
public Set<ServerPlayerConnection> seenBy;
|
// public Set<ServerPlayerConnection> seenBy;
|
||||||
|
//
|
||||||
@Shadow
|
// @Shadow
|
||||||
public abstract void updatePlayer(ServerPlayer player);
|
// public abstract void updatePlayer(ServerPlayer player);
|
||||||
|
//
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
// @Inject(method = "<init>", at = @At("RETURN"))
|
||||||
private void reassignSeenBy(CallbackInfo ci) {
|
// private void reassignSeenBy(CallbackInfo ci) {
|
||||||
// Implementation of 0107-Multithreaded-Tracker.patch
|
// // Implementation of 0107-Multithreaded-Tracker.patch
|
||||||
this.seenBy = ReferenceSets.synchronize(new ReferenceOpenHashSet<>()); // Mirai - sync
|
// this.seenBy = ReferenceSets.synchronize(new ReferenceOpenHashSet<>()); // Mirai - sync
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Implementation of 0107-Multithreaded-Tracker.patch
|
// // Implementation of 0107-Multithreaded-Tracker.patch
|
||||||
@Override
|
// @Override
|
||||||
@Final
|
// @Final
|
||||||
@Invoker
|
// @Invoker
|
||||||
public abstract void callUpdatePlayers(List<ServerPlayer> players); // Mirai -> public
|
// public abstract void callUpdatePlayers(List<ServerPlayer> players); // Mirai -> public
|
||||||
|
//
|
||||||
@Redirect(method = "updatePlayers", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkMap$TrackedEntity;updatePlayer(Lnet/minecraft/server/level/ServerPlayer;)V"))
|
// @Redirect(method = "updatePlayers", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkMap$TrackedEntity;updatePlayer(Lnet/minecraft/server/level/ServerPlayer;)V"))
|
||||||
private void handleCitizensPluginTracking(ChunkMap.TrackedEntity self, ServerPlayer serverPlayer) {
|
// private void handleCitizensPluginTracking(ChunkMap.TrackedEntity self, ServerPlayer serverPlayer) {
|
||||||
// Nitori - Citizens tracker must run on the main thread to avoid cyclic wait
|
// // Nitori - Citizens tracker must run on the main thread to avoid cyclic wait
|
||||||
if (PluginCompatibilityRegistry.CITIZENS.shouldRedirectToMainThread(self, serverPlayer)) {
|
// if (PluginCompatibilityRegistry.CITIZENS.shouldRedirectToMainThread(self, serverPlayer)) {
|
||||||
((IMixinChunkMapAccess) (Object) ((ServerLevel) serverPlayer.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() ->
|
// ((IMixinChunkMapAccess) (Object) ((ServerLevel) serverPlayer.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() ->
|
||||||
this.updatePlayer(serverPlayer)
|
// this.updatePlayer(serverPlayer)
|
||||||
);
|
// );
|
||||||
} else {
|
// } else {
|
||||||
this.updatePlayer(serverPlayer);
|
// this.updatePlayer(serverPlayer);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Implementation of 0107-Multithreaded-Tracker.patch
|
// // Implementation of 0107-Multithreaded-Tracker.patch
|
||||||
@SuppressWarnings("EmptyMethod")
|
// @SuppressWarnings("EmptyMethod")
|
||||||
@Redirect(method = "removePlayer", at = @At(value = "INVOKE", target = "Lorg/spigotmc/AsyncCatcher;catchOp(Ljava/lang/String;)V"))
|
// @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
|
// private void skipSpigotAsyncPlayerTrackerClear(String reason) {} // Mirai - we can remove async too
|
||||||
|
//
|
||||||
// Implementation of 0107-Multithreaded-Tracker.patch
|
// // Implementation of 0107-Multithreaded-Tracker.patch
|
||||||
@SuppressWarnings("EmptyMethod")
|
// @SuppressWarnings("EmptyMethod")
|
||||||
@Redirect(method = "updatePlayer", at = @At(value = "INVOKE", target = "Lorg/spigotmc/AsyncCatcher;catchOp(Ljava/lang/String;)V"))
|
// @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
|
// 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"))
|
// @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) {
|
// private void handleTrainCartsPluginAddPairing(ServerEntity self, ServerPlayer serverPlayer) {
|
||||||
if (PluginCompatibilityRegistry.TRAIN_CARTS.shouldRedirectToMainThread((ChunkMap.TrackedEntity) (Object) this)) {
|
// if (PluginCompatibilityRegistry.TRAIN_CARTS.shouldRedirectToMainThread((ChunkMap.TrackedEntity) (Object) this)) {
|
||||||
((IMixinChunkMapAccess) (Object) ((ServerLevel) serverPlayer.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() ->
|
// ((IMixinChunkMapAccess) (Object) ((ServerLevel) serverPlayer.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() ->
|
||||||
self.addPairing(serverPlayer)
|
// self.addPairing(serverPlayer)
|
||||||
);
|
// );
|
||||||
} else {
|
// } else {
|
||||||
self.addPairing(serverPlayer);
|
// self.addPairing(serverPlayer);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -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!");
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
@@ -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);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
@@ -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);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
@@ -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();
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
@@ -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();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
@@ -18,147 +18,147 @@ package net.gensokyoreimagined.nitori.tracker;
|
|||||||
* Ported from Petal, derived from Airplane
|
* Ported from Petal, derived from Airplane
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
//import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
||||||
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
|
//import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
//import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
import ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet; //io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet;
|
//import ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet; //io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices; //io.papermc.paper.world.ChunkEntitySlices;
|
//import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices; //io.papermc.paper.world.ChunkEntitySlices;
|
||||||
import net.gensokyoreimagined.nitori.access.IMixinChunkEntitySlicesAccess;
|
//import net.gensokyoreimagined.nitori.access.IMixinChunkEntitySlicesAccess;
|
||||||
import net.gensokyoreimagined.nitori.access.IMixinChunkMap_TrackedEntityAccess;
|
//import net.gensokyoreimagined.nitori.access.IMixinChunkMap_TrackedEntityAccess;
|
||||||
import net.gensokyoreimagined.nitori.access.IMixinIteratorSafeOrderedReferenceSetAccess;
|
//import net.gensokyoreimagined.nitori.access.IMixinIteratorSafeOrderedReferenceSetAccess;
|
||||||
import net.minecraft.server.MinecraftServer;
|
//import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.level.ChunkMap;
|
//import net.minecraft.server.level.ChunkMap;
|
||||||
import net.minecraft.server.level.ServerChunkCache;
|
//import net.minecraft.server.level.ServerChunkCache;
|
||||||
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 net.minecraft.world.level.chunk.LevelChunk;
|
//import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
//
|
||||||
import java.util.ArrayList;
|
//import java.util.ArrayList;
|
||||||
import java.util.List;
|
//import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
//import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.Executor;
|
//import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Executors;
|
//import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
//import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
//
|
||||||
public class MultithreadedTracker {
|
//public class MultithreadedTracker {
|
||||||
|
//
|
||||||
private enum TrackerStage {
|
// private enum TrackerStage {
|
||||||
UPDATE_PLAYERS,
|
// UPDATE_PLAYERS,
|
||||||
SEND_CHANGES
|
// SEND_CHANGES
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private static final int parallelism = Math.max(4, Runtime.getRuntime().availableProcessors());
|
// private static final int parallelism = Math.max(4, Runtime.getRuntime().availableProcessors());
|
||||||
private static final Executor trackerExecutor = Executors.newFixedThreadPool(parallelism, new ThreadFactoryBuilder()
|
// private static final Executor trackerExecutor = Executors.newFixedThreadPool(parallelism, new ThreadFactoryBuilder()
|
||||||
.setNameFormat("mirai-tracker-%d")
|
// .setNameFormat("mirai-tracker-%d")
|
||||||
.setPriority(Thread.NORM_PRIORITY - 2)
|
// .setPriority(Thread.NORM_PRIORITY - 2)
|
||||||
.build());
|
// .build());
|
||||||
|
//
|
||||||
private final ReferenceList<ServerChunkCache.ChunkAndHolder> entityTickingChunks;
|
// private final ReferenceList<ServerChunkCache.ChunkAndHolder> entityTickingChunks;
|
||||||
private final AtomicInteger taskIndex = new AtomicInteger();
|
// private final AtomicInteger taskIndex = new AtomicInteger();
|
||||||
|
//
|
||||||
private final ConcurrentLinkedQueue<Runnable> mainThreadTasks;
|
// private final ConcurrentLinkedQueue<Runnable> mainThreadTasks;
|
||||||
private final AtomicInteger finishedTasks = new AtomicInteger();
|
// private final AtomicInteger finishedTasks = new AtomicInteger();
|
||||||
|
//
|
||||||
public MultithreadedTracker(ReferenceList<ServerChunkCache.ChunkAndHolder> entityTickingChunks, ConcurrentLinkedQueue<Runnable> mainThreadTasks) {
|
// public MultithreadedTracker(ReferenceList<ServerChunkCache.ChunkAndHolder> entityTickingChunks, ConcurrentLinkedQueue<Runnable> mainThreadTasks) {
|
||||||
this.entityTickingChunks = entityTickingChunks;
|
// this.entityTickingChunks = entityTickingChunks;
|
||||||
this.mainThreadTasks = mainThreadTasks;
|
// this.mainThreadTasks = mainThreadTasks;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public void tick() {
|
// public void tick() {
|
||||||
this.taskIndex.set(0);
|
// this.taskIndex.set(0);
|
||||||
this.finishedTasks.set(0);
|
// this.finishedTasks.set(0);
|
||||||
|
//
|
||||||
for (int i = 0; i < parallelism; i++) {
|
// for (int i = 0; i < parallelism; i++) {
|
||||||
trackerExecutor.execute(this::runUpdatePlayers);
|
// trackerExecutor.execute(this::runUpdatePlayers);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// start with updating players
|
// // start with updating players
|
||||||
while (this.taskIndex.get() < this.entityTickingChunks.size()) {
|
// while (this.taskIndex.get() < this.entityTickingChunks.size()) {
|
||||||
this.runMainThreadTasks();
|
// this.runMainThreadTasks();
|
||||||
this.handleChunkUpdates(5); // assist
|
// this.handleChunkUpdates(5); // assist
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// then send changes
|
// // 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
|
||||||
|
//
|
||||||
for (ServerChunkCache.ChunkAndHolder chunkAndHolder : this.entityTickingChunks) {
|
// for (ServerChunkCache.ChunkAndHolder chunkAndHolder : this.entityTickingChunks) {
|
||||||
LevelChunk chunk = chunkAndHolder.chunk();
|
// LevelChunk chunk = chunkAndHolder.chunk();
|
||||||
|
//
|
||||||
if (chunk != null) {
|
// if (chunk != null) {
|
||||||
this.updateChunkEntities(chunk, TrackerStage.SEND_CHANGES);
|
// this.updateChunkEntities(chunk, TrackerStage.SEND_CHANGES);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private void runMainThreadTasks() {
|
// private void runMainThreadTasks() {
|
||||||
try {
|
// try {
|
||||||
Runnable task;
|
// Runnable task;
|
||||||
while ((task = this.mainThreadTasks.poll()) != null) {
|
// while ((task = this.mainThreadTasks.poll()) != null) {
|
||||||
task.run();
|
// task.run();
|
||||||
}
|
// }
|
||||||
} catch (Throwable throwable) {
|
// } catch (Throwable throwable) {
|
||||||
MinecraftServer.LOGGER.warn("Tasks failed while ticking track queue", throwable);
|
// MinecraftServer.LOGGER.warn("Tasks failed while ticking track queue", throwable);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private void runUpdatePlayers() {
|
// private void runUpdatePlayers() {
|
||||||
try {
|
// try {
|
||||||
while (handleChunkUpdates(10));
|
// while (handleChunkUpdates(10));
|
||||||
} finally {
|
// } finally {
|
||||||
this.finishedTasks.incrementAndGet();
|
// this.finishedTasks.incrementAndGet();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private boolean handleChunkUpdates(int tasks) {
|
// private boolean handleChunkUpdates(int tasks) {
|
||||||
int index;
|
// int index;
|
||||||
while ((index = this.taskIndex.getAndAdd(tasks)) < this.entityTickingChunks.size()) {
|
// while ((index = this.taskIndex.getAndAdd(tasks)) < this.entityTickingChunks.size()) {
|
||||||
for (int i = index; i < index + tasks && i < this.entityTickingChunks.size(); i++) {
|
// for (int i = index; i < index + tasks && i < this.entityTickingChunks.size(); i++) {
|
||||||
LevelChunk chunk = this.entityTickingChunks.getChecked(i).chunk();
|
// LevelChunk chunk = this.entityTickingChunks.getChecked(i).chunk();
|
||||||
if (chunk != null) {
|
// if (chunk != null) {
|
||||||
try {
|
// try {
|
||||||
this.updateChunkEntities(chunk, TrackerStage.UPDATE_PLAYERS);
|
// this.updateChunkEntities(chunk, TrackerStage.UPDATE_PLAYERS);
|
||||||
} catch (Throwable throwable) {
|
// } catch (Throwable throwable) {
|
||||||
MinecraftServer.LOGGER.warn("Ticking tracker failed", throwable);
|
// MinecraftServer.LOGGER.warn("Ticking tracker failed", throwable);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private void updateChunkEntities(LevelChunk chunk, TrackerStage trackerStage) {
|
// private void updateChunkEntities(LevelChunk chunk, TrackerStage trackerStage) {
|
||||||
final ChunkEntitySlices entitySlices = chunk.level.moonrise$getEntityLookup().getChunk(chunk.locX, chunk.locZ);
|
// final ChunkEntitySlices entitySlices = chunk.level.moonrise$getEntityLookup().getChunk(chunk.locX, chunk.locZ);
|
||||||
if (entitySlices == null) {
|
// if (entitySlices == null) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
final Entity[] rawEntities = ((IMixinChunkEntitySlicesAccess) (Object) entitySlices).getEntities().getRawData();
|
// final Entity[] rawEntities = ((IMixinChunkEntitySlicesAccess) (Object) entitySlices).getEntities().getRawData();
|
||||||
final ChunkMap chunkMap = chunk.level.chunkSource.chunkMap;
|
// final ChunkMap chunkMap = chunk.level.chunkSource.chunkMap;
|
||||||
|
//
|
||||||
for (int i = 0; i < rawEntities.length; i++) {
|
// for (int i = 0; i < rawEntities.length; i++) {
|
||||||
Entity entity = rawEntities[i];
|
// Entity entity = rawEntities[i];
|
||||||
if (entity != null) {
|
// if (entity != null) {
|
||||||
ChunkMap.TrackedEntity entityTracker = chunkMap.entityMap.get(entity.getId());
|
// ChunkMap.TrackedEntity entityTracker = chunkMap.entityMap.get(entity.getId());
|
||||||
if (entityTracker != null) {
|
// if (entityTracker != null) {
|
||||||
if (trackerStage == TrackerStage.SEND_CHANGES) {
|
// if (trackerStage == TrackerStage.SEND_CHANGES) {
|
||||||
entityTracker.serverEntity.sendChanges();
|
// entityTracker.serverEntity.sendChanges();
|
||||||
} else if (trackerStage == TrackerStage.UPDATE_PLAYERS) {
|
// } else if (trackerStage == TrackerStage.UPDATE_PLAYERS) {
|
||||||
ReferenceList<ServerPlayer> nearbyPlayers = chunkMap.level.moonrise$getNearbyPlayers().getChunk(entity.chunkPosition()).getPlayers(NearbyPlayers.NearbyMapType.VIEW_DISTANCE);
|
// 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
|
// List<ServerPlayer> nearbyPlayersList = new ArrayList<ServerPlayer>(nearbyPlayers.size()); // intentionally typed as List for requirement clarity
|
||||||
nearbyPlayers.forEach(nearbyPlayersList::add);
|
// nearbyPlayers.forEach(nearbyPlayersList::add);
|
||||||
((IMixinChunkMap_TrackedEntityAccess) (Object) entityTracker).callUpdatePlayers(nearbyPlayersList);
|
// ((IMixinChunkMap_TrackedEntityAccess) (Object) entityTracker).callUpdatePlayers(nearbyPlayersList);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "Nitori",
|
"id": "Nitori",
|
||||||
"version": "1.4-SNAPSHOT",
|
"version": "1.5-SNAPSHOT",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"mixins.core.json"
|
"mixins.core.json"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -6,17 +6,16 @@
|
|||||||
"target": "@env(DEFAULT)",
|
"target": "@env(DEFAULT)",
|
||||||
"compatibilityLevel": "JAVA_17",
|
"compatibilityLevel": "JAVA_17",
|
||||||
"server": [
|
"server": [
|
||||||
"ChunkMapMixin",
|
"MixinBlock",
|
||||||
"ChunkMapMixin$TrackedEntity",
|
|
||||||
"MixinBlockPos",
|
"MixinBlockPos",
|
||||||
"MixinChunkEntitySlices",
|
"MixinChunkEntitySlices",
|
||||||
"MixinCraftPlayer",
|
"MixinCraftPlayer",
|
||||||
"MixinEntity",
|
"MixinEntity",
|
||||||
"MixinEntitySectionStorage",
|
"MixinEntitySectionStorage",
|
||||||
"collections.gamerules.MixinGameRules",
|
"MixinGameRules",
|
||||||
"MixinIteratorSafeOrderedReferenceSet",
|
"MixinIteratorSafeOrderedReferenceSet",
|
||||||
"MixinLevelStorageAccess",
|
"MixinLevelStorageAccess",
|
||||||
"entity.micro_opts.MixinMob",
|
"MixinMob",
|
||||||
"MixinNoiseBasedChunkGenerator",
|
"MixinNoiseBasedChunkGenerator",
|
||||||
"MixinPlayer",
|
"MixinPlayer",
|
||||||
"MixinPlayerList",
|
"MixinPlayerList",
|
||||||
@@ -43,7 +42,6 @@
|
|||||||
"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.attributes.AttributeContainerMixin",
|
||||||
"collections.block_entity_tickers.WorldChunkMixin",
|
"collections.block_entity_tickers.WorldChunkMixin",
|
||||||
|
|||||||
Reference in New Issue
Block a user