Add and use reference counted ChunkData

ChunkData is stored directly on chunk holders, entity slices,
and on entities. Currently, this allows access to
NearbyPlayers$TrackedChunk without performing a map lookup.
This commit is contained in:
Spottedleaf
2024-09-04 13:18:00 -07:00
parent d9988c86f4
commit 1c150afe83
18 changed files with 256 additions and 39 deletions

View File

@@ -4,6 +4,10 @@ import ca.spottedleaf.moonrise.common.list.ReferenceList;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.common.util.MoonriseConstants;
import ca.spottedleaf.moonrise.common.util.ChunkSystem;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickConstants;
import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
@@ -11,6 +15,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;
import java.util.ArrayList;
public final class NearbyPlayers {
@@ -76,6 +81,16 @@ public final class NearbyPlayers {
}
}
public void clear() {
if (this.players.isEmpty()) {
return;
}
for (final ServerPlayer player : new ArrayList<>(this.players.keySet())) {
this.removePlayer(player);
}
}
public void tickPlayer(final ServerPlayer player) {
final TrackedPlayer[] players = this.players.get(player);
if (players == null) {
@@ -100,6 +115,10 @@ public final class NearbyPlayers {
return this.byChunk.get(CoordinateUtils.getChunkKey(pos));
}
public TrackedChunk getChunk(final int chunkX, final int chunkZ) {
return this.byChunk.get(CoordinateUtils.getChunkKey(chunkX, chunkZ));
}
public ReferenceList<ServerPlayer> getPlayers(final BlockPos pos, final NearbyMapType type) {
return this.directByChunk[type.ordinal()].get(CoordinateUtils.getChunkKey(pos));
}
@@ -196,9 +215,17 @@ public final class NearbyPlayers {
protected void addCallback(final ServerPlayer parameter, final int chunkX, final int chunkZ) {
final long chunkKey = CoordinateUtils.getChunkKey(chunkX, chunkZ);
NearbyPlayers.this.byChunk.computeIfAbsent(chunkKey, (final long keyInMap) -> {
return new TrackedChunk(keyInMap, NearbyPlayers.this);
}).addPlayer(parameter, this.type);
final TrackedChunk chunk = NearbyPlayers.this.byChunk.get(chunkKey);
final NearbyMapType type = this.type;
if (chunk != null) {
chunk.addPlayer(parameter, type);
} else {
final TrackedChunk created = new TrackedChunk(chunkKey, NearbyPlayers.this);
NearbyPlayers.this.byChunk.put(chunkKey, created);
created.addPlayer(parameter, type);
((ChunkSystemLevel)NearbyPlayers.this.world).moonrise$requestChunkData(chunkKey).nearbyPlayers = created;
}
}
@Override
@@ -214,6 +241,10 @@ public final class NearbyPlayers {
if (chunk.isEmpty()) {
NearbyPlayers.this.byChunk.remove(chunkKey);
final ChunkData chunkData = ((ChunkSystemLevel)NearbyPlayers.this.world).moonrise$releaseChunkData(chunkKey);
if (chunkData != null) {
chunkData.nearbyPlayers = null;
}
}
}
}

View File

@@ -3,6 +3,7 @@ package ca.spottedleaf.moonrise.common.util;
import ca.spottedleaf.concurrentutil.util.Priority;
import ca.spottedleaf.moonrise.common.PlatformHooks;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
import ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader;
import ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemServerChunkCache;

View File

@@ -1,5 +1,6 @@
package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
import com.google.common.collect.ImmutableList;
@@ -49,6 +50,9 @@ abstract class EntityMixin implements ChunkSystemEntity {
@Unique
private FullChunkStatus chunkStatus;
@Unique
private ChunkData chunkData;
@Unique
private int sectionX = Integer.MIN_VALUE;
@@ -76,6 +80,16 @@ abstract class EntityMixin implements ChunkSystemEntity {
this.chunkStatus = status;
}
@Override
public final ChunkData moonrise$getChunkData() {
return this.chunkData;
}
@Override
public final void moonrise$setChunkData(final ChunkData chunkData) {
this.chunkData = chunkData;
}
@Override
public final int moonrise$getSectionX() {
return this.sectionX;

View File

@@ -1,6 +1,9 @@
package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable;
import ca.spottedleaf.moonrise.common.PlatformHooks;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup;
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.dfl.DefaultEntityLookup;
@@ -46,6 +49,9 @@ abstract class LevelMixin implements ChunkSystemLevel, ChunkSystemEntityGetter,
@Unique
private EntityLookup entityLookup;
@Unique
private final ConcurrentLong2ReferenceChainedHashTable<ChunkData> chunkData = new ConcurrentLong2ReferenceChainedHashTable<>();
@Override
public final EntityLookup moonrise$getEntityLookup() {
return this.entityLookup;
@@ -217,6 +223,37 @@ abstract class LevelMixin implements ChunkSystemLevel, ChunkSystemEntityGetter,
// no-op on ClientLevel
}
@Override
public final ChunkData moonrise$getChunkData(final long chunkKey) {
return this.chunkData.get(chunkKey);
}
@Override
public final ChunkData moonrise$getChunkData(final int chunkX, final int chunkZ) {
return this.chunkData.get(CoordinateUtils.getChunkKey(chunkX, chunkZ));
}
@Override
public final ChunkData moonrise$requestChunkData(final long chunkKey) {
return this.chunkData.compute(chunkKey, (final long keyInMap, final ChunkData valueInMap) -> {
if (valueInMap == null) {
final ChunkData ret = new ChunkData();
ret.increaseRef();
return ret;
}
valueInMap.increaseRef();
return valueInMap;
});
}
@Override
public final ChunkData moonrise$releaseChunkData(final long chunkKey) {
return this.chunkData.compute(chunkKey, (final long keyInMap, final ChunkData chunkData) -> {
return chunkData.decreaseRef() == 0 ? null : chunkData;
});
}
/**
* @reason Declare method in this class so that any invocations are virtual, and not interface.
* @author Spottedleaf

View File

@@ -282,7 +282,8 @@ abstract class ServerChunkCacheMixin extends ChunkSource implements ChunkSystemS
*/
@Overwrite
public void getFullChunk(final long pos, final Consumer<LevelChunk> consumer) {
final LevelChunk fullChunk = this.getChunkNow(CoordinateUtils.getChunkX(pos), CoordinateUtils.getChunkZ(pos));
// note: bypass currentlyLoaded from getChunkNow
final LevelChunk fullChunk = this.fullChunks.get(pos);
if (fullChunk != null) {
consumer.accept(fullChunk);
}

View File

@@ -33,7 +33,7 @@ abstract class ChunkMapMixin {
public ServerLevel level;
@Shadow
protected abstract boolean playerIsCloseEnoughForSpawning(ServerPlayer serverPlayer, ChunkPos chunkPos);
public abstract boolean playerIsCloseEnoughForSpawning(ServerPlayer serverPlayer, ChunkPos chunkPos);
/**
* @reason Hook for updating the spawn tracker in distance manager. We add our own hook instead of using the
@@ -116,15 +116,15 @@ abstract class ChunkMapMixin {
*/
@Overwrite
public List<ServerPlayer> getPlayersCloseForSpawning(final ChunkPos pos) {
final List<ServerPlayer> ret = new ArrayList<>();
final ReferenceList<ServerPlayer> players = ((ChunkSystemServerLevel)this.level).moonrise$getNearbyPlayers().getPlayers(
pos, NearbyPlayers.NearbyMapType.SPAWN_RANGE
);
if (players == null) {
return ret;
return new ArrayList<>();
}
List<ServerPlayer> ret = null;
final ServerPlayer[] raw = players.getRawDataUnchecked();
final int len = players.size();
@@ -132,10 +132,15 @@ abstract class ChunkMapMixin {
for (int i = 0; i < len; ++i) {
final ServerPlayer player = raw[i];
if (this.playerIsCloseEnoughForSpawning(player, pos)) {
ret.add(player);
if (ret == null) {
ret = new ArrayList<>(len - i);
ret.add(player);
} else {
ret.add(player);
}
}
}
return ret;
return ret == null ? new ArrayList<>() : ret;
}
}

View File

@@ -1,11 +1,20 @@
package ca.spottedleaf.moonrise.mixin.chunk_tick_iteration;
import ca.spottedleaf.moonrise.common.list.ReferenceList;
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
import com.llamalad7.mixinextras.sugar.Local;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkSource;
import net.minecraft.world.level.chunk.LevelChunk;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@@ -91,6 +100,46 @@ abstract class ServerChunkCacheMixin extends ChunkSource {
return false;
}
/**
* @reason Use the nearby players cache
* @author Spottedleaf
*/
@Redirect(
method = "tickChunks",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/level/ChunkMap;anyPlayerCloseEnoughForSpawning(Lnet/minecraft/world/level/ChunkPos;)Z"
)
)
private boolean useNearbyCache(final ChunkMap instance, final ChunkPos chunkPos,
@Local(ordinal = 0, argsOnly = false) final LevelChunk levelChunk) {
final ChunkData chunkData =
((ChunkSystemChunkHolder)((ChunkSystemLevelChunk)levelChunk).moonrise$getChunkAndHolder().holder())
.moonrise$getRealChunkHolder().holderData;
final NearbyPlayers.TrackedChunk nearbyPlayers = chunkData.nearbyPlayers;
if (nearbyPlayers == null) {
return false;
}
final ReferenceList<ServerPlayer> players = nearbyPlayers.getPlayers(NearbyPlayers.NearbyMapType.SPAWN_RANGE);
if (players == null) {
return false;
}
final ServerPlayer[] raw = players.getRawDataUnchecked();
final int len = players.size();
Objects.checkFromIndexSize(0, len, raw.length);
for (int i = 0; i < len; ++i) {
if (instance.playerIsCloseEnoughForSpawning(raw[i], chunkPos)) {
return true;
}
}
return false;
}
/**
* @reason Clear the iteration array, and at the same time broadcast chunk changes.
* @author Spottedleaf

View File

@@ -67,7 +67,6 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkHolder.PlayerP
)
)
private boolean newTrackerTick(final Iterator<?> iterator) {
final NearbyPlayers nearbyPlayers = ((ChunkSystemServerLevel)this.level).moonrise$getNearbyPlayers();
final ServerEntityLookup entityLookup = (ServerEntityLookup)((ChunkSystemServerLevel)this.level).moonrise$getEntityLookup();;
final ReferenceList<Entity> trackerEntities = entityLookup.trackerEntities;
@@ -78,7 +77,7 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkHolder.PlayerP
if (tracker == null) {
continue;
}
((EntityTrackerTrackedEntity)tracker).moonrise$tick(nearbyPlayers.getChunk(entity.chunkPosition()));
((EntityTrackerTrackedEntity)tracker).moonrise$tick(((ChunkSystemEntity)entity).moonrise$getChunkData().nearbyPlayers);
if (((EntityTrackerTrackedEntity)tracker).moonrise$hasPlayers()
|| ((ChunkSystemEntity)entity).moonrise$getChunkStatus().isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
tracker.serverEntity.sendChanges();

View File

@@ -4,16 +4,16 @@ import ca.spottedleaf.moonrise.common.list.ReferenceList;
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
import ca.spottedleaf.moonrise.common.util.TickThread;
import ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerTrackedEntity;
import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerPlayerConnection;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.List;
import java.util.Set;
@Mixin(ChunkMap.TrackedEntity.class)
@@ -22,26 +22,22 @@ abstract class TrackedEntityMixin implements EntityTrackerTrackedEntity {
@Final
private Set<ServerPlayerConnection> seenBy;
@Shadow
@Final
private int range;
@Shadow
public abstract void updatePlayer(ServerPlayer serverPlayer);
@Shadow
public abstract void removePlayer(ServerPlayer serverPlayer);
/**
* @reason ReferenceOpenHashSet is a better choice than a wrapped IdentityHashMap
* @author Spottedleaf
*/
@Redirect(
method = "<init>",
at = @At(
value = "INVOKE",
target = "Lcom/google/common/collect/Sets;newIdentityHashSet()Ljava/util/Set;"
)
)
private <E> Set<E> useBetterIdentitySet() {
return new ReferenceOpenHashSet<>();
}
@Shadow
protected abstract int scaledRange(final int i);
@Shadow
@Final
Entity entity;
@Unique
private long lastChunkUpdate = -1L;
@@ -126,4 +122,42 @@ abstract class TrackedEntityMixin implements EntityTrackerTrackedEntity {
public final boolean moonrise$hasPlayers() {
return !this.seenBy.isEmpty();
}
/**
* @reason ReferenceOpenHashSet is a better choice than a wrapped IdentityHashMap
* @author Spottedleaf
*/
@Redirect(
method = "<init>",
at = @At(
value = "INVOKE",
target = "Lcom/google/common/collect/Sets;newIdentityHashSet()Ljava/util/Set;"
)
)
private <E> Set<E> useBetterIdentitySet() {
return new ReferenceOpenHashSet<>();
}
/**
* @reason Optimise impl to not retrieve indirect passengers unless needed
* @author Spottedleaf
*/
@Overwrite
public int getEffectiveRange() {
int range = this.range;
final Entity entity = this.entity;
if (entity.getPassengers() == ImmutableList.<Entity>of()) {
return this.scaledRange(range);
}
// note: we change to List
final List<Entity> passengers = (List<Entity>)entity.getIndirectPassengers();
for (int i = 0, len = passengers.size(); i < len; ++i) {
// note: max should be branchless
range = Math.max(range, passengers.get(i).getType().clientTrackingRange() << 4);
}
return range;
}
}

View File

@@ -1,5 +1,6 @@
package ca.spottedleaf.moonrise.patches.chunk_system.entity;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.monster.Shulker;
@@ -19,6 +20,10 @@ public interface ChunkSystemEntity {
public void moonrise$setChunkStatus(final FullChunkStatus status);
public ChunkData moonrise$getChunkData();
public void moonrise$setChunkData(final ChunkData chunkData);
public int moonrise$getSectionX();
public void moonrise$setSectionX(final int x);

View File

@@ -1,5 +1,6 @@
package ca.spottedleaf.moonrise.patches.chunk_system.level;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
@@ -19,4 +20,12 @@ public interface ChunkSystemLevel {
public void moonrise$midTickTasks();
public ChunkData moonrise$getChunkData(final long chunkKey);
public ChunkData moonrise$getChunkData(final int chunkX, final int chunkZ);
public ChunkData moonrise$requestChunkData(final long chunkKey);
public ChunkData moonrise$releaseChunkData(final long chunkKey);
}

View File

@@ -0,0 +1,21 @@
package ca.spottedleaf.moonrise.patches.chunk_system.level.chunk;
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
public final class ChunkData {
private int referenceCount = 0;
public NearbyPlayers.TrackedChunk nearbyPlayers; // Moonrise - nearby players
public ChunkData() {
}
public int increaseRef() {
return ++this.referenceCount;
}
public int decreaseRef() {
return --this.referenceCount;
}
}

View File

@@ -1,6 +1,7 @@
package ca.spottedleaf.moonrise.patches.chunk_system.level.entity;
import ca.spottedleaf.moonrise.common.list.EntityList;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity;
import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
@@ -42,6 +43,7 @@ public final class ChunkEntitySlices {
private final EntityList entities = new EntityList();
public FullChunkStatus status;
public final ChunkData chunkData;
private boolean isTransient;
@@ -54,7 +56,7 @@ public final class ChunkEntitySlices {
}
public ChunkEntitySlices(final Level world, final int chunkX, final int chunkZ, final FullChunkStatus status,
final int minSection, final int maxSection) { // inclusive, inclusive
final ChunkData chunkData, final int minSection, final int maxSection) { // inclusive, inclusive
this.minSection = minSection;
this.maxSection = maxSection;
this.chunkX = chunkX;
@@ -67,6 +69,7 @@ public final class ChunkEntitySlices {
this.entitiesByType = new Reference2ObjectOpenHashMap<>();
this.status = status;
this.chunkData = chunkData;
}
public static List<Entity> readEntities(final ServerLevel world, final CompoundTag compoundTag) {
@@ -223,6 +226,7 @@ public final class ChunkEntitySlices {
return false;
}
((ChunkSystemEntity)entity).moonrise$setChunkStatus(this.status);
((ChunkSystemEntity)entity).moonrise$setChunkData(this.chunkData);
final int sectionIndex = chunkSection - this.minSection;
this.allEntities.addEntity(entity, sectionIndex);
@@ -256,6 +260,7 @@ public final class ChunkEntitySlices {
return false;
}
((ChunkSystemEntity)entity).moonrise$setChunkStatus(null);
((ChunkSystemEntity)entity).moonrise$setChunkData(null);
final int sectionIndex = chunkSection - this.minSection;
this.allEntities.removeEntity(entity, sectionIndex);
@@ -788,4 +793,4 @@ public final class ChunkEntitySlices {
return false;
}
}
}
}

View File

@@ -46,7 +46,8 @@ public final class ClientEntityLookup extends EntityLookup {
final ChunkEntitySlices ret = new ChunkEntitySlices(
this.world, chunkX, chunkZ,
ticking ? FullChunkStatus.ENTITY_TICKING : FullChunkStatus.FULL, WorldUtil.getMinSection(this.world), WorldUtil.getMaxSection(this.world)
ticking ? FullChunkStatus.ENTITY_TICKING : FullChunkStatus.FULL, null,
WorldUtil.getMinSection(this.world), WorldUtil.getMaxSection(this.world)
);
// note: not handled by superclass

View File

@@ -32,7 +32,7 @@ public final class DefaultEntityLookup extends EntityLookup {
protected ChunkEntitySlices createEntityChunk(final int chunkX, final int chunkZ, final boolean transientChunk) {
final ChunkEntitySlices ret = new ChunkEntitySlices(
this.world, chunkX, chunkZ, FullChunkStatus.FULL,
WorldUtil.getMinSection(this.world), WorldUtil.getMaxSection(this.world)
null, WorldUtil.getMinSection(this.world), WorldUtil.getMaxSection(this.world)
);
// note: not handled by superclass

View File

@@ -5,7 +5,6 @@ import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTabl
import ca.spottedleaf.concurrentutil.util.Priority;
import ca.spottedleaf.moonrise.common.PlatformHooks;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.common.util.MoonriseCommon;
import ca.spottedleaf.moonrise.common.util.TickThread;
import ca.spottedleaf.moonrise.common.util.WorldUtil;
import ca.spottedleaf.moonrise.common.util.ChunkSystem;
@@ -1023,11 +1022,10 @@ public final class ChunkHolderManager {
}
private void removeChunkHolder(final NewChunkHolder holder) {
holder.markUnloaded();
holder.onUnload();
this.autoSaveQueue.remove(holder);
ChunkSystem.onChunkHolderDelete(this.world, holder.vanillaChunkHolder);
this.chunkHolders.remove(CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ));
}
// note: never call while inside the chunk system, this will absolutely break everything

View File

@@ -14,7 +14,9 @@ import ca.spottedleaf.moonrise.common.util.WorldUtil;
import ca.spottedleaf.moonrise.common.util.ChunkSystem;
import ca.spottedleaf.moonrise.patches.chunk_system.ChunkSystemFeatures;
import ca.spottedleaf.moonrise.patches.chunk_system.async_save.AsyncChunkSaveData;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkStatus;
@@ -61,6 +63,8 @@ public final class NewChunkHolder {
private static final Logger LOGGER = LoggerFactory.getLogger(NewChunkHolder.class);
public final ChunkData holderData;
public final ServerLevel world;
public final int chunkX;
public final int chunkZ;
@@ -92,7 +96,7 @@ public final class NewChunkHolder {
if (this.entityChunk == null) {
ret = this.entityChunk = new ChunkEntitySlices(
this.world, this.chunkX, this.chunkZ, this.getChunkStatus(),
WorldUtil.getMinSection(this.world), WorldUtil.getMaxSection(this.world)
this.holderData, WorldUtil.getMinSection(this.world), WorldUtil.getMaxSection(this.world)
);
ret.setTransient(transientChunk);
@@ -654,6 +658,7 @@ public final class NewChunkHolder {
world.getLightEngine(), null, world.getChunkSource().chunkMap
);
((ChunkSystemChunkHolder)this.vanillaChunkHolder).moonrise$setRealChunkHolder(this);
this.holderData = ((ChunkSystemLevel)this.world).moonrise$requestChunkData(CoordinateUtils.getChunkKey(chunkX, chunkZ));
}
public ChunkAccess getCurrentChunk() {
@@ -753,8 +758,9 @@ public final class NewChunkHolder {
/** Unloaded from chunk map */
private boolean unloaded;
void markUnloaded() {
void onUnload() {
this.unloaded = true;
((ChunkSystemLevel)this.world).moonrise$releaseChunkData(CoordinateUtils.getChunkKey(this.chunkX, this.chunkZ));
}
private boolean inUnloadQueue = false;

View File

@@ -44,6 +44,7 @@ accessible method net/minecraft/server/level/ChunkMap upgradeChunkTag (Lnet/mine
accessible field net/minecraft/server/level/ChunkMap worldGenContext Lnet/minecraft/world/level/chunk/status/WorldGenContext;
accessible field net/minecraft/server/level/ChunkMap tickingGenerated Ljava/util/concurrent/atomic/AtomicInteger;
accessible field net/minecraft/server/level/ChunkMap progressListener Lnet/minecraft/server/level/progress/ChunkProgressListener;
accessible method net/minecraft/server/level/ChunkMap playerIsCloseEnoughForSpawning (Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/world/level/ChunkPos;)Z
# ChunkLevel
accessible field net/minecraft/server/level/ChunkLevel FULL_CHUNK_LEVEL I