Search in sources :

Example 1 with SingleThreadQueueExtent

use of com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent in project FastAsyncWorldEdit by IntellectualSites.

the class Regenerator method generate.

private boolean generate() throws Exception {
    if (generateConcurrent) {
        // Using concurrent chunk generation
        executor = Executors.newFixedThreadPool(Settings.settings().QUEUE.PARALLEL_THREADS, new ThreadFactoryBuilder().setNameFormat("fawe-regen-%d").build());
    }
    // else using sequential chunk generation, concurrent not supported
    // TODO: can we get that required radius down without affecting chunk generation (e.g. strucures, features, ...)?
    // for now it is working well and fast, if we are bored in the future we could do the research (a lot of it) to reduce the border radius
    // generate chunk coords lists with a certain radius
    Int2ObjectOpenHashMap<List<Long>> chunkCoordsForRadius = new Int2ObjectOpenHashMap<>();
    chunkStati.keySet().stream().map(ChunkStatusWrapper::requiredNeighborChunkRadius0).distinct().forEach(radius -> {
        if (radius == -1) {
            // ignore ChunkStatus.EMPTY
            return;
        }
        // 9 = 8 + 1, 8: max border radius used in chunk stages, 1: need 1 extra chunk for chunk
        int border = 10 - radius;
        // features to generate at the border of the region
        chunkCoordsForRadius.put(radius, getChunkCoordsRegen(region, border));
    });
    // create chunks
    for (Long xz : chunkCoordsForRadius.get(0)) {
        ProtoChunk chunk = createProtoChunk(MathMan.unpairIntX(xz), MathMan.unpairIntY(xz));
        protoChunks.put(xz, chunk);
    }
    // generate lists for RegionLimitedWorldAccess, need to be square with odd length (e.g. 17x17), 17 = 1 middle chunk + 8 border chunks * 2
    Int2ObjectOpenHashMap<Long2ObjectOpenHashMap<List<IChunkAccess>>> worldlimits = new Int2ObjectOpenHashMap<>();
    chunkStati.keySet().stream().map(ChunkStatusWrapper::requiredNeighborChunkRadius0).distinct().forEach(radius -> {
        if (radius == -1) {
            // ignore ChunkStatus.EMPTY
            return;
        }
        Long2ObjectOpenHashMap<List<IChunkAccess>> map = new Long2ObjectOpenHashMap<>();
        for (Long xz : chunkCoordsForRadius.get(radius)) {
            int x = MathMan.unpairIntX(xz);
            int z = MathMan.unpairIntY(xz);
            List<IChunkAccess> l = new ArrayList<>((radius + 1 + radius) * (radius + 1 + radius));
            for (int zz = z - radius; zz <= z + radius; zz++) {
                // order is important, first z then x
                for (int xx = x - radius; xx <= x + radius; xx++) {
                    l.add(protoChunks.get(MathMan.pairInt(xx, zz)));
                }
            }
            map.put(xz, l);
        }
        worldlimits.put(radius, map);
    });
    // run generation tasks excluding FULL chunk status
    for (Map.Entry<ChunkStatus, Concurrency> entry : chunkStati.entrySet()) {
        ChunkStatus chunkStatus = entry.getKey();
        int radius = chunkStatus.requiredNeighborChunkRadius0();
        List<Long> coords = chunkCoordsForRadius.get(radius);
        if (this.generateConcurrent && entry.getValue() == Concurrency.RADIUS) {
            SequentialTasks<ConcurrentTasks<SequentialTasks<Long>>> tasks = getChunkStatusTaskRows(coords, radius);
            for (ConcurrentTasks<SequentialTasks<Long>> para : tasks) {
                List<Runnable> scheduled = new ArrayList<>(tasks.size());
                for (SequentialTasks<Long> row : para) {
                    scheduled.add(() -> {
                        for (Long xz : row) {
                            chunkStatus.processChunkSave(xz, worldlimits.get(radius).get(xz));
                        }
                    });
                }
                try {
                    List<Future<?>> futures = new ArrayList<>();
                    scheduled.forEach(task -> futures.add(executor.submit(task)));
                    for (Future<?> future : futures) {
                        future.get();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } else if (this.generateConcurrent && entry.getValue() == Concurrency.FULL) {
            // every chunk can be processed individually
            List<Runnable> scheduled = new ArrayList<>(coords.size());
            for (long xz : coords) {
                scheduled.add(() -> {
                    chunkStatus.processChunkSave(xz, worldlimits.get(radius).get(xz));
                });
            }
            try {
                List<Future<?>> futures = new ArrayList<>();
                scheduled.forEach(task -> futures.add(executor.submit(task)));
                for (Future<?> future : futures) {
                    future.get();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            // run sequential
            for (long xz : coords) {
                chunkStatus.processChunkSave(xz, worldlimits.get(radius).get(xz));
            }
        }
    }
    // convert to proper chunks
    for (Long xz : chunkCoordsForRadius.get(0)) {
        ProtoChunk proto = protoChunks.get(xz);
        chunks.put(xz, createChunk(proto));
    }
    // final chunkstatus
    ChunkStatus FULL = getFullChunkStatus();
    for (Long xz : chunkCoordsForRadius.get(0)) {
        // FULL.requiredNeighbourChunkRadius() == 0!
        Chunk chunk = chunks.get(xz);
        FULL.processChunkSave(xz, Arrays.asList(chunk));
    }
    // populate
    List<BlockPopulator> populators = getBlockPopulators();
    for (Long xz : chunkCoordsForRadius.get(0)) {
        int x = MathMan.unpairIntX(xz);
        int z = MathMan.unpairIntY(xz);
        // prepare chunk seed
        Random random = getChunkRandom(seed, x, z);
        // actually populate
        Chunk c = chunks.get(xz);
        populators.forEach(pop -> {
            populate(c, random, pop);
        });
    }
    source = new SingleThreadQueueExtent(BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMinHeight() : 0, BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMaxHeight() : 256);
    source.init(target, initSourceQueueCache(), null);
    return true;
}
Also used : ThreadFactoryBuilder(com.google.common.util.concurrent.ThreadFactoryBuilder) Arrays(java.util.Arrays) SingleThreadQueueExtent(com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent) BlockVector2(com.sk89q.worldedit.math.BlockVector2) BlockVector3(com.sk89q.worldedit.math.BlockVector3) CuboidRegion(com.sk89q.worldedit.regions.CuboidRegion) Random(java.util.Random) CompletableFuture(java.util.concurrent.CompletableFuture) Function(java.util.function.Function) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Future(java.util.concurrent.Future) WorldEditException(com.sk89q.worldedit.WorldEditException) RegenOptions(com.sk89q.worldedit.world.RegenOptions) Long2ObjectOpenHashMap(it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap) Map(java.util.Map) Region(com.sk89q.worldedit.regions.Region) ExecutorService(java.util.concurrent.ExecutorService) BlockPopulator(org.bukkit.generator.BlockPopulator) Int2ObjectOpenHashMap(it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap) LogManagerCompat(com.sk89q.worldedit.internal.util.LogManagerCompat) Iterator(java.util.Iterator) IChunkCache(com.fastasyncworldedit.core.queue.IChunkCache) Settings(com.fastasyncworldedit.core.configuration.Settings) BukkitWorld(com.sk89q.worldedit.bukkit.BukkitWorld) Long2ObjectLinkedOpenHashMap(it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap) Collectors(java.util.stream.Collectors) Executors(java.util.concurrent.Executors) MathMan(com.fastasyncworldedit.core.util.MathMan) List(java.util.List) Logger(org.apache.logging.log4j.Logger) BaseBlock(com.sk89q.worldedit.world.block.BaseBlock) Comparator(java.util.Comparator) Pattern(com.sk89q.worldedit.function.pattern.Pattern) IChunkGet(com.fastasyncworldedit.core.queue.IChunkGet) Extent(com.sk89q.worldedit.extent.Extent) BiomeType(com.sk89q.worldedit.world.biome.BiomeType) SingleThreadQueueExtent(com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent) ArrayList(java.util.ArrayList) Random(java.util.Random) ThreadFactoryBuilder(com.google.common.util.concurrent.ThreadFactoryBuilder) ArrayList(java.util.ArrayList) List(java.util.List) Int2ObjectOpenHashMap(it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap) Long2ObjectOpenHashMap(it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap) WorldEditException(com.sk89q.worldedit.WorldEditException) BlockPopulator(org.bukkit.generator.BlockPopulator) CompletableFuture(java.util.concurrent.CompletableFuture) Future(java.util.concurrent.Future) LinkedHashMap(java.util.LinkedHashMap) Long2ObjectOpenHashMap(it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap) Map(java.util.Map) Int2ObjectOpenHashMap(it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap) Long2ObjectLinkedOpenHashMap(it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap)

Aggregations

Settings (com.fastasyncworldedit.core.configuration.Settings)1 IChunkCache (com.fastasyncworldedit.core.queue.IChunkCache)1 IChunkGet (com.fastasyncworldedit.core.queue.IChunkGet)1 SingleThreadQueueExtent (com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent)1 MathMan (com.fastasyncworldedit.core.util.MathMan)1 ThreadFactoryBuilder (com.google.common.util.concurrent.ThreadFactoryBuilder)1 WorldEditException (com.sk89q.worldedit.WorldEditException)1 BukkitWorld (com.sk89q.worldedit.bukkit.BukkitWorld)1 Extent (com.sk89q.worldedit.extent.Extent)1 Pattern (com.sk89q.worldedit.function.pattern.Pattern)1 LogManagerCompat (com.sk89q.worldedit.internal.util.LogManagerCompat)1 BlockVector2 (com.sk89q.worldedit.math.BlockVector2)1 BlockVector3 (com.sk89q.worldedit.math.BlockVector3)1 CuboidRegion (com.sk89q.worldedit.regions.CuboidRegion)1 Region (com.sk89q.worldedit.regions.Region)1 RegenOptions (com.sk89q.worldedit.world.RegenOptions)1 BiomeType (com.sk89q.worldedit.world.biome.BiomeType)1 BaseBlock (com.sk89q.worldedit.world.block.BaseBlock)1 Int2ObjectOpenHashMap (it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap)1 Long2ObjectLinkedOpenHashMap (it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap)1