Added lazy mode
This commit is contained in:
parent
781e980286
commit
ba559f64c9
@ -7,6 +7,7 @@ import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@ -209,6 +210,9 @@ public class MinecraftLandGenerator implements Runnable {
|
||||
+ "in slower generation. Smaller values will result in starting the server more often, which has some overhead and takes time. "
|
||||
+ "Set this as high as possible without totally filling up your RAM.")
|
||||
private int maxLoaded;
|
||||
@Option(names = { "--lazy", "-l" },
|
||||
description = "Scan the world for existing chunks and skip them.")
|
||||
private boolean lazy;
|
||||
|
||||
@Override
|
||||
protected void runGenerate() {
|
||||
@ -216,6 +220,21 @@ public class MinecraftLandGenerator implements Runnable {
|
||||
for (int x = bounds.x; x < bounds.x + bounds.w; x++)
|
||||
for (int z = bounds.z; z < bounds.z + bounds.h; z++)
|
||||
loadedChunks.add(new Vector2i(x, z));
|
||||
if (lazy) {
|
||||
log.info("Searching for existing chunks to be skipped");
|
||||
/*
|
||||
* All chunks to load -> The set of region files containing them -> (The chunks in those region files -> to world coordinates)
|
||||
* -> to list -> remove from original list
|
||||
*/
|
||||
int size = loadedChunks.size();
|
||||
loadedChunks.removeAll(
|
||||
loadedChunks.stream().map(v -> new Vector2i(v.x >> 5, v.y >> 5)).distinct()
|
||||
.flatMap(v -> world.availableChunks(v, dimension)
|
||||
.map(w -> new Vector2i((v.x << 5) | w.x, (v.y << 5) | w.y)))
|
||||
.collect(Collectors.toList()));
|
||||
log.debug("Removed " + (size - loadedChunks.size())
|
||||
+ " chunks that are already present");
|
||||
}
|
||||
log.info("Generating world");
|
||||
if (loadedChunks.size() < 5000)
|
||||
log.debug("Chunks to generate: " + loadedChunks);
|
||||
@ -224,7 +243,7 @@ public class MinecraftLandGenerator implements Runnable {
|
||||
for (int i = 0; i < stepCount; i++) {
|
||||
List<Vector2i> batch = loadedChunks.subList(i * maxLoaded,
|
||||
Math.min((i + 1) * maxLoaded, loadedChunks.size() - 1));
|
||||
log.info("Generating batch " + i + " / " + stepCount + " with " + batch.size()
|
||||
log.info("Generating batch " + (i + 1) + " / " + stepCount + " with " + batch.size()
|
||||
+ " chunks");
|
||||
try {
|
||||
world.setLoadedChunks(batch, dimension);
|
||||
|
@ -1,12 +1,16 @@
|
||||
package morlok8k.MinecraftLandGenerator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@ -14,6 +18,7 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@ -198,4 +203,47 @@ public class World {
|
||||
return IntStream.rangeClosed(0, (int) stepCount).mapToObj(i -> start + (int) (realStep * i))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* List all available chunks in a region file.
|
||||
*
|
||||
* @param regionX
|
||||
* the x coordinate of the region file in the world
|
||||
* @param regionZ
|
||||
* the z coordinate of the region file in the world
|
||||
* @param dimension
|
||||
* the dimension of the region file in the world
|
||||
* @return a stream of all chunks in the given region file, in coordinates relative to the region file's origin (not in world coordinates)
|
||||
* @see #availableChunks(Vector2i, Dimension)
|
||||
*/
|
||||
public List<Vector2i> availableChunks(int regionX, int regionZ, Dimension dimension) {
|
||||
return availableChunks(new Vector2i(regionX, regionZ), dimension)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* List all available chunks in a region file.
|
||||
*
|
||||
* @param regionCoords
|
||||
* the coordinates of the region file
|
||||
* @param dimension
|
||||
* the dimension of the region file in the world
|
||||
* @return a stream of all chunks in the given region file, in coordinates relative to the region file's origin (not in world coordinates)
|
||||
* @see #availableChunks(int, int, Dimension)
|
||||
*/
|
||||
public Stream<Vector2i> availableChunks(Vector2i regionCoords, Dimension dimension) {
|
||||
Path path = world.resolve(dimension.path).resolve("region")
|
||||
.resolve("r." + regionCoords.x + "." + regionCoords.y + ".mca");
|
||||
if (!Files.exists(path)) return Collections.<Vector2i> emptyList().stream();
|
||||
try (FileChannel channel = FileChannel.open(path, StandardOpenOption.READ)) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(4096);
|
||||
channel.read(buffer);
|
||||
buffer.flip();
|
||||
return IntStream.range(0, buffer.capacity()).filter(i -> buffer.get(i) != 0)
|
||||
.mapToObj(i -> new Vector2i(i & 31, i >> 5));
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not open region file " + path + ", assuming it contains no chunks", e);
|
||||
return Collections.<Vector2i> emptyList().stream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user