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:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user