Skip to content

Commit

Permalink
Added lazy mode (untested)
Browse files Browse the repository at this point in the history
  • Loading branch information
piegamesde committed Dec 7, 2018
1 parent 781e980 commit fd94130
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
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;
Expand Down Expand Up @@ -209,13 +210,31 @@ public static class ForceloadChunks extends CommandLineHelper {
+ "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() {
ArrayList<Vector2i> loadedChunks = new ArrayList<>();
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);
Expand All @@ -224,7 +243,7 @@ protected void runGenerate() {
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);
Expand Down
48 changes: 48 additions & 0 deletions src/main/java/morlok8k/MinecraftLandGenerator/World.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
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;
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;
Expand Down Expand Up @@ -198,4 +203,47 @@ private static List<Integer> generateLinearSpawnpoints(int start, int length, in
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("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();
}
}
}

0 comments on commit fd94130

Please sign in to comment.