Search in sources :

Example 1 with SimpleEntityLookupInterface

use of carpet.fakes.SimpleEntityLookupInterface in project fabric-carpet by gnembon.

the class ChunkMap_scarpetChunkCreationMixin method regenerateChunkRegion.

@Override
public Map<String, Integer> regenerateChunkRegion(final List<ChunkPos> requestedChunksList) {
    final Object2IntMap<String> report = new Object2IntOpenHashMap<>();
    final Set<ChunkPos> requestedChunks = new HashSet<>(requestedChunksList);
    // Load requested chunks
    final Set<ChunkPos> existingChunks = this.loadExistingChunks(requestedChunks, report);
    // Finish pending generation stages
    // This ensures that no generation events will be put back on the main thread after the chunks have been deleted
    final Set<ChunkAccess> affectedChunks = new HashSet<>();
    for (final ChunkPos pos : existingChunks) affectedChunks.add(this.getCurrentChunk(pos));
    report.put("affected_chunks", affectedChunks.size());
    // Load neighbors for light removal
    final Set<ChunkPos> neighbors = new HashSet<>();
    for (final ChunkAccess chunk : affectedChunks) {
        final ChunkPos pos = chunk.getPos();
        for (int x = -1; x <= 1; ++x) for (int z = -1; z <= 1; ++z) if (x != 0 || z != 0) {
            final ChunkPos nPos = new ChunkPos(pos.x + x, pos.z + z);
            if (!requestedChunks.contains(nPos))
                neighbors.add(nPos);
        }
    }
    this.loadExistingChunks(neighbors);
    // Determine affected neighbors
    final Set<ChunkAccess> affectedNeighbors = new HashSet<>();
    for (final ChunkPos pos : neighbors) {
        final ChunkAccess chunk = this.getCurrentChunk(pos);
        if (chunk.getStatus().isOrAfter(ChunkStatus.LIGHT.getParent()))
            affectedNeighbors.add(chunk);
    }
    for (final ChunkAccess chunk : affectedChunks) {
        final ChunkPos pos = chunk.getPos();
        // remove entities
        long longPos = pos.toLong();
        if (this.entitiesInLevel.contains(longPos) && chunk instanceof LevelChunk)
            ((SimpleEntityLookupInterface<Entity>) ((ServerWorldInterface) level).getEntityLookupCMPublic()).getChunkEntities(pos).forEach(entity -> {
                if (!(entity instanceof Player))
                    entity.discard();
            });
        if (chunk instanceof LevelChunk)
            ((LevelChunk) chunk).setLoaded(false);
        if (this.entitiesInLevel.remove(pos.toLong()) && chunk instanceof LevelChunk)
            // block entities only
            this.level.unload((LevelChunk) chunk);
        ((ServerLightingProviderInterface) this.lightEngine).invokeUpdateChunkStatus(pos);
        ((ServerLightingProviderInterface) this.lightEngine).removeLightData(chunk);
        this.progressListener.onStatusChange(pos, null);
    }
    for (final ChunkAccess chunk : affectedChunks) {
        final ChunkPos cPos = chunk.getPos();
        final long pos = cPos.toLong();
        final ChunkHolder oldHolder = this.updatingChunkMap.remove(pos);
        final ChunkHolder newHolder = new ChunkHolder(cPos, oldHolder.getTicketLevel(), level, this.lightEngine, this.queueSorter, (ChunkHolder.PlayerProvider) this);
        // enable chunk blending?
        ((ChunkHolderInterface) newHolder).setDefaultProtoChunk(cPos, this.mainThreadExecutor, level);
        this.updatingChunkMap.put(pos, newHolder);
        ((ChunkTicketManagerInterface) this.distanceManager).replaceHolder(oldHolder, newHolder);
    }
    this.modified = true;
    this.promoteChunkMap();
    for (final ChunkAccess chunk : affectedNeighbors) ((ServerLightingProviderInterface) this.lightEngine).removeLightData(chunk);
    for (final ChunkAccess chunk : affectedNeighbors) this.addRelightTicket(chunk.getPos());
    this.tickTicketManager();
    final List<CompletableFuture<?>> lightFutures = new ArrayList<>();
    for (final ChunkAccess chunk : affectedNeighbors) {
        final ChunkPos pos = chunk.getPos();
        lightFutures.add(this.getChunkRangeFuture(pos, 1, (pos_) -> ChunkStatus.LIGHT).thenCompose(either -> either.map(list -> ((ServerLightingProviderInterface) this.lightEngine).relight(chunk), unloaded -> {
            this.releaseRelightTicket(pos);
            return CompletableFuture.completedFuture(null);
        })));
    }
    // Force generation to previous states
    // This ensures that the world is in a consistent state after this method
    // Also, this is needed to ensure chunks are saved to disk
    final Map<ChunkPos, ChunkStatus> targetGenerationStatus = affectedChunks.stream().collect(Collectors.toMap(ChunkAccess::getPos, ChunkAccess::getStatus));
    for (final Entry<ChunkPos, ChunkStatus> entry : targetGenerationStatus.entrySet()) this.addTicket(entry.getKey(), entry.getValue());
    this.tickTicketManager();
    final List<Pair<ChunkStatus, CompletableFuture<?>>> targetGenerationFutures = new ArrayList<>();
    for (final Entry<ChunkPos, ChunkStatus> entry : targetGenerationStatus.entrySet()) targetGenerationFutures.add(Pair.of(entry.getValue(), this.updatingChunkMap.get(entry.getKey().toLong()).getOrScheduleFuture(entry.getValue(), (ChunkMap) (Object) this)));
    final Map<ChunkStatus, List<CompletableFuture<?>>> targetGenerationFuturesGrouped = targetGenerationFutures.stream().collect(Collectors.groupingBy(Pair::getKey, Collectors.mapping(Entry::getValue, Collectors.toList())));
    for (final ChunkStatus status : ChunkStatus.getStatusList()) {
        final List<CompletableFuture<?>> futures = targetGenerationFuturesGrouped.get(status);
        if (futures == null)
            continue;
        report.put("layer_count_" + status.getName(), futures.size());
        final long start = System.currentTimeMillis();
        this.waitFor(futures);
        report.put("layer_time_" + status.getName(), (int) (System.currentTimeMillis() - start));
    }
    report.put("relight_count", lightFutures.size());
    final long relightStart = System.currentTimeMillis();
    this.waitFor(lightFutures);
    report.put("relight_time", (int) (System.currentTimeMillis() - relightStart));
    return report;
}
Also used : ChunkTicketManagerInterface(carpet.fakes.ChunkTicketManagerInterface) ThreadedAnvilChunkStorageInterface(carpet.fakes.ThreadedAnvilChunkStorageInterface) Either(com.mojang.datafixers.util.Either) Inject(org.spongepowered.asm.mixin.injection.Inject) CHUNK_GENERATED(carpet.script.CarpetEventServer.Event.CHUNK_GENERATED) CallbackInfoReturnable(org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable) Future(java.util.concurrent.Future) MinecraftServer(net.minecraft.server.MinecraftServer) Pair(org.apache.commons.lang3.tuple.Pair) Mixin(org.spongepowered.asm.mixin.Mixin) Map(java.util.Map) SimpleEntityLookupInterface(carpet.fakes.SimpleEntityLookupInterface) Object2IntOpenHashMap(it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap) TickTask(net.minecraft.server.TickTask) RegionFile(net.minecraft.world.level.chunk.storage.RegionFile) At(org.spongepowered.asm.mixin.injection.At) LongSet(it.unimi.dsi.fastutil.longs.LongSet) ChunkLoadingFailure(net.minecraft.server.level.ChunkHolder.ChunkLoadingFailure) ChunkProgressListener(net.minecraft.server.level.progress.ChunkProgressListener) Set(java.util.Set) CHUNK_LOADED(carpet.script.CarpetEventServer.Event.CHUNK_LOADED) ThreadedLevelLightEngine(net.minecraft.server.level.ThreadedLevelLightEngine) BlockableEventLoop(net.minecraft.util.thread.BlockableEventLoop) Final(org.spongepowered.asm.mixin.Final) Collectors(java.util.stream.Collectors) Player(net.minecraft.world.entity.player.Player) ChunkAccess(net.minecraft.world.level.chunk.ChunkAccess) ChunkTaskPriorityQueueSorter(net.minecraft.server.level.ChunkTaskPriorityQueueSorter) List(java.util.List) Util(net.minecraft.Util) TicketType(net.minecraft.server.level.TicketType) Entry(java.util.Map.Entry) Shadow(org.spongepowered.asm.mixin.Shadow) LevelChunk(net.minecraft.world.level.chunk.LevelChunk) ChunkHolder(net.minecraft.server.level.ChunkHolder) Unique(org.spongepowered.asm.mixin.Unique) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) ServerWorldInterface(carpet.fakes.ServerWorldInterface) ChunkMap(net.minecraft.server.level.ChunkMap) DistanceManager(net.minecraft.server.level.ChunkMap.DistanceManager) ServerLevel(net.minecraft.server.level.ServerLevel) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) IntFunction(java.util.function.IntFunction) WorldTools(carpet.script.utils.WorldTools) ServerLightingProviderInterface(carpet.fakes.ServerLightingProviderInterface) ChunkHolderInterface(carpet.fakes.ChunkHolderInterface) Long2ObjectLinkedOpenHashMap(it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap) ChunkPos(net.minecraft.world.level.ChunkPos) Entity(net.minecraft.world.entity.Entity) Object2IntMap(it.unimi.dsi.fastutil.objects.Object2IntMap) ChunkStatus(net.minecraft.world.level.chunk.ChunkStatus) ChunkHolder(net.minecraft.server.level.ChunkHolder) ArrayList(java.util.ArrayList) ChunkAccess(net.minecraft.world.level.chunk.ChunkAccess) CompletableFuture(java.util.concurrent.CompletableFuture) ChunkMap(net.minecraft.server.level.ChunkMap) Entry(java.util.Map.Entry) ChunkTicketManagerInterface(carpet.fakes.ChunkTicketManagerInterface) Object2IntOpenHashMap(it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap) ChunkPos(net.minecraft.world.level.ChunkPos) List(java.util.List) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Pair(org.apache.commons.lang3.tuple.Pair) Player(net.minecraft.world.entity.player.Player) LevelChunk(net.minecraft.world.level.chunk.LevelChunk) SimpleEntityLookupInterface(carpet.fakes.SimpleEntityLookupInterface) ChunkHolderInterface(carpet.fakes.ChunkHolderInterface) ChunkStatus(net.minecraft.world.level.chunk.ChunkStatus) ServerLightingProviderInterface(carpet.fakes.ServerLightingProviderInterface)

Aggregations

ChunkHolderInterface (carpet.fakes.ChunkHolderInterface)1 ChunkTicketManagerInterface (carpet.fakes.ChunkTicketManagerInterface)1 ServerLightingProviderInterface (carpet.fakes.ServerLightingProviderInterface)1 ServerWorldInterface (carpet.fakes.ServerWorldInterface)1 SimpleEntityLookupInterface (carpet.fakes.SimpleEntityLookupInterface)1 ThreadedAnvilChunkStorageInterface (carpet.fakes.ThreadedAnvilChunkStorageInterface)1 CHUNK_GENERATED (carpet.script.CarpetEventServer.Event.CHUNK_GENERATED)1 CHUNK_LOADED (carpet.script.CarpetEventServer.Event.CHUNK_LOADED)1 WorldTools (carpet.script.utils.WorldTools)1 Either (com.mojang.datafixers.util.Either)1 Long2ObjectLinkedOpenHashMap (it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap)1 LongSet (it.unimi.dsi.fastutil.longs.LongSet)1 Object2IntMap (it.unimi.dsi.fastutil.objects.Object2IntMap)1 Object2IntOpenHashMap (it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Map (java.util.Map)1 Entry (java.util.Map.Entry)1