Add more Flora config options

This commit is contained in:
dfsek 2020-09-24 02:18:08 -07:00
parent ae4be37fe8
commit fd49d0a99c
5 changed files with 107 additions and 32 deletions

View File

@ -10,6 +10,10 @@ public class MaxMin {
this.min = min; this.min = min;
} }
public boolean isInRange(int test) {
return test >= min && test < max;
}
public int getMax() { public int getMax() {
return max; return max;
} }

View File

@ -2,6 +2,7 @@ package com.dfsek.terra.config.genconfig;
import com.dfsek.terra.MaxMin; import com.dfsek.terra.MaxMin;
import com.dfsek.terra.TerraTree; import com.dfsek.terra.TerraTree;
import com.dfsek.terra.config.ConfigUtil;
import com.dfsek.terra.config.TerraConfigObject; import com.dfsek.terra.config.TerraConfigObject;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -36,6 +37,8 @@ public class AbstractBiomeConfig extends TerraConfigObject {
private int treeChance; private int treeChance;
private int treeDensity; private int treeDensity;
private String equation; private String equation;
private int floraAttempts;
private Map<Flora, MaxMin> floraHeights;
private TreeMap<Integer, Palette<BlockData>> paletteMap; private TreeMap<Integer, Palette<BlockData>> paletteMap;
public AbstractBiomeConfig(File file) throws IOException, InvalidConfigurationException { public AbstractBiomeConfig(File file) throws IOException, InvalidConfigurationException {
@ -91,21 +94,32 @@ public class AbstractBiomeConfig extends TerraConfigObject {
} }
if(contains("flora")) { if(contains("flora")) {
floraHeights = new HashMap<>();
flora = new ProbabilityCollection<>(); flora = new ProbabilityCollection<>();
for(Map.Entry<String, Object> e : Objects.requireNonNull(getConfigurationSection("flora")).getValues(false).entrySet()) {
try { try {
Bukkit.getLogger().info("[Terra] Adding " + e.getKey() + " to abstract biome's flora list with weight " + e.getValue()); for(Map.Entry<String, Object> e : Objects.requireNonNull(getConfigurationSection("flora")).getValues(false).entrySet()) {
flora.add(FloraType.valueOf(e.getKey()), (Integer) e.getValue()); Map<?, ?> val = ((ConfigurationSection) e.getValue()).getValues(false);
Map<?, ?> y = ((ConfigurationSection) val.get("y")).getValues(false);
try {
Bukkit.getLogger().info("[Terra] Adding " + e.getKey() + " to biome's flora list with weight " + e.getValue());
Flora floraObj = FloraType.valueOf(e.getKey());
flora.add(floraObj, (Integer) val.get("weight"));
floraHeights.put(floraObj, new MaxMin((Integer) y.get("min"), (Integer) y.get("max")));
} catch(IllegalArgumentException ex) { } catch(IllegalArgumentException ex) {
try { try {
Bukkit.getLogger().info("[Terra] Is custom flora: true"); Bukkit.getLogger().info("[Terra] Is custom flora: true");
Flora floraCustom = FloraConfig.fromID(e.getKey()); Flora floraCustom = FloraConfig.fromID(e.getKey());
flora.add(floraCustom, (Integer) e.getValue()); flora.add(floraCustom, (Integer) val.get("weight"));
floraHeights.put(floraCustom, new MaxMin((Integer) y.get("min"), (Integer) y.get("max")));
} catch(NullPointerException ex2) { } catch(NullPointerException ex2) {
throw new IllegalArgumentException("SEVERE configuration error for flora in abstract biome, ID " + getID() + "\n\nFlora with ID " + e.getKey() + " cannot be found!"); throw new InvalidConfigurationException("SEVERE configuration error for flora in biome, ID " + getID() + "\n\nFlora with ID " + e.getKey() + " cannot be found!");
} }
} }
} }
} catch(ClassCastException e) {
if(ConfigUtil.debug) e.printStackTrace();
throw new InvalidConfigurationException("SEVERE configuration error for flora in biome, ID " + getID());
}
} }
if(contains("trees")) { if(contains("trees")) {
trees = new ProbabilityCollection<>(); trees = new ProbabilityCollection<>();
@ -118,6 +132,7 @@ public class AbstractBiomeConfig extends TerraConfigObject {
} }
} }
floraChance = getInt("flora-chance", 0); floraChance = getInt("flora-chance", 0);
floraAttempts = getInt("flora-attempts", 1);
treeChance = getInt("tree-chance", 0); treeChance = getInt("tree-chance", 0);
treeDensity = getInt("tree-density", 0); treeDensity = getInt("tree-density", 0);
equation = getString("noise-equation"); equation = getString("noise-equation");
@ -139,6 +154,10 @@ public class AbstractBiomeConfig extends TerraConfigObject {
return biomeID; return biomeID;
} }
public int getFloraAttempts() {
return floraAttempts;
}
public int getFloraChance() { public int getFloraChance() {
return floraChance; return floraChance;
} }
@ -163,6 +182,10 @@ public class AbstractBiomeConfig extends TerraConfigObject {
return ores; return ores;
} }
public Map<Flora, MaxMin> getFloraHeights() {
return floraHeights;
}
public static Map<String, AbstractBiomeConfig> getBiomes() { public static Map<String, AbstractBiomeConfig> getBiomes() {
return biomes; return biomes;
} }

View File

@ -6,6 +6,7 @@ import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.UserDefinedDecorator; import com.dfsek.terra.biome.UserDefinedDecorator;
import com.dfsek.terra.biome.UserDefinedGenerator; import com.dfsek.terra.biome.UserDefinedGenerator;
import com.dfsek.terra.carving.UserDefinedCarver; import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.ConfigUtil;
import com.dfsek.terra.config.TerraConfigObject; import com.dfsek.terra.config.TerraConfigObject;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -39,7 +40,9 @@ public class BiomeConfig extends TerraConfigObject {
private Map<OreConfig, MaxMin> ores; private Map<OreConfig, MaxMin> ores;
private Map<OreConfig, MaxMin> oreHeights; private Map<OreConfig, MaxMin> oreHeights;
private Map<CarverConfig, Integer> carvers; private Map<CarverConfig, Integer> carvers;
private Map<Flora, MaxMin> floraHeights;
private String eq; private String eq;
private int floraAttempts;
public BiomeConfig(File file) throws InvalidConfigurationException, IOException { public BiomeConfig(File file) throws InvalidConfigurationException, IOException {
super(file); super(file);
@ -47,10 +50,6 @@ public class BiomeConfig extends TerraConfigObject {
@Override @Override
public void init() throws InvalidConfigurationException { public void init() throws InvalidConfigurationException {
oreHeights = new HashMap<>();
ores = new HashMap<>();
ProbabilityCollection<Flora> flora = new ProbabilityCollection<>();
ProbabilityCollection<Tree> trees = new ProbabilityCollection<>();
if(!contains("id")) throw new InvalidConfigurationException("Biome ID unspecified!"); if(!contains("id")) throw new InvalidConfigurationException("Biome ID unspecified!");
this.biomeID = getString("id"); this.biomeID = getString("id");
if(!contains("name")) throw new InvalidConfigurationException("Biome Name unspecified!"); if(!contains("name")) throw new InvalidConfigurationException("Biome Name unspecified!");
@ -128,38 +127,55 @@ public class BiomeConfig extends TerraConfigObject {
// Get various simple values using getOrDefault config methods. // Get various simple values using getOrDefault config methods.
try { try {
floraChance = getInt("flora-chance", Objects.requireNonNull(abstractBiome).getFloraChance()); floraChance = getInt("flora-chance", Objects.requireNonNull(abstractBiome).getFloraChance());
floraAttempts = getInt("flora-attempts", Objects.requireNonNull(abstractBiome).getFloraAttempts());
treeChance = getInt("tree-chance", Objects.requireNonNull(abstractBiome).getTreeChance()); treeChance = getInt("tree-chance", Objects.requireNonNull(abstractBiome).getTreeChance());
treeDensity = getInt("tree-density", Objects.requireNonNull(abstractBiome).getTreeDensity()); treeDensity = getInt("tree-density", Objects.requireNonNull(abstractBiome).getTreeDensity());
eq = getString("noise-equation", Objects.requireNonNull(abstractBiome).getEquation()); eq = getString("noise-equation", Objects.requireNonNull(abstractBiome).getEquation());
} catch(NullPointerException e) { } catch(NullPointerException e) {
floraChance = getInt("flora-chance", 0); floraChance = getInt("flora-chance", 0);
floraAttempts = getInt("flora-attempts", 1);
treeChance = getInt("tree-chance", 0); treeChance = getInt("tree-chance", 0);
treeDensity = getInt("tree-density", 0); treeDensity = getInt("tree-density", 0);
eq = getString("noise-equation", null); eq = getString("noise-equation", null);
} }
// Check if flora should be handled by super biome. // Check if flora should be handled by super biome.
ProbabilityCollection<Flora> flora = new ProbabilityCollection<>();
if(extending && abstractBiome.getFlora() != null && !contains("flora")) { if(extending && abstractBiome.getFlora() != null && !contains("flora")) {
flora = abstractBiome.getFlora(); flora = abstractBiome.getFlora();
floraHeights = abstractBiome.getFloraHeights();
Bukkit.getLogger().info("Using super flora (" + flora.size() + " entries, " + floraChance + " % chance)"); Bukkit.getLogger().info("Using super flora (" + flora.size() + " entries, " + floraChance + " % chance)");
} else if(contains("flora")) { } else if(contains("flora")) {
floraHeights = new HashMap<>();
try {
for(Map.Entry<String, Object> e : Objects.requireNonNull(getConfigurationSection("flora")).getValues(false).entrySet()) { for(Map.Entry<String, Object> e : Objects.requireNonNull(getConfigurationSection("flora")).getValues(false).entrySet()) {
Map<?, ?> val = ((ConfigurationSection) e.getValue()).getValues(false);
Map<?, ?> y = ((ConfigurationSection) val.get("y")).getValues(false);
try { try {
Bukkit.getLogger().info("[Terra] Adding " + e.getKey() + " to biome's flora list with weight " + e.getValue()); Bukkit.getLogger().info("[Terra] Adding " + e.getKey() + " to biome's flora list with weight " + e.getValue());
flora.add(FloraType.valueOf(e.getKey()), (Integer) e.getValue()); Flora floraObj = FloraType.valueOf(e.getKey());
flora.add(floraObj, (Integer) val.get("weight"));
floraHeights.put(floraObj, new MaxMin((Integer) y.get("min"), (Integer) y.get("max")));
} catch(IllegalArgumentException ex) { } catch(IllegalArgumentException ex) {
try { try {
Bukkit.getLogger().info("[Terra] Is custom flora: true"); Bukkit.getLogger().info("[Terra] Is custom flora: true");
Flora floraCustom = FloraConfig.fromID(e.getKey()); Flora floraCustom = FloraConfig.fromID(e.getKey());
flora.add(floraCustom, (Integer) e.getValue()); flora.add(floraCustom, (Integer) val.get("weight"));
floraHeights.put(floraCustom, new MaxMin((Integer) y.get("min"), (Integer) y.get("max")));
} catch(NullPointerException ex2) { } catch(NullPointerException ex2) {
throw new IllegalArgumentException("SEVERE configuration error for flora in biome " + getFriendlyName() + ", ID " + getID() + "\n\nFlora with ID " + e.getKey() + " cannot be found!"); throw new InvalidConfigurationException("SEVERE configuration error for flora in biome " + getFriendlyName() + ", ID " + getID() + "\n\nFlora with ID " + e.getKey() + " cannot be found!");
} }
} }
} }
} catch(ClassCastException e) {
if(ConfigUtil.debug) e.printStackTrace();
throw new InvalidConfigurationException("SEVERE configuration error for flora in biome " + getFriendlyName() + ", ID " + getID());
}
} else flora = new ProbabilityCollection<>(); } else flora = new ProbabilityCollection<>();
if(extending && abstractBiome.getTrees() != null && !contains("trees")) { // Check if trees should be handled by super biome. // Check if trees should be handled by super biome.
ProbabilityCollection<Tree> trees = new ProbabilityCollection<>();
if(extending && abstractBiome.getTrees() != null && !contains("trees")) {
trees = abstractBiome.getTrees(); trees = abstractBiome.getTrees();
Bukkit.getLogger().info("Using super trees"); Bukkit.getLogger().info("Using super trees");
} else if(contains("trees")) { } else if(contains("trees")) {
@ -188,6 +204,8 @@ public class BiomeConfig extends TerraConfigObject {
} }
// Check if ores should be handled by super biome. // Check if ores should be handled by super biome.
oreHeights = new HashMap<>();
ores = new HashMap<>();
if(extending && abstractBiome.getOres() != null && !contains("ores")) { if(extending && abstractBiome.getOres() != null && !contains("ores")) {
ores = abstractBiome.getOres(); ores = abstractBiome.getOres();
oreHeights = abstractBiome.getOreHeights(); oreHeights = abstractBiome.getOreHeights();
@ -221,6 +239,10 @@ public class BiomeConfig extends TerraConfigObject {
return biome; return biome;
} }
public int getFloraAttempts() {
return floraAttempts;
}
public String getID() { public String getID() {
return biomeID; return biomeID;
} }
@ -233,6 +255,10 @@ public class BiomeConfig extends TerraConfigObject {
return ores; return ores;
} }
public MaxMin getFloraHeights(Flora f) {
return floraHeights.computeIfAbsent(f, input -> new MaxMin(-1, -1));
}
public static BiomeConfig fromBiome(UserDefinedBiome b) { public static BiomeConfig fromBiome(UserDefinedBiome b) {
for(BiomeConfig biome : biomes.values()) { for(BiomeConfig biome : biomes.values()) {
if(biome.getBiome().equals(b)) return biome; if(biome.getBiome().equals(b)) return biome;

View File

@ -16,9 +16,11 @@ import org.polydev.gaea.world.palette.RandomPalette;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set;
public class FloraConfig extends TerraConfigObject implements Flora { public class FloraConfig extends TerraConfigObject implements Flora {
private static final Map<String, FloraConfig> floraConfig = new HashMap<>(); private static final Map<String, FloraConfig> floraConfig = new HashMap<>();
@ -26,7 +28,9 @@ public class FloraConfig extends TerraConfigObject implements Flora {
private String id; private String id;
private String friendlyName; private String friendlyName;
List<Material> spawnable; Set<Material> spawnable;
Set<Material> replaceable;
public FloraConfig(File file) throws IOException, InvalidConfigurationException { public FloraConfig(File file) throws IOException, InvalidConfigurationException {
super(file); super(file);
} }
@ -38,12 +42,25 @@ public class FloraConfig extends TerraConfigObject implements Flora {
if(!contains("name")) throw new InvalidConfigurationException("Flora name unspecified!"); if(!contains("name")) throw new InvalidConfigurationException("Flora name unspecified!");
if(!contains("spawnable")) throw new InvalidConfigurationException("Flora spawnable blocks unspecified!"); if(!contains("spawnable")) throw new InvalidConfigurationException("Flora spawnable blocks unspecified!");
spawnable = new HashSet<>();
replaceable = new HashSet<>();
try { try {
spawnable = ConfigUtil.getElements(getStringList("spawnable"), Material.class); for(String s : getStringList("spawnable")) {
spawnable.add(Bukkit.createBlockData(s).getMaterial());
}
Bukkit.getLogger().info("[Terra] Added " + spawnable.size() + " items to spawnable list."); Bukkit.getLogger().info("[Terra] Added " + spawnable.size() + " items to spawnable list.");
} catch(IllegalArgumentException e) { } catch(IllegalArgumentException e) {
throw new InvalidConfigurationException("Invalid material ID in spawnable list: " + e.getMessage()); throw new InvalidConfigurationException("Invalid material ID in spawnable list: " + e.getMessage());
} }
try {
for(String s : getStringList("replaceable")) {
replaceable.add(Bukkit.createBlockData(s).getMaterial());
}
Bukkit.getLogger().info("[Terra] Added " + spawnable.size() + " items to replaceable list.");
} catch(IllegalArgumentException e) {
throw new InvalidConfigurationException("Invalid material ID in replaceable list: " + e.getMessage());
}
Palette<BlockData> p = new RandomPalette<>(new Random(getInt("seed", 4))); Palette<BlockData> p = new RandomPalette<>(new Random(getInt("seed", 4)));
@ -75,7 +92,7 @@ public class FloraConfig extends TerraConfigObject implements Flora {
public boolean plant(Location location) { public boolean plant(Location location) {
int size = floraPalette.getSize(); int size = floraPalette.getSize();
for(int i = 0; i < size; i++) { for(int i = 0; i < size; i++) {
if(!location.clone().add(0, i+1, 0).getBlock().isEmpty()) return false; if(!replaceable.contains(location.clone().add(0, i+1, 0).getBlock().getType())) return false;
} }
for(int i = 0; i < size; i++) { for(int i = 0; i < size; i++) {
location.clone().add(0, i+1, 0).getBlock().setBlockData(floraPalette.get(size-(i+1), location.getBlockX(), location.getBlockZ()), false); location.clone().add(0, i+1, 0).getBlock().setBlockData(floraPalette.get(size-(i+1), location.getBlockX(), location.getBlockZ()), false);

View File

@ -2,6 +2,8 @@ package com.dfsek.terra.population;
import com.dfsek.terra.TerraProfiler; import com.dfsek.terra.TerraProfiler;
import com.dfsek.terra.biome.TerraBiomeGrid; import com.dfsek.terra.biome.TerraBiomeGrid;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.genconfig.BiomeConfig;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -19,13 +21,16 @@ public class FloraPopulator extends GaeaBlockPopulator {
ProfileFuture flora = TerraProfiler.fromWorld(world).measure("FloraTime"); ProfileFuture flora = TerraProfiler.fromWorld(world).measure("FloraTime");
for(int x = 0; x < 16; x++) { for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) { for(int z = 0; z < 16; z++) {
Biome biome = 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);
if(biome.getDecorator().getFloraChance() <= 0 || random.nextInt(100) > biome.getDecorator().getFloraChance()) if(biome.getDecorator().getFloraChance() <= 0 || random.nextInt(100) > biome.getDecorator().getFloraChance())
continue; continue;
try { try {
BiomeConfig c = BiomeConfig.fromBiome(biome);
for(int i = 0; i < c.getFloraAttempts(); i++) {
Flora item = biome.getDecorator().getFlora().get(random); Flora item = biome.getDecorator().getFlora().get(random);
Block highest = item.getHighestValidSpawnAt(chunk, x, z); Block highest = item.getHighestValidSpawnAt(chunk, x, z);
if(highest != null) item.plant(highest.getLocation()); if(highest != null && c.getFloraHeights(item).isInRange(highest.getY())) item.plant(highest.getLocation());
}
} catch(NullPointerException ignored) {} } catch(NullPointerException ignored) {}
} }
} }