tweaks to region generator & cache

This commit is contained in:
dags- 2020-04-30 14:01:50 +01:00
parent 0ea18b62ad
commit 19e4990073
7 changed files with 161 additions and 17 deletions

View File

@ -0,0 +1,57 @@
package com.terraforged.core.region.gen;
import com.terraforged.core.region.Region;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class FutureRegion implements Future<Region>, Callable<Region> {
private final int rx;
private final int rz;
private final RegionGenerator generator;
private volatile Region result;
public FutureRegion(int rx, int rz, RegionGenerator generator) {
this.rx = rx;
this.rz = rz;
this.generator = generator;
}
@Override
public Region call() {
Region region = result;
if (region == null) {
region = generator.generateRegion(rx, rz);
result = region;
}
return region;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return result != null;
}
@Override
public Region get() {
return call();
}
@Override
public Region get(long timeout, TimeUnit unit) {
return get();
}
}

View File

@ -0,0 +1,61 @@
package com.terraforged.core.region.gen;
import com.terraforged.core.region.Region;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class FutureRegionZoom implements Future<Region>, Callable<Region> {
private final float cx;
private final float cz;
private final float zoom;
private final boolean filters;
private final RegionGenerator generator;
private volatile Region result;
public FutureRegionZoom(float cx, float cz, float zoom, boolean filters, RegionGenerator generator) {
this.cx = cx;
this.cz = cz;
this.zoom = zoom;
this.filters = filters;
this.generator = generator;
}
@Override
public Region call() {
Region region = result;
if (region == null) {
region = generator.generateRegion(cx, cz, zoom, filters);
result = region;
}
return region;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return result != null;
}
@Override
public Region get() {
return call();
}
@Override
public Region get(long timeout, TimeUnit unit) {
return get();
}
}

View File

@ -73,7 +73,7 @@ public class RegionCache implements RegionExtent, Disposable.Listener<Region> {
@Override
public Region getRegion(int regionX, int regionZ) {
Region region = queueRegion(regionX, regionZ).get();
Region region = computeRegion(regionX, regionZ).get();
if (queuing) {
queueNeighbours(regionX, regionZ);
@ -82,9 +82,14 @@ public class RegionCache implements RegionExtent, Disposable.Listener<Region> {
return region;
}
private CacheEntry<Region> computeRegion(int regionX, int regionZ) {
long id = NoiseUtil.seed(regionX, regionZ);
return cache.computeIfAbsent(id, l -> generator.compute(regionX, regionZ));
}
public CacheEntry<Region> queueRegion(int regionX, int regionZ) {
long id = NoiseUtil.seed(regionX, regionZ);
return cache.computeIfAbsent(id, l -> generator.generateCached(regionX, regionZ));
return cache.computeIfAbsent(id, l -> generator.queue(regionX, regionZ));
}
private void queueNeighbours(int regionX, int regionZ) {

View File

@ -97,8 +97,20 @@ public class RegionGenerator implements RegionExtent {
return CompletableFuture.supplyAsync(() -> generateRegion(centerX, centerZ, zoom, filter), threadPool);
}
public CacheEntry<Region> generateCached(int regionX, int regionZ) {
return CacheEntry.supplyAsync(() -> generateRegion(regionX, regionZ), threadPool);
public CacheEntry<Region> compute(int regionX, int regionZ) {
return CacheEntry.supply(new FutureRegion(regionX, regionZ, this));
}
public CacheEntry<Region> compute(float centerX, float centerZ, float zoom, boolean filter) {
return CacheEntry.supply(new FutureRegionZoom(centerX, centerZ, zoom, filter, this));
}
public CacheEntry<Region> queue(int regionX, int regionZ) {
return CacheEntry.supplyAsync(new FutureRegion(regionX, regionZ, this), threadPool);
}
public CacheEntry<Region> queue(float centerX, float centerZ, float zoom, boolean filter) {
return CacheEntry.supplyAsync(new FutureRegionZoom(centerX, centerZ, zoom, filter, this), threadPool);
}
public Region generateRegion(int regionX, int regionZ) {

View File

@ -3,14 +3,16 @@ package com.terraforged.core.util.concurrent.cache;
import com.terraforged.core.util.concurrent.ThreadPool;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.Future;
public class CacheEntry<T> implements ExpiringEntry {
private volatile long timestamp;
private final ForkJoinTask<T> task;
private final Future<T> task;
public CacheEntry(ForkJoinTask<T> task) {
public CacheEntry(Future<T> task) {
this.task = task;
this.timestamp = System.currentTimeMillis();
}
@ -25,7 +27,19 @@ public class CacheEntry<T> implements ExpiringEntry {
}
public T get() {
return task.join();
if (task instanceof ForkJoinTask) {
return ((ForkJoinTask<T>) task).join();
}
try {
return task.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
public static <T> CacheEntry<T> supply(Future<T> future) {
return new CacheEntry<>(future);
}
public static <T> CacheEntry<T> supplyAsync(Callable<T> callable, ThreadPool executor) {

View File

@ -395,7 +395,7 @@ public class TerraChunkGenerator extends ObfHelperChunkGenerator<GenerationSetti
.legacy(context.terraSettings.version == 0)
.pool(ThreadPool.getPool())
.factory(context.factory)
.size(4, 2)
.size(3, 2)
.build()
.toCache(false);
}

View File

@ -32,6 +32,7 @@ import com.terraforged.core.region.Region;
import com.terraforged.core.region.gen.RegionGenerator;
import com.terraforged.core.settings.Settings;
import com.terraforged.core.util.concurrent.ThreadPool;
import com.terraforged.core.util.concurrent.cache.CacheEntry;
import com.terraforged.core.world.GeneratorContext;
import com.terraforged.core.world.WorldGeneratorFactory;
import com.terraforged.core.world.terrain.Terrain;
@ -48,8 +49,6 @@ import net.minecraft.nbt.CompoundNBT;
import java.awt.*;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class Preview extends Button {
@ -68,7 +67,7 @@ public class Preview extends Button {
private int seed;
private long lastUpdate = 0L;
private Settings settings = new Settings();
private Future<Region> task = null;
private CacheEntry<Region> task = null;
private Region region = null;
private String[] labels = {"Area: ", "Terrain: ", "Biome: "};
@ -131,10 +130,6 @@ public class Preview extends Button {
try {
region = task.get();
render(region);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.getCause().printStackTrace();
} finally {
task = null;
}
@ -195,7 +190,7 @@ public class Preview extends Button {
texture.updateDynamicTexture();
}
private Future<Region> generate(Settings settings, CompoundNBT prevSettings) {
private CacheEntry<Region> generate(Settings settings, CompoundNBT prevSettings) {
NBTHelper.deserialize(prevSettings, previewSettings);
settings.generator.seed = seed;
this.settings = settings;
@ -208,7 +203,7 @@ public class Preview extends Button {
.size(FACTOR, 0)
.build();
return renderer.generate(offsetX, offsetZ, 101 - previewSettings.zoom, true);
return renderer.queue(offsetX, offsetZ, 101 - previewSettings.zoom, true);
}
private void updateLegend(int mx ,int my) {