mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-18 10:32:30 +00:00
Add advanced biome blending
This commit is contained in:
parent
81d607b900
commit
cfbd6533dd
2
pom.xml
2
pom.xml
@ -95,7 +95,7 @@
|
||||
<dependency>
|
||||
<groupId>org.polydev</groupId>
|
||||
<artifactId>gaea</artifactId>
|
||||
<version>1.10.45</version>
|
||||
<version>1.10.46</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.lucko</groupId>
|
||||
|
@ -26,6 +26,7 @@ import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.profiler.WorldProfiler;
|
||||
|
||||
import java.io.File;
|
||||
@ -46,7 +47,7 @@ public class TerraCommand implements CommandExecutor, TabExecutor {
|
||||
return true;
|
||||
case "biome":
|
||||
if(! (sender instanceof Player)) return false;
|
||||
sender.sendMessage("You are in " + BiomeConfig.fromBiome((UserDefinedBiome) TerraBiomeGrid.fromWorld(((Player) sender).getWorld()).getBiome(((Player) sender).getLocation())).getFriendlyName());
|
||||
sender.sendMessage("You are in " + BiomeConfig.fromBiome((UserDefinedBiome) TerraBiomeGrid.fromWorld(((Player) sender).getWorld()).getBiome(((Player) sender).getLocation(), GenerationPhase.POPULATE)).getFriendlyName());
|
||||
return true;
|
||||
case "profile":
|
||||
if(! (sender instanceof Player)) {
|
||||
|
21
src/main/java/com/dfsek/terra/biome/CoordinatePerturb.java
Normal file
21
src/main/java/com/dfsek/terra/biome/CoordinatePerturb.java
Normal file
@ -0,0 +1,21 @@
|
||||
package com.dfsek.terra.biome;
|
||||
|
||||
import org.polydev.gaea.math.FastNoise;
|
||||
|
||||
public class CoordinatePerturb {
|
||||
private final FastNoise perturbX;
|
||||
private final FastNoise perturbZ;
|
||||
private final int amplitude;
|
||||
public CoordinatePerturb(float frequency, int amplitude, long seed) {
|
||||
perturbX = new FastNoise((int) seed);
|
||||
perturbX.setNoiseType(FastNoise.NoiseType.Simplex);
|
||||
perturbX.setFrequency(frequency);
|
||||
perturbZ = new FastNoise((int) seed+1);
|
||||
perturbZ.setNoiseType(FastNoise.NoiseType.Simplex);
|
||||
perturbZ.setFrequency(frequency);
|
||||
this.amplitude = amplitude;
|
||||
}
|
||||
public int[] getShiftedCoords(int x, int z) {
|
||||
return new int[] {(int) (perturbX.getNoise(x, z)*amplitude+x), (int) (perturbZ.getNoise(x, z)*amplitude+z)};
|
||||
}
|
||||
}
|
@ -7,21 +7,29 @@ import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.biome.BiomeGrid;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class TerraBiomeGrid extends BiomeGrid {
|
||||
private static int failNum = 0;
|
||||
private CoordinatePerturb perturb;
|
||||
|
||||
private static final Map<World, TerraBiomeGrid> grids = new HashMap<>();
|
||||
private final World w;
|
||||
private final BiomeZone zone;
|
||||
private final boolean perturbPaletteOnly;
|
||||
|
||||
|
||||
|
||||
private TerraBiomeGrid(World w, float freq1, float freq2, boolean blank) {
|
||||
super(w, freq1, freq2);
|
||||
WorldConfig c = WorldConfig.fromWorld(w);
|
||||
if(c.biomeBlend) {
|
||||
perturb = new CoordinatePerturb(c.blendFreq, c.blendAmp, w.getSeed());
|
||||
}
|
||||
perturbPaletteOnly = c.perturbPaletteOnly;
|
||||
this.w = w;
|
||||
this.zone = BiomeZone.fromWorld(w);
|
||||
if(!blank) grids.put(w, this);
|
||||
@ -41,9 +49,17 @@ public class TerraBiomeGrid extends BiomeGrid {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome getBiome(int x, int z) {
|
||||
public Biome getBiome(int x, int z, GenerationPhase phase) {
|
||||
int xp = x;
|
||||
int zp = z;
|
||||
if(perturb != null && (!perturbPaletteOnly || phase.equals(GenerationPhase.PALETTE_APPLY))) {
|
||||
int[] perturbCoords = perturb.getShiftedCoords(x, z);
|
||||
xp = perturbCoords[0];
|
||||
zp = perturbCoords[1];
|
||||
}
|
||||
|
||||
try {
|
||||
return zone.getGrid(x, z).getBiome(x, z);
|
||||
return zone.getGrid(xp, zp).getBiome(xp, zp, phase);
|
||||
} catch(NullPointerException e) {
|
||||
if(ConfigUtil.debug) e.printStackTrace();
|
||||
if(failNum % 256 == 0) Bukkit.getLogger().severe("[Terra] A severe configuration error has prevented Terra from properly generating terrain at coordinates: " + x + ", " + z + ". Please check your configuration for errors. Any config errors will have been reported above.");
|
||||
@ -53,8 +69,8 @@ public class TerraBiomeGrid extends BiomeGrid {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome getBiome(Location l) {
|
||||
return getBiome(l.getBlockX(), l.getBlockZ());
|
||||
public Biome getBiome(Location l, GenerationPhase phase) {
|
||||
return getBiome(l.getBlockX(), l.getBlockZ(), phase);
|
||||
}
|
||||
|
||||
public static void invalidate() {
|
||||
|
@ -8,6 +8,8 @@ import org.bukkit.World;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.biome.BiomeGrid;
|
||||
import org.polydev.gaea.biome.NormalizationUtil;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.math.Interpolator;
|
||||
|
||||
public class UserDefinedGrid extends BiomeGrid {
|
||||
private final ImageLoader imageLoader;
|
||||
@ -26,17 +28,17 @@ public class UserDefinedGrid extends BiomeGrid {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome getBiome(int x, int z) {
|
||||
public Biome getBiome(int x, int z, GenerationPhase phase) {
|
||||
if(fromImage) {
|
||||
double xi = imageLoader.getNoiseVal(x, z, channelX);
|
||||
double zi = imageLoader.getNoiseVal(x, z, channelZ);
|
||||
return super.getGrid()[NormalizationUtil.normalize(xi, getSizeX())][NormalizationUtil.normalize(zi, getSizeZ())];
|
||||
}
|
||||
return super.getBiome(x, z);
|
||||
return super.getBiome(x, z, phase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome getBiome(Location l) {
|
||||
return this.getBiome(l.getBlockX(), l.getBlockZ());
|
||||
public Biome getBiome(Location l, GenerationPhase phase) {
|
||||
return this.getBiome(l.getBlockX(), l.getBlockZ(), phase);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.config.genconfig.BiomeConfig;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.world.carving.Carver;
|
||||
import org.polydev.gaea.world.carving.Worm;
|
||||
|
||||
@ -40,7 +41,7 @@ public class UserDefinedCarver extends Carver {
|
||||
|
||||
@Override
|
||||
public boolean isChunkCarved(World w, int chunkX, int chunkZ, Random random) {
|
||||
return random.nextInt(100) < BiomeConfig.fromBiome((UserDefinedBiome) TerraBiomeGrid.fromWorld(w).getBiome(chunkX << 4, chunkZ << 4)).getCarverChance(this);
|
||||
return random.nextInt(100) < BiomeConfig.fromBiome((UserDefinedBiome) TerraBiomeGrid.fromWorld(w).getBiome(chunkX << 4, chunkZ << 4, GenerationPhase.POPULATE)).getCarverChance(this);
|
||||
}
|
||||
|
||||
private class UserDefinedWorm extends Worm {
|
||||
|
@ -34,8 +34,11 @@ public class WorldConfig {
|
||||
public ImageLoader.Channel biomeXChannel;
|
||||
public ImageLoader.Channel biomeZChannel;
|
||||
public ImageLoader.Channel zoneChannel;
|
||||
public ImageLoader.Channel terrainChannel;
|
||||
public boolean biomeBlend;
|
||||
public ImageLoader imageLoader;
|
||||
public int blendAmp;
|
||||
public float blendFreq;
|
||||
public boolean perturbPaletteOnly;
|
||||
|
||||
|
||||
public WorldConfig(World w, JavaPlugin main) {
|
||||
@ -74,6 +77,12 @@ public class WorldConfig {
|
||||
freq1 = 1f/config.getInt("frequencies.grid-x", 256);
|
||||
freq2 = 1f/config.getInt("frequencies.grid-z", 512);
|
||||
fromImage = config.getBoolean("image.use-image", false);
|
||||
biomeBlend = config.getBoolean("blend.enable", false);
|
||||
blendAmp = config.getInt("blend.amplitude", 8);
|
||||
blendFreq = (float) config.getDouble("blend.frequency", 0.01);
|
||||
perturbPaletteOnly = config.getBoolean("blend.ignore-terrain", true);
|
||||
|
||||
|
||||
|
||||
// Load image stuff
|
||||
try {
|
||||
|
@ -13,6 +13,7 @@ import org.bukkit.block.data.type.Slab;
|
||||
import org.bukkit.block.data.type.Stairs;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.generation.GenerationPopulator;
|
||||
import org.polydev.gaea.math.ChunkInterpolator;
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
@ -32,7 +33,7 @@ public class SlabGenerator extends GenerationPopulator {
|
||||
for(byte z = 0; z < 16; z++) {
|
||||
int xi = (chunkX << 4) + x;
|
||||
int zi = (chunkZ << 4) + z;
|
||||
BiomeConfig config = BiomeConfig.fromBiome((UserDefinedBiome) g.getBiome(xi, zi));
|
||||
BiomeConfig config = BiomeConfig.fromBiome((UserDefinedBiome) g.getBiome(xi, zi, GenerationPhase.PALETTE_APPLY));
|
||||
if(config.getSlabs() == null) continue;
|
||||
double thresh = config.getSlabThreshold();
|
||||
for(int y = 0; y < world.getMaxHeight(); y++) {
|
||||
|
@ -1,10 +1,14 @@
|
||||
package com.dfsek.terra.generation;
|
||||
|
||||
import com.dfsek.terra.biome.TerraBiomeGrid;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.biome.UserDefinedGrid;
|
||||
import com.dfsek.terra.math.NoiseFunction2;
|
||||
import com.dfsek.terra.math.NoiseFunction3;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.polydev.gaea.biome.Generator;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.math.FastNoise;
|
||||
import org.polydev.gaea.math.parsii.eval.Expression;
|
||||
import org.polydev.gaea.math.parsii.eval.Parser;
|
||||
@ -20,9 +24,9 @@ import java.util.TreeMap;
|
||||
public class UserDefinedGenerator extends Generator {
|
||||
private final Expression noiseExp;
|
||||
private final Scope s = new Scope();
|
||||
private final Variable xVar = s.getVariable("x");;
|
||||
private final Variable xVar = s.getVariable("x");
|
||||
private final Variable yVar = s.getVariable("y");
|
||||
private final Variable zVar = s.getVariable("z");;
|
||||
private final Variable zVar = s.getVariable("z");
|
||||
private final TreeMap<Integer, Palette<BlockData>> paletteMap;
|
||||
private final NoiseFunction2 n2 = new NoiseFunction2();
|
||||
private final NoiseFunction3 n3 = new NoiseFunction3();
|
||||
@ -51,8 +55,8 @@ public class UserDefinedGenerator extends Generator {
|
||||
xVar.setValue(x);
|
||||
yVar.setValue(0);
|
||||
zVar.setValue(z);
|
||||
n2.setNoise(gen, false);
|
||||
n3.setNoise(gen, false);
|
||||
n2.setNoise(gen);
|
||||
n3.setNoise(gen);
|
||||
return noiseExp.evaluate();
|
||||
}
|
||||
}
|
||||
@ -72,8 +76,8 @@ public class UserDefinedGenerator extends Generator {
|
||||
xVar.setValue(x);
|
||||
yVar.setValue(y);
|
||||
zVar.setValue(z);
|
||||
n2.setNoise(gen, false);
|
||||
n3.setNoise(gen, false);
|
||||
n2.setNoise(gen);
|
||||
n3.setNoise(gen);
|
||||
return noiseExp.evaluate();
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import com.dfsek.terra.config.WorldConfig;
|
||||
import com.dfsek.terra.config.genconfig.BiomeConfig;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@ -37,7 +38,7 @@ public class DebugFrame extends JFrame implements ActionListener {
|
||||
xp = (int) (((double) Math.floorMod(p.getLocation().getBlockX() - (img.getWidth() / 2), x) / x) * getWidth());
|
||||
zp = (int) (((double) Math.floorMod(p.getLocation().getBlockZ() - (img.getHeight() / 2), z) / z) * getHeight());
|
||||
}
|
||||
String str = BiomeConfig.fromBiome((UserDefinedBiome) TerraBiomeGrid.fromWorld(p.getWorld()).getBiome(p.getLocation())).getID();
|
||||
String str = BiomeConfig.fromBiome((UserDefinedBiome) TerraBiomeGrid.fromWorld(p.getWorld()).getBiome(p.getLocation(), GenerationPhase.POPULATE)).getID();
|
||||
g.setColor(new Color(255, 255, 255, 128));
|
||||
g.fillRect(xp + 13, zp - 13, (int) (8 + 8.25 * str.length()), 33);
|
||||
g.setColor(Color.BLACK);
|
||||
|
@ -19,8 +19,8 @@ public class NoiseFunction2 implements Function {
|
||||
return gen.getSimplexFractal((float) list.get(0).evaluate(), (float) list.get(1).evaluate());
|
||||
}
|
||||
|
||||
public void setNoise(FastNoise gen, boolean override) {
|
||||
if(this.gen == null || override) this.gen = gen;
|
||||
public void setNoise(FastNoise gen) {
|
||||
this.gen = gen;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -18,8 +18,8 @@ public class NoiseFunction3 implements Function {
|
||||
return gen.getSimplexFractal((float) list.get(0).evaluate(), (float) list.get(1).evaluate(), (float) list.get(2).evaluate());
|
||||
}
|
||||
|
||||
public void setNoise(FastNoise gen, boolean override) {
|
||||
if(this.gen == null || override) this.gen = gen;
|
||||
public void setNoise(FastNoise gen) {
|
||||
this.gen = gen;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -10,6 +10,7 @@ import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.population.GaeaBlockPopulator;
|
||||
import org.polydev.gaea.profiler.ProfileFuture;
|
||||
import org.polydev.gaea.world.Flora;
|
||||
@ -27,7 +28,7 @@ public class FloraPopulator extends GaeaBlockPopulator {
|
||||
pop.add(chunk);
|
||||
for(int x = 0; x < 16; x++) {
|
||||
for(int z = 0; z < 16; z++) {
|
||||
UserDefinedBiome biome = (UserDefinedBiome) TerraBiomeGrid.fromWorld(world).getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z);
|
||||
UserDefinedBiome biome = (UserDefinedBiome) TerraBiomeGrid.fromWorld(world).getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, GenerationPhase.POPULATE);
|
||||
if(biome.getDecorator().getFloraChance() <= 0 || random.nextInt(100) > biome.getDecorator().getFloraChance())
|
||||
continue;
|
||||
try {
|
||||
|
@ -11,6 +11,7 @@ import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.population.GaeaBlockPopulator;
|
||||
import org.polydev.gaea.profiler.ProfileFuture;
|
||||
|
||||
@ -22,7 +23,7 @@ public class OrePopulator extends GaeaBlockPopulator {
|
||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||
try (ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("OreTime")) {
|
||||
Location l = chunk.getBlock(8, 0, 0).getLocation();
|
||||
Biome b = TerraBiomeGrid.fromWorld(world).getBiome(l.getBlockX(), l.getBlockZ());
|
||||
Biome b = TerraBiomeGrid.fromWorld(world).getBiome(l.getBlockX(), l.getBlockZ(), GenerationPhase.POPULATE);
|
||||
for(Map.Entry<OreConfig, Range> e : BiomeConfig.fromBiome((UserDefinedBiome) b).getOres().entrySet()) {
|
||||
int num = e.getValue().get(random);
|
||||
for(int i = 0; i < num; i++) {
|
||||
|
@ -9,6 +9,7 @@ import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.population.GaeaBlockPopulator;
|
||||
import org.polydev.gaea.profiler.ProfileFuture;
|
||||
import org.polydev.gaea.util.WorldUtil;
|
||||
@ -22,14 +23,14 @@ public class TreePopulator extends GaeaBlockPopulator {
|
||||
int x = random.nextInt(16); // Decrease chances of chunk-crossing trees
|
||||
int z = random.nextInt(16);
|
||||
Location origin = chunk.getBlock(x, 0, z).getLocation();
|
||||
Biome b = TerraBiomeGrid.fromWorld(world).getBiome(origin);
|
||||
Biome b = TerraBiomeGrid.fromWorld(world).getBiome(origin, GenerationPhase.POPULATE);
|
||||
if(((UserDefinedDecorator) b.getDecorator()).getTreeChance() < random.nextInt(100)) return;
|
||||
int numTrees = 0;
|
||||
for(int i = 0; i < 48; i++) {
|
||||
int y = WorldUtil.getHighestValidSpawnAt(chunk, x, z);
|
||||
if(y <= 0) continue;
|
||||
origin = chunk.getBlock(x, y, z).getLocation().add(0, 1, 0);
|
||||
b = TerraBiomeGrid.fromWorld(world).getBiome(origin);
|
||||
b = TerraBiomeGrid.fromWorld(world).getBiome(origin, GenerationPhase.POPULATE);
|
||||
numTrees++;
|
||||
try {
|
||||
b.getDecorator().getTrees().get(random).plant(origin, random, false, Terra.getInstance());
|
||||
|
Loading…
x
Reference in New Issue
Block a user