biome cleanup

This commit is contained in:
dfsek
2021-01-26 21:50:56 -07:00
parent 82fa9abe15
commit f6967be95f
31 changed files with 414 additions and 30 deletions

View File

@@ -6,8 +6,6 @@ import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.world.biome.Generator;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.StandardBiomeProvider;
import com.dfsek.terra.biome.TerraBiome;
import com.dfsek.terra.biome.pipeline.BiomePipeline;
import com.dfsek.terra.biome.pipeline.expand.FractalExpander;
@@ -19,6 +17,8 @@ import com.dfsek.terra.biome.pipeline.source.RandomSource;
import com.dfsek.terra.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.biome.pipeline.stages.SeededBuilder;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.biome.provider.StandardBiomeProvider;
import org.junit.jupiter.api.Test;
import javax.swing.*;

View File

@@ -8,19 +8,28 @@ import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeRegistry;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.platform.handle.ItemHandle;
import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.world.biome.Generator;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.TerraBiome;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfig;
import com.dfsek.terra.config.fileloaders.FolderLoader;
import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader;
import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.AbstractableTemplate;
import com.dfsek.terra.debug.DebugLogger;
import com.dfsek.terra.registry.BiomeRegistry;
import com.dfsek.terra.registry.ConfigRegistry;
import com.dfsek.terra.world.TerraWorld;
import javax.swing.*;
import java.awt.*;
@@ -36,8 +45,87 @@ import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import java.util.logging.Logger;
public class DistributionTest {
private static final TerraPlugin MAIN = new TerraPlugin() {
@Override
public WorldHandle getWorldHandle() {
return null;
}
@Override
public boolean isEnabled() {
return false;
}
@Override
public TerraWorld getWorld(World world) {
return null;
}
@Override
public Logger getLogger() {
return Logger.getLogger("Terra");
}
@Override
public PluginConfig getTerraConfig() {
return new PluginConfig();
}
@Override
public File getDataFolder() {
return null;
}
@Override
public boolean isDebug() {
return false;
}
@Override
public Language getLanguage() {
return null;
}
@Override
public ConfigRegistry getRegistry() {
return null;
}
@Override
public void reload() {
}
@Override
public ItemHandle getItemHandle() {
return null;
}
@Override
public void saveDefaultConfig() {
}
@Override
public String platformName() {
return null;
}
@Override
public DebugLogger getDebugLogger() {
return new DebugLogger(Logger.getLogger("Terra"));
}
@Override
public void register(TypeRegistry registry) {
}
};
private static BiomeProvider getProvider(long seed) throws ConfigException, IOException {
System.out.println(seed);
File pack = new File("/home/dfsek/Documents/Terra/platforms/bukkit/target/server/plugins/Terra/packs/default/");
@@ -46,11 +134,11 @@ public class DistributionTest {
AbstractConfigLoader loader = new AbstractConfigLoader();
BiomeRegistry biomeRegistry = new BiomeRegistry();
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.load(inputStreams, TestBiome::new), null));
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.load(inputStreams, TestBiome::new), MAIN));
BiomeProviderTemplate template = new BiomeProviderTemplate();
ConfigLoader pipeLoader = new ConfigLoader()
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader(null, biomeRegistry, folderLoader))
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader(MAIN, biomeRegistry, folderLoader))
.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader())
.registerLoader(TerraBiome.class, biomeRegistry);
new GenericLoaders(null).register(pipeLoader);

View File

@@ -11,9 +11,9 @@ import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.world.biome.Generator;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.ImageBiomeProvider;
import com.dfsek.terra.biome.TerraBiome;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.biome.provider.ImageBiomeProvider;
import com.dfsek.terra.config.fileloaders.FolderLoader;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.AbstractableTemplate;

View File

@@ -0,0 +1,23 @@
package noise;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.api.math.ProbabilityCollection;
public class ColorConfigTemplate implements ConfigTemplate {
@Value("colors")
private ProbabilityCollection<Integer> colors;
@Value("enable")
@Default
private boolean enable = false;
public boolean enable() {
return enable;
}
public ProbabilityCollection<Integer> getColors() {
return colors;
}
}

View File

@@ -0,0 +1,16 @@
package noise;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
@SuppressWarnings("unused")
public class NoiseConfigTemplate implements ConfigTemplate {
@Value(".")
private NoiseBuilder builder;
public NoiseBuilder getBuilder() {
return builder;
}
}

View File

@@ -0,0 +1,193 @@
package noise;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader;
import com.dfsek.terra.config.loaders.config.NoiseBuilderLoader;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import org.apache.commons.io.FileUtils;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
public class NoiseTool {
public static void main(String... args) throws ConfigException, IOException {
JFrame frame = new JFrame("Noise Viewer");
AtomicInteger seed = new AtomicInteger(2403);
JLabel label = new JLabel(new ImageIcon(load(seed.get(), false, false)));
frame.add(label);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
if(e.getKeyChar() == 'r') {
try {
label.setIcon(new ImageIcon(load(seed.get(), false, false)));
} catch(ConfigException | IOException configException) {
configException.printStackTrace();
}
} else if(e.getKeyChar() == 's') {
try {
seed.set(ThreadLocalRandom.current().nextInt());
label.setIcon(new ImageIcon(load(seed.get(), false, false)));
} catch(ConfigException | IOException configException) {
configException.printStackTrace();
}
} else if(e.getKeyChar() == 'd') {
try {
label.setIcon(new ImageIcon(load(seed.get(), true, false)));
} catch(ConfigException | IOException configException) {
configException.printStackTrace();
}
} else if(e.getKeyChar() == 'c') {
try {
label.setIcon(new ImageIcon(load(seed.get(), false, true)));
} catch(ConfigException | IOException configException) {
configException.printStackTrace();
}
}
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
});
frame.setVisible(true);
}
private static int normal(double in, double out, double min, double max) {
double range = max - min;
return (int) (((in - min) * out) / range);
}
private static int buildRGBA(int in) {
return (255 << 24)
+ (in << 16)
+ (in << 8)
+ in;
}
private static BufferedImage load(int seed, boolean distribution, boolean chunk) throws ConfigException, IOException {
long s = System.nanoTime();
ConfigLoader loader = new ConfigLoader();
loader.registerLoader(NoiseBuilder.class, new NoiseBuilderLoader())
.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader());
NoiseConfigTemplate template = new NoiseConfigTemplate();
File file = new File("./config.yml");
System.out.println(file.getAbsolutePath());
File colorFile = new File("./color.yml");
System.out.println(file.getAbsolutePath());
if(!file.exists()) {
file.getParentFile().mkdirs();
FileUtils.copyInputStreamToFile(NoiseTool.class.getResourceAsStream("/config.yml"), file);
}
boolean colors = false;
ColorConfigTemplate color = new ColorConfigTemplate();
if(colorFile.exists()) {
loader.load(color, new FileInputStream(colorFile));
colors = color.enable();
}
ProbabilityCollection<Integer> colorCollection = color.getColors();
loader.load(template, new FileInputStream(file));
NoiseSampler noise = template.getBuilder().build(seed);
int size = 1024;
BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
double[][] noiseVals = new double[size][size];
int[][] rgbVals = new int[size][size];
double max = Double.MIN_VALUE;
double min = Double.MAX_VALUE;
int[] buckets = new int[1024];
for(int x = 0; x < noiseVals.length; x++) {
for(int z = 0; z < noiseVals[x].length; z++) {
double n = template.getBuilder().getDimensions() == 2 ? noise.getNoise(x, z) : noise.getNoise(x, 0, z);
noiseVals[x][z] = n;
max = Math.max(n, max);
min = Math.min(n, min);
if(colors) rgbVals[x][z] = colorCollection.get(noise, x, z);
}
}
for(int x = 0; x < noiseVals.length; x++) {
for(int z = 0; z < noiseVals[x].length; z++) {
if(colors) image.setRGB(x, z, rgbVals[x][z] + (255 << 24));
else image.setRGB(x, z, buildRGBA(normal(noiseVals[x][z], 255, min, max)));
buckets[normal(noiseVals[x][z], size - 1, min, max)]++;
}
}
long time = System.nanoTime() - s;
double ms = time / 1000000d;
if(chunk) {
for(int x = 0; x < image.getWidth(); x += 16) {
for(int y = 0; y < image.getHeight(); y++) image.setRGB(x, y, buildRGBA(0));
}
for(int y = 0; y < image.getWidth(); y += 16) {
for(int x = 0; x < image.getHeight(); x++) image.setRGB(x, y, buildRGBA(0));
}
}
Graphics graphics = image.getGraphics();
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, 325, 90);
graphics.setColor(Color.BLACK);
graphics.setFont(new Font("Monospace", Font.BOLD, 20));
graphics.drawString("min: " + min, 0, 20);
graphics.drawString("max: " + max, 0, 40);
graphics.drawString("seed: " + seed, 0, 60);
graphics.drawString("time: " + ms + "ms", 0, 80);
if(distribution) {
graphics.setColor(Color.WHITE);
graphics.fillRect(0, size - (size / 4) - 1, size, (size / 4) - 1);
int highestBucket = Integer.MIN_VALUE;
for(int i : buckets) highestBucket = Math.max(highestBucket, i);
graphics.setColor(Color.BLACK);
graphics.drawString("" + highestBucket, 0, size - (size / 4) - 1 + 20);
for(int x = 0; x < size; x++) {
for(int y = 0; y < ((double) buckets[x] / highestBucket) * ((double) size / 4); y++) {
image.setRGB(x, size - y - 1, buildRGBA(0));
}
}
}
return image;
}
}