Config refactoring, work on caverns, multi-level tree gen

This commit is contained in:
dfsek 2020-10-04 21:14:58 -07:00
parent c80e65cce9
commit 277fbccc07
34 changed files with 328 additions and 110 deletions

View File

@ -0,0 +1,10 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<Languages>
<language minSize="54" name="Java" />
</Languages>
</inspection_tool>
</profile>
</component>

View File

@ -4,7 +4,7 @@ import com.dfsek.terra.biome.BiomeZone;
import com.dfsek.terra.biome.TerraBiomeGrid;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.UserDefinedGrid;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.base.ConfigUtil;
import com.dfsek.terra.config.base.WorldConfig;
import com.dfsek.terra.config.genconfig.BiomeGridConfig;

View File

@ -1,7 +1,6 @@
package com.dfsek.terra.async;
import com.dfsek.terra.Terra;
import com.dfsek.terra.TerraProfiler;
import com.dfsek.terra.biome.TerraBiomeGrid;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.genconfig.StructureConfig;
@ -13,9 +12,7 @@ import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import org.polydev.gaea.generation.GenerationPhase;
import org.polydev.gaea.profiler.ProfileFuture;
import java.util.Collections;
import java.util.Random;
public class AsyncStructureFinder implements Runnable {
@ -53,11 +50,13 @@ public class AsyncStructureFinder implements Runnable {
int run = 1;
boolean toggle = true;
boolean found = false;
Vector spawn = null;
main: for(int i = startRadius; i < maxRadius; i++) {
for(int j = 0; j < run; j++) {
if(toggle) x += 16;
else x -= 16;
if(hasValidSpawn(x, z)) {
spawn = target.getSpawn().getNearestSpawn(x, z, seed);
if(isValidSpawn(spawn.getBlockX(), spawn.getBlockZ())) {
found = true;
break main;
}
@ -65,7 +64,8 @@ public class AsyncStructureFinder implements Runnable {
for(int j = 0; j < run; j++) {
if(toggle) z += 16;
else z -= 16;
if(hasValidSpawn(x, z)) {
spawn = target.getSpawn().getNearestSpawn(x, z, seed);
if(isValidSpawn(spawn.getBlockX(), spawn.getBlockZ())) {
found = true;
break main;
}
@ -74,25 +74,22 @@ public class AsyncStructureFinder implements Runnable {
toggle = !toggle;
}
if(found) {
Vector v = target.getSpawn().getNearestSpawn(x, z, seed);
x = v.getBlockX();
z = v.getBlockZ();
p.sendMessage("Located structure at (" + x + ", " + z + ").");
p.sendMessage("Located structure at (" + spawn.getBlockX() + ", " + spawn.getBlockZ() + ").");
if(tp) {
int finalX = x;
int finalZ = z;
Bukkit.getScheduler().runTask(Terra.getInstance(), () -> p.teleport(new Location(p.getWorld(), finalX, p.getLocation().getY(), finalZ)));
}
} else if(p.isOnline()) p.sendMessage("Unable to locate structure.");
} else if(p.isOnline()) p.sendMessage("Unable to locate structure. " + spawn);
}
private boolean hasValidSpawn(int x, int z) {
UserDefinedBiome b = (UserDefinedBiome) grid.getBiome(x, z, GenerationPhase.POPULATE);
Location spawn = target.getSpawn().getNearestSpawn(x, z, seed).toLocation(world); // Probably(tm) async safe
private boolean isValidSpawn(int x, int z) {
Location spawn = new Location(world, x, 255, z); // Probably(tm) async safe
UserDefinedBiome b = (UserDefinedBiome) grid.getBiome(spawn, GenerationPhase.POPULATE);
Random r2 = new Random(spawn.hashCode());
GaeaStructure struc = target.getStructure(r2);
main: for(int y = target.getSearchStart().get(r2); y > 0; y--) {
if(y > target.getBound().getMax() || y < target.getBound().getMin()) return false;
spawn.setY(y);
if(y > target.getBound().getMax() || y < target.getBound().getMin()) return false;
for(StructureSpawnRequirement s : struc.getSpawns()) {
if(! s.isValidSpawn(spawn)) continue main; // Probably(tm) async safe
if(!b.equals(grid.getBiome(spawn.clone().add(s.getX(), s.getY(), s.getZ()), GenerationPhase.POPULATE))) return false;

View File

@ -1,6 +1,6 @@
package com.dfsek.terra.biome;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.base.ConfigUtil;
import org.bukkit.Bukkit;
import org.bukkit.Location;

View File

@ -57,9 +57,17 @@ public class SimplexCarver extends Carver {
double mainNoise = noise.getNoise(x, z)*2;
double columnNoise = Math.pow(Math.max(column.getNoise(x, z), 0)*2, 3);
double hc = (acot(16*(hasCaves.getNoise(x, z)-0.2))/Math.PI)-0.1;
CarvingData.CarvingType type = CarvingData.CarvingType.BOTTOM;
double simplex = (Math.pow(mainNoise + root2inverse, 3)/2 + columnNoise) * hc;
for(int y = 0; y < 64; y++) {
double finalNoise = (-0.05*Math.abs(y-(heightNoise*16 + 24))+1 - (Math.pow(mainNoise + root2inverse, 3)/2 + columnNoise)) * hc;
if(finalNoise > 0.5) c.carve(x-ox, y, z-oz, CarvingData.CarvingType.CENTER);
double finalNoise = (-0.05*Math.abs(y-(heightNoise*16 + 24))+1 - simplex) * hc;
if(finalNoise > 0.5) {
c.carve(x-ox, y, z-oz, type);
double finalNoiseUp = (-0.05*Math.abs((y+1)-(heightNoise*16 + 24))+1 - simplex) * hc;
if(finalNoiseUp > 0.5) {
type = CarvingData.CarvingType.CENTER;
} else type = CarvingData.CarvingType.TOP;
}
}
}
}

View File

@ -1,7 +1,7 @@
package com.dfsek.terra.carving;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import org.polydev.gaea.math.Range;
import com.dfsek.terra.biome.UserDefinedBiome;
import org.bukkit.World;

View File

@ -1,5 +1,6 @@
package com.dfsek.terra.config;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.base.ConfigUtil;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;

View File

@ -1,5 +1,6 @@
package com.dfsek.terra.config;
import com.dfsek.terra.config.base.ConfigPack;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;

View File

@ -1,7 +1,8 @@
package com.dfsek.terra.config;
package com.dfsek.terra.config.base;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.ConfigLoader;
import com.dfsek.terra.config.exception.ConfigException;
import com.dfsek.terra.config.genconfig.biome.AbstractBiomeConfig;
import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
@ -26,6 +27,9 @@ import java.util.Map;
import java.util.logging.Logger;
import java.util.stream.Collectors;
/**
* Represents a Terra configuration pack.
*/
public class ConfigPack extends YamlConfiguration {
private static final Map<String, ConfigPack> configs = new HashMap<>();
private final Map<String, OreConfig> ores;
@ -104,7 +108,7 @@ public class ConfigPack extends YamlConfiguration {
return carvers;
}
public static void loadAll(JavaPlugin main) {
public static synchronized void loadAll(JavaPlugin main) {
configs.clear();
List<Path> subfolder;
try {
@ -135,7 +139,7 @@ public class ConfigPack extends YamlConfiguration {
return id;
}
public static ConfigPack fromID(String id) {
public static synchronized ConfigPack fromID(String id) {
return configs.get(id);
}

View File

@ -1,7 +1,6 @@
package com.dfsek.terra.config.base;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.exception.ConfigException;
import org.bukkit.Bukkit;
import org.bukkit.Material;

View File

@ -1,6 +1,5 @@
package com.dfsek.terra.config.base;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.image.ImageLoader;
import org.bukkit.Bukkit;
import org.bukkit.World;

View File

@ -2,7 +2,7 @@ package com.dfsek.terra.config.genconfig;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.UserDefinedGrid;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.TerraConfig;
import com.dfsek.terra.config.base.WorldConfig;
import com.dfsek.terra.config.exception.ConfigException;

View File

@ -2,7 +2,7 @@ package com.dfsek.terra.config.genconfig;
import com.dfsek.terra.Debug;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.TerraConfig;
import com.dfsek.terra.config.base.ConfigUtil;
import com.dfsek.terra.config.exception.ConfigException;

View File

@ -1,6 +1,6 @@
package com.dfsek.terra.config.genconfig;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.TerraConfig;
import com.dfsek.terra.config.base.ConfigUtil;
import com.dfsek.terra.config.exception.ConfigException;

View File

@ -1,6 +1,6 @@
package com.dfsek.terra.config.genconfig;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.base.ConfigUtil;
import com.dfsek.terra.config.TerraConfig;
import com.dfsek.terra.config.exception.ConfigException;

View File

@ -1,7 +1,7 @@
package com.dfsek.terra.config.genconfig;
import com.dfsek.terra.Debug;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.TerraConfig;
import com.dfsek.terra.config.exception.ConfigException;
import org.bukkit.Bukkit;

View File

@ -1,7 +1,7 @@
package com.dfsek.terra.config.genconfig;
import com.dfsek.terra.Debug;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.TerraConfig;
import com.dfsek.terra.config.base.ConfigUtil;
import com.dfsek.terra.config.exception.ConfigException;

View File

@ -1,19 +1,14 @@
package com.dfsek.terra.config.genconfig.biome;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.TerraConfig;
import com.dfsek.terra.config.exception.ConfigException;
import com.dfsek.terra.config.genconfig.biome.BiomeConfigUtil;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.configuration.InvalidConfigurationException;
import org.polydev.gaea.world.palette.Palette;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class AbstractBiomeConfig extends TerraConfig {
private final String biomeID;

View File

@ -3,7 +3,7 @@ package com.dfsek.terra.config.genconfig.biome;
import com.dfsek.terra.Debug;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.TerraConfig;
import com.dfsek.terra.config.exception.ConfigException;
import com.dfsek.terra.config.exception.NotFoundException;
@ -19,6 +19,7 @@ import org.polydev.gaea.math.FastNoise;
import org.polydev.gaea.math.ProbabilityCollection;
import org.polydev.gaea.math.Range;
import org.polydev.gaea.math.parsii.tokenizer.ParseException;
import org.polydev.gaea.tree.Tree;
import org.polydev.gaea.world.Flora;
import org.polydev.gaea.world.palette.Palette;
import org.polydev.gaea.world.palette.RandomPalette;
@ -39,6 +40,7 @@ public class BiomeConfig extends TerraConfig {
private final BiomeOreConfig ore;
private final BiomeCarverConfig carver;
private final BiomeFloraConfig flora;
private final BiomeTreeConfig tree;
private String eq;
private int floraAttempts;
private final BiomeSlabConfig slab;
@ -128,7 +130,6 @@ public class BiomeConfig extends TerraConfig {
} else flora = new BiomeFloraConfig(this);
// Check if trees should be handled by super biome.
BiomeTreeConfig tree;
if(extending && abstractBiome.getTrees() != null && ! contains("trees")) {
tree = abstractBiome.getTrees();
Debug.info("Using super trees");
@ -273,4 +274,8 @@ public class BiomeConfig extends TerraConfig {
public List<StructureConfig> getStructures() {
return structures;
}
public Range getTreeRange(Tree t) {
return tree.getTreeHeights().getOrDefault(t, new Range(-1, -1));
}
}

View File

@ -1,51 +0,0 @@
package com.dfsek.terra.config.genconfig.biome;
import com.dfsek.terra.Debug;
import com.dfsek.terra.config.exception.ConfigException;
import com.dfsek.terra.config.TerraConfig;
import com.dfsek.terra.config.exception.NotFoundException;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.configuration.InvalidConfigurationException;
import org.polydev.gaea.math.ProbabilityCollection;
import org.polydev.gaea.world.palette.Palette;
import org.polydev.gaea.world.palette.RandomPalette;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class BiomeConfigUtil {
protected static Map<Material, Palette<BlockData>> getSlabPalettes(List<Map<?, ?>> paletteConfigSection, TerraConfig config) throws InvalidConfigurationException {
Map<Material, Palette<BlockData>> paletteMap = new HashMap<>();
for(Map<?, ?> e : paletteConfigSection) {
for(Map.Entry<?, ?> entry : e.entrySet()) {
try {
if(((String) entry.getValue()).startsWith("BLOCK:")) {
try {
Debug.info("Adding slab palette with single material " + entry.getKey());
paletteMap.put(Bukkit.createBlockData((String) entry.getKey()).getMaterial(), new RandomPalette<BlockData>(new Random(0)).add(new ProbabilityCollection<BlockData>().add(Bukkit.createBlockData(((String) entry.getValue()).substring(6)), 1), 1));
} catch(IllegalArgumentException ex) {
throw new ConfigException("Invalid BlockData in slab configuration: " + ex.getMessage(), config.getID());
}
} else {
try {
Palette<BlockData> p = config.getConfig().getPalette((String) entry.getValue()).getPalette();
if(p.getSize() != 1) throw new InvalidConfigurationException("Slab palette must hold only one layer. Palette " + entry.getValue() + " is too large/small");
paletteMap.put(Bukkit.createBlockData((String) entry.getKey()).getMaterial(), p);
} catch(NullPointerException ex) {
throw new NotFoundException("Slab Palette", (String) entry.getValue(), config.getID());
}
}
} catch(ClassCastException ex) {
throw new ConfigException("Unable to parse Slab Palette configuration! Check YAML syntax.", config.getID());
}
}
}
Debug.info("Adding " + paletteMap.size() + " slab palettes...");
return paletteMap;
}
}

View File

@ -24,9 +24,9 @@ public class BiomeSlabConfig extends TerraConfigSection {
private final Map<Material, Palette<BlockData>> stairs;
public BiomeSlabConfig(@NotNull TerraConfig parent) throws InvalidConfigurationException {
super(parent);
slabs = BiomeConfigUtil.getSlabPalettes(parent.getMapList("slabs.palettes"), parent);
slabs = getSlabPalettes(parent.getMapList("slabs.palettes"));
if(parent.contains("slabs.stair-palettes") && parent.getBoolean("slabs.use-stairs-if-available", false)) {
stairs = BiomeConfigUtil.getSlabPalettes(parent.getMapList("slabs.stair-palettes"), parent);
stairs = getSlabPalettes(parent.getMapList("slabs.stair-palettes"));
} else stairs = new HashMap<>();
}
protected Map<Material, Palette<BlockData>> getSlabPalettes(List<Map<?, ?>> paletteConfigSection) throws InvalidConfigurationException {

View File

@ -6,13 +6,17 @@ import com.dfsek.terra.config.exception.ConfigException;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.polydev.gaea.math.ProbabilityCollection;
import org.polydev.gaea.math.Range;
import org.polydev.gaea.tree.Tree;
import org.polydev.gaea.tree.TreeType;
import org.polydev.gaea.world.Flora;
import java.util.HashMap;
import java.util.Map;
public class BiomeTreeConfig extends TerraConfigSection {
private final ProbabilityCollection<Tree> trees = new ProbabilityCollection<>();
private final Map<Tree, Range> treeHeights = new HashMap<>();
public BiomeTreeConfig(TerraConfig parent) throws InvalidConfigurationException {
super(parent);
ConfigurationSection c = parent.getConfigurationSection("trees");
@ -21,7 +25,11 @@ public class BiomeTreeConfig extends TerraConfigSection {
if(cfg.size() == 0) return;
for(Map.Entry<String, Object> e : cfg.entrySet()) {
try {
trees.add(TreeType.valueOf(e.getKey()), (Integer) e.getValue());
Map<?, ?> val = ((ConfigurationSection) e.getValue()).getValues(false);
Map<?, ?> y = ((ConfigurationSection) val.get("y")).getValues(false);
Tree tree = TreeType.valueOf(e.getKey());
trees.add(tree, (Integer) val.get("weight"));
treeHeights.put(tree, new Range((Integer) y.get("min"), (Integer) y.get("max")));
} catch(ClassCastException ex) {
throw new ConfigException("Unable to parse Tree configuration! Check YAML syntax.", parent.getID());
} catch(IllegalArgumentException ex) {
@ -33,4 +41,8 @@ public class BiomeTreeConfig extends TerraConfigSection {
public ProbabilityCollection<Tree> getTrees() {
return trees;
}
public Map<Tree, Range> getTreeHeights() {
return treeHeights;
}
}

View File

@ -4,7 +4,7 @@ import com.dfsek.terra.Debug;
import com.dfsek.terra.Terra;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
import com.dfsek.terra.population.CavePopulator;
import com.dfsek.terra.population.FloraPopulator;
@ -145,7 +145,7 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
needsLoad = false;
}
public static void saveAll() {
public static synchronized void saveAll() {
for(Map.Entry<World, PopulationManager> e : popMap.entrySet()) {
try {
e.getValue().saveBlocks(e.getKey());

View File

@ -2,8 +2,7 @@ package com.dfsek.terra.population;
import com.dfsek.terra.TerraProfiler;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.carving.SimplexCarver;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.base.ConfigUtil;
import com.dfsek.terra.config.genconfig.CarverConfig;
import org.bukkit.Chunk;
@ -80,10 +79,10 @@ public class CavePopulator extends BlockPopulator {
b.setBlockData(orig, true);
}
}
for(Map.Entry<Vector, CarvingData.CarvingType> e : new SimplexCarver(chunk.getX(), chunk.getZ()).carve(chunk.getX(), chunk.getZ(), world).getCarvedBlocks().entrySet()) {
/*for(Map.Entry<Vector, CarvingData.CarvingType> e : new SimplexCarver(chunk.getX(), chunk.getZ()).carve(chunk.getX(), chunk.getZ(), world).getCarvedBlocks().entrySet()) {
Vector v = e.getKey();
chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ()).setBlockData(AIR, false);
}
}*/
}
}

View File

@ -4,7 +4,7 @@ import com.dfsek.terra.TerraProfiler;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.biome.TerraBiomeGrid;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
import org.bukkit.Chunk;
import org.bukkit.World;

View File

@ -1,7 +1,7 @@
package com.dfsek.terra.population;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import org.polydev.gaea.math.Range;
import com.dfsek.terra.TerraProfiler;
import com.dfsek.terra.biome.UserDefinedBiome;

View File

@ -0,0 +1,15 @@
package com.dfsek.terra.population;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.jetbrains.annotations.NotNull;
import org.polydev.gaea.population.GaeaBlockPopulator;
import java.util.Random;
public class SnowPopulator extends GaeaBlockPopulator {
@Override
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
}
}

View File

@ -4,7 +4,7 @@ import com.dfsek.terra.TerraProfiler;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.biome.TerraBiomeGrid;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.ConfigPack;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.genconfig.StructureConfig;
import com.dfsek.terra.structure.GaeaStructure;
import com.dfsek.terra.structure.StructureSpawnRequirement;

View File

@ -4,18 +4,24 @@ import com.dfsek.terra.Terra;
import com.dfsek.terra.TerraProfiler;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.biome.TerraBiomeGrid;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.base.WorldConfig;
import com.dfsek.terra.generation.UserDefinedDecorator;
import org.bukkit.Chunk;
import org.bukkit.Location;
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.math.Range;
import org.polydev.gaea.population.GaeaBlockPopulator;
import org.polydev.gaea.profiler.ProfileFuture;
import org.polydev.gaea.tree.Tree;
import org.polydev.gaea.util.WorldUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class TreePopulator extends GaeaBlockPopulator {
@ -26,8 +32,9 @@ public class TreePopulator extends GaeaBlockPopulator {
TerraBiomeGrid grid = tw.getGrid();;
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 = grid.getBiome(origin, GenerationPhase.POPULATE);
int origX = chunk.getX() << 4;
int origZ = chunk.getZ() << 4;
Biome b = grid.getBiome(x+origX, z+origZ, GenerationPhase.POPULATE);
if(((UserDefinedDecorator) b.getDecorator()).getTreeChance() < random.nextInt(100)) return;
int max = 50;
int att = 0;
@ -38,15 +45,28 @@ public class TreePopulator extends GaeaBlockPopulator {
if(chunk.getBlock(x, y, z).getType().isAir() && chunk.getBlock(x, y-1, z).getType().isSolid()) break;
y--;
}
if(y == 0) continue;
origin = chunk.getBlock(x, y, z).getLocation().add(0, 1, 0);
b = grid.getBiome(origin, GenerationPhase.POPULATE);
Tree tree = b.getDecorator().getTrees().get(random);
Range range = tw.getConfig().getBiome((UserDefinedBiome) b).getTreeRange(tree);
if(!tw.getConfig().getBiome((UserDefinedBiome) b).getTreeRange(tree).isInRange(y)) continue;
b = grid.getBiome(x+origX, z+origZ, GenerationPhase.POPULATE);
for(Block block : getValidSpawnsAt(chunk, x, z, range)) {
try {
if(b.getDecorator().getTrees().get(random).plant(origin, random, false, Terra.getInstance())) i++;
if(tree.plant(block.getLocation(), random, false, Terra.getInstance())) i++;
} catch(NullPointerException ignore) {}
}
x = random.nextInt(16);
z = random.nextInt(16);
}
}
}
public List<Block> getValidSpawnsAt(Chunk chunk, int x, int z, Range check) {
List<Block> blocks = new ArrayList<>();
for(int y : check) {
if(chunk.getBlock(x, y, z).getType().isSolid() && chunk.getBlock(x, y + 1, z).getType().isAir()) {
blocks.add(chunk.getBlock(x, y, z));
}
}
return blocks;
}
}

View File

@ -0,0 +1,157 @@
package com.dfsek.terra.procgen.math;
import org.bukkit.util.Vector;
/**
* oh yeah
*/
public class Vector2 implements Cloneable {
private double x;
private double z;
/**
* Create a vector with a given X and Z component
* @param x X component
* @param z Z component
*/
public Vector2(double x, double z) {
this.x = x;
this.z = z;
}
/**
* Get X component
* @return X component
*/
public double getX() {
return x;
}
/**
* Get Z component
* @return Z component
*/
public double getZ() {
return z;
}
/**
* Multiply X and Z components by a value.
* @param m Value to multiply
* @return Mutated vector, for chaining.
*/
public Vector2 multiply(double m) {
x*=m;
z*=m;
return this;
}
/**
* Divide X and Z components by a value.
* @param d Divisor
* @return Mutated vector, for chaining.
*/
public Vector2 divide(double d) {
x/=d;
z/=d;
return this;
}
/**
* Get the squared length of this Vector
* @return squared length
*/
public double lengthSquared() {
return x*x+z*z;
}
/**
* Get the length of this Vector
* @return length
*/
public double length() {
return Math.sqrt(lengthSquared());
}
/**
* Add this vector to another.
* @param other Vector to add
* @return Mutated vector, for chaining.
*/
public Vector2 add(Vector2 other) {
x+=other.x;
z+=other.z;
return this;
}
/**
* Subtract a vector from this vector,
* @param other Vector to subtract
* @return Mutated vector, for chaining.
*/
public Vector2 subtract(Vector2 other) {
x-=other.x;
z-=other.z;
return this;
}
/**
* Normalize this vector to length 1
* @return Mutated vector, for chaining.
*/
public Vector2 normalize() {
divide(length());
return this;
}
/**
* Get the distance from this vector to another.
* @param other Another vector
* @return Distance between vectors
*/
public double distance(Vector2 other) {
return Math.sqrt(distanceSquared(other));
}
/**
* Get the squared distance between 2 vectors.
* @param other Another vector
* @return Squared distance
*/
public double distanceSquared(Vector2 other) {
double dx = other.x - x;
double dz = other.z - z;
return dx * dx + dz * dz;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Vector2)) {
return false;
}
Vector2 other = (Vector2) obj;
return other.x == this.x && other.z == this.z;
}
@Override
public int hashCode() {
int hash = 17;
hash = 31 * hash + Double.hashCode(x);
hash = 31 * hash + Double.hashCode(z);
return hash;
}
@Override
public String toString() {
return "(" + x + ", " + z + ")";
}
@Override
public Vector2 clone() {
try {
return (Vector2) super.clone();
} catch (CloneNotSupportedException e) {
throw new Error(e);
}
}
}

View File

@ -0,0 +1,7 @@
package com.dfsek.terra.procgen.pixel;
public class Distribution {
public Distribution(Rectangle bound, int numPoints, double minRad) {
}
}

View File

@ -0,0 +1,9 @@
package com.dfsek.terra.procgen.pixel;
import com.dfsek.terra.procgen.math.Vector2;
import java.util.Set;
public abstract class Polygon {
public abstract Set<Vector2> getContainedPixels();
}

View File

@ -0,0 +1,31 @@
package com.dfsek.terra.procgen.pixel;
import com.dfsek.terra.procgen.math.Vector2;
import java.util.HashSet;
import java.util.Set;
public class Rectangle extends Polygon {
private Vector2 min;
private Vector2 max;
public Rectangle(Vector2 min, Vector2 max) {
this.max = new Vector2(Math.min(min.getX(), max.getX()), Math.min(min.getZ(), max.getZ()));
this.min = new Vector2(Math.max(min.getX(), max.getX()), Math.max(min.getZ(), max.getZ()));;
}
public Rectangle(Vector2 center, double xRadius, double zRadius) {
Vector2 rad = new Vector2(xRadius, zRadius);
this.min = center.clone().subtract(rad);
this.max = center.clone().add(rad);
}
@Override
public Set<Vector2> getContainedPixels() {
Set<Vector2> pixels = new HashSet<>();
for(int x = (int) min.getX(); x <= max.getX(); x++) {
for(int z = (int) min.getZ(); z <= max.getZ(); z++) {
pixels.add(new Vector2(x, z));
}
}
return pixels;
}
}

View File

@ -17,7 +17,7 @@ public abstract class VoxelGeometry {
}
public void merge(VoxelGeometry other) {
geometry.addAll(other.getGeometry());
geometry.addAll(other.geometry);
}
public static VoxelGeometry getBlank() {
return new VoxelGeometry() {};