Add y-level specific snow, more mountain biomes in default config.

This commit is contained in:
dfsek 2020-10-10 01:22:00 -07:00
parent 4e8ff7ffbb
commit aa378b40ec
8 changed files with 162 additions and 93 deletions

View File

@ -32,7 +32,7 @@ public class BiomeCommand extends WorldCommand {
@Override @Override
public List<com.dfsek.terra.command.type.Command> getSubCommands() { public List<com.dfsek.terra.command.type.Command> getSubCommands() {
return Arrays.asList(new BiomeLocateCommand(true), new BiomeLocateCommand(false)); return Arrays.asList(new BiomeLocateCommand(true), new BiomeLocateCommand(false), new BiomeInfoCommand());
} }
@Override @Override

View File

@ -0,0 +1,72 @@
package com.dfsek.terra.command.biome;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.biome.TerraBiomeGrid;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.command.type.WorldCommand;
import com.dfsek.terra.config.TerraConfig;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.genconfig.StructureConfig;
import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.generation.TerraChunkGenerator;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.polydev.gaea.generation.GenerationPhase;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class BiomeInfoCommand extends WorldCommand {
@Override
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) {
String id = args[0];
ConfigPack cfg = TerraWorld.getWorld(world).getConfig();
UserDefinedBiome b;
try {
b = cfg.getBiome(id).getBiome();
} catch(IllegalArgumentException | NullPointerException e) {
LangUtil.send("command.biome.invalid", sender, id);
return true;
}
sender.sendMessage("Biome info for \"" + b.getID() + "\".");
sender.sendMessage("Vanilla biome: " + b.getVanillaBiome());
sender.sendMessage("Erodible: " + b.isErodible());
sender.sendMessage("-------Structures-------");
List<StructureConfig> structureConfigs = cfg.getBiome(b).getStructures();
for(StructureConfig c : structureConfigs) {
sender.sendMessage(" - " + c.getID());
}
return true;
}
@Override
public String getName() {
return "info";
}
@Override
public List<com.dfsek.terra.command.type.Command> getSubCommands() {
return Collections.emptyList();
}
@Override
public int arguments() {
return 1;
}
@Override
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
if(!(sender instanceof Player) || !(((Player) sender).getWorld().getGenerator() instanceof TerraChunkGenerator)) return Collections.emptyList();
List<String> ids = TerraWorld.getWorld(((Player) sender).getWorld()).getConfig().getBiomeIDs();
if(args.length == 1) return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList());
return Collections.emptyList();
}
}

View File

@ -12,17 +12,8 @@ import java.util.Map;
public class AbstractBiomeConfig extends TerraConfig { public class AbstractBiomeConfig extends TerraConfig {
private final String biomeID; private final String biomeID;
private final int floraChance;
private final int treeChance;
private final int treeDensity;
private final String equation; private final String equation;
private final int floraAttempts;
private final int snowChance;
private double slabThreshold;
private BiomeSlabConfig slabs; private BiomeSlabConfig slabs;
private final boolean floraSimplex;
private final int floraSeed;
private final float floraFreq;
private final int seaLevel; private final int seaLevel;
private List<String> structureConfigs; private List<String> structureConfigs;
private BiomePaletteConfig palette; private BiomePaletteConfig palette;
@ -31,6 +22,7 @@ public class AbstractBiomeConfig extends TerraConfig {
private BiomeTreeConfig trees; private BiomeTreeConfig trees;
private BiomeOreConfig ores; private BiomeOreConfig ores;
private BiomeOceanConfig ocean; private BiomeOceanConfig ocean;
private BiomeSnowConfig snow;
public AbstractBiomeConfig(File file, ConfigPack config) throws IOException, InvalidConfigurationException { public AbstractBiomeConfig(File file, ConfigPack config) throws IOException, InvalidConfigurationException {
super(file, config); super(file, config);
@ -38,16 +30,8 @@ public class AbstractBiomeConfig extends TerraConfig {
if(!contains("id")) throw new ConfigException("Abstract Biome ID unspecified!", "null"); if(!contains("id")) throw new ConfigException("Abstract Biome ID unspecified!", "null");
this.biomeID = getString("id"); this.biomeID = getString("id");
floraChance = getInt("flora-chance", 0);
floraAttempts = getInt("flora-attempts", 1);
treeChance = getInt("tree-chance", 0);
treeDensity = getInt("tree-density", 0);
equation = getString("noise-equation"); equation = getString("noise-equation");
floraSimplex = getBoolean("flora-simplex.enable", false);
floraFreq = (float) getDouble("flora-simplex.frequency", 0.1);
floraSeed = getInt("flora-simplex.seed", 0);
seaLevel = getInt("ocean.level", 62); seaLevel = getInt("ocean.level", 62);
snowChance = getInt("snow-chance", 0);
if(contains("carving")) carving = new BiomeCarverConfig(this); if(contains("carving")) carving = new BiomeCarverConfig(this);
@ -64,6 +48,8 @@ public class AbstractBiomeConfig extends TerraConfig {
if(contains("slabs") && getBoolean("slabs.enable", false)) slabs = new BiomeSlabConfig(this); if(contains("slabs") && getBoolean("slabs.enable", false)) slabs = new BiomeSlabConfig(this);
if(contains("structures")) structureConfigs = getStringList("structures"); if(contains("structures")) structureConfigs = getStringList("structures");
if(contains("snow")) snow = new BiomeSnowConfig(this);
} }
@Override @Override
@ -71,42 +57,10 @@ public class AbstractBiomeConfig extends TerraConfig {
return biomeID; return biomeID;
} }
public int getFloraAttempts() {
return floraAttempts;
}
public int getFloraChance() {
return floraChance;
}
public int getTreeChance() {
return treeChance;
}
public int getTreeDensity() {
return treeDensity;
}
public String getEquation() { public String getEquation() {
return equation; return equation;
} }
public double getSlabThreshold() {
return slabThreshold;
}
public float getFloraFreq() {
return floraFreq;
}
public int getFloraSeed() {
return floraSeed;
}
public boolean isFloraSimplex() {
return floraSimplex;
}
public BiomePaletteConfig getPaletteData() { public BiomePaletteConfig getPaletteData() {
return palette; return palette;
} }
@ -143,7 +97,7 @@ public class AbstractBiomeConfig extends TerraConfig {
return structureConfigs; return structureConfigs;
} }
public int getSnowChance() { public BiomeSnowConfig getSnow() {
return snowChance; return snow;
} }
} }

View File

@ -3,35 +3,25 @@ package com.dfsek.terra.config.genconfig.biome;
import com.dfsek.terra.Debug; import com.dfsek.terra.Debug;
import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.carving.UserDefinedCarver; import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.TerraConfig; import com.dfsek.terra.config.TerraConfig;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.exception.ConfigException; import com.dfsek.terra.config.exception.ConfigException;
import com.dfsek.terra.config.exception.NotFoundException; import com.dfsek.terra.config.exception.NotFoundException;
import com.dfsek.terra.config.genconfig.OreConfig;
import com.dfsek.terra.config.genconfig.StructureConfig; import com.dfsek.terra.config.genconfig.StructureConfig;
import com.dfsek.terra.generation.UserDefinedDecorator; import com.dfsek.terra.generation.UserDefinedDecorator;
import com.dfsek.terra.generation.UserDefinedGenerator; import com.dfsek.terra.generation.UserDefinedGenerator;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.InvalidConfigurationException;
import org.polydev.gaea.math.FastNoise;
import org.polydev.gaea.math.ProbabilityCollection;
import org.polydev.gaea.math.Range; import org.polydev.gaea.math.Range;
import org.polydev.gaea.math.parsii.tokenizer.ParseException; import org.polydev.gaea.math.parsii.tokenizer.ParseException;
import org.polydev.gaea.tree.Tree; import org.polydev.gaea.tree.Tree;
import org.polydev.gaea.world.Flora; import org.polydev.gaea.world.Flora;
import org.polydev.gaea.world.palette.Palette;
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.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Random;
public class BiomeConfig extends TerraConfig { public class BiomeConfig extends TerraConfig {
@ -43,9 +33,9 @@ public class BiomeConfig extends TerraConfig {
private final BiomeTreeConfig tree; private final BiomeTreeConfig tree;
private final BiomeOceanConfig ocean; private final BiomeOceanConfig ocean;
private final BiomeSlabConfig slab; private final BiomeSlabConfig slab;
private final BiomeSnowConfig snow;
private String eq; private String eq;
private int snowChance;
private final List<StructureConfig> structures; private final List<StructureConfig> structures;
private final ConfigPack config; private final ConfigPack config;
@ -73,10 +63,8 @@ public class BiomeConfig extends TerraConfig {
// Get various simple values using getOrDefault config methods. // Get various simple values using getOrDefault config methods.
try { try {
snowChance = getInt("snow-chance", Objects.requireNonNull(abstractBiome).getSnowChance());
eq = getString("noise-equation", Objects.requireNonNull(abstractBiome).getEquation()); eq = getString("noise-equation", Objects.requireNonNull(abstractBiome).getEquation());
} catch(NullPointerException e) { } catch(NullPointerException e) {
snowChance = getInt("snow-chance", 0);
eq = getString("noise-equation", null); eq = getString("noise-equation", null);
} }
@ -126,6 +114,12 @@ public class BiomeConfig extends TerraConfig {
Debug.info("Using super ocean"); Debug.info("Using super ocean");
} else ocean = new BiomeOceanConfig(this); } else ocean = new BiomeOceanConfig(this);
// Get ocean stuff
if(extending && abstractBiome.getSnow() != null) {
snow = abstractBiome.getSnow();
Debug.info("Using super snow");
} else snow = new BiomeSnowConfig(this);
//Make sure equation is non-null //Make sure equation is non-null
if(eq == null || eq.equals("")) throw new ConfigException("Could not find noise equation! Biomes must include a noise equation, or extend an abstract biome with one.", getID()); if(eq == null || eq.equals("")) throw new ConfigException("Could not find noise equation! Biomes must include a noise equation, or extend an abstract biome with one.", getID());
@ -208,7 +202,7 @@ public class BiomeConfig extends TerraConfig {
return tree.getTreeHeights().getOrDefault(t, new Range(-1, -1)); return tree.getTreeHeights().getOrDefault(t, new Range(-1, -1));
} }
public int getSnowChance() { public BiomeSnowConfig getSnow() {
return snowChance; return snow;
} }
} }

View File

@ -0,0 +1,52 @@
package com.dfsek.terra.config.genconfig.biome;
import com.dfsek.terra.Debug;
import com.dfsek.terra.config.TerraConfig;
import com.dfsek.terra.config.TerraConfigSection;
import com.dfsek.terra.config.base.ConfigUtil;
import com.dfsek.terra.config.exception.ConfigException;
import com.dfsek.terra.config.exception.NotFoundException;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.jetbrains.annotations.NotNull;
import org.polydev.gaea.math.FastNoise;
import org.polydev.gaea.math.ProbabilityCollection;
import org.polydev.gaea.math.Range;
import org.polydev.gaea.world.Flora;
import org.polydev.gaea.world.FloraType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BiomeSnowConfig extends TerraConfigSection {
private final int[] snowHeights;
private boolean doSnow = false;
public BiomeSnowConfig(TerraConfig parent) throws InvalidConfigurationException {
super(parent);
snowHeights = new int[256];
List<Map<?, ?>> maps = parent.getMapList("snow");
if(maps.size() == 0) return;
try {
for(Map<?, ?> e : maps) {
Range r = new Range((Integer) e.get("min"), (Integer) e.get("max"));
int chance = (Integer) e.get("chance");
for(int y : r) {
if(chance > 0) doSnow = true;
snowHeights[y] = chance;
}
}
} catch(ClassCastException e) {
if(ConfigUtil.debug) e.printStackTrace();
throw new ConfigException("Unable to parse Snow configuration! Check YAML syntax.", parent.getID());
}
}
public int getSnowChance(int y) {
return snowHeights[y];
}
public boolean doSnow() {
return doSnow;
}
}

View File

@ -102,18 +102,23 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
private void prepareBlockPart(BlockData down, BlockData orig, ChunkData chunk, Vector block, Map<Material, Palette<BlockData>> slabs, Map<Material, Palette<BlockData>> stairs, double thresh) { private void prepareBlockPart(BlockData down, BlockData orig, ChunkData chunk, Vector block, Map<Material, Palette<BlockData>> slabs, Map<Material, Palette<BlockData>> stairs, double thresh) {
double _11 = getInterpolatedNoise(block.getBlockX(), block.getBlockY() - 0.4, block.getBlockZ()); double _11 = getInterpolatedNoise(block.getBlockX(), block.getBlockY() - 0.4, block.getBlockZ());
if(_11 > thresh) { if(_11 > thresh) {
double _01 = getInterpolatedNoise(block.getBlockX() - 0.5, block.getBlockY(), block.getBlockZ());
double _10 = getInterpolatedNoise(block.getBlockX(), block.getBlockY(), block.getBlockZ() - 0.5);
double _12 = getInterpolatedNoise(block.getBlockX(), block.getBlockY(), block.getBlockZ() + 0.5);
double _21 = getInterpolatedNoise(block.getBlockX() + 0.5, block.getBlockY(), block.getBlockZ());
if(stairs != null) { if(stairs != null) {
Palette<BlockData> stairPalette = stairs.get(down.getMaterial()); Palette<BlockData> stairPalette = stairs.get(down.getMaterial());
if(stairPalette != null) { if(stairPalette != null) {
BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ()); BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ());
Stairs finalStair = getStair(new double[] {_01, _10, _12, _21}, (Stairs) stair, thresh); Stairs stairNew = (Stairs) stair.clone();
if(finalStair != null) { if(getInterpolatedNoise(block.getBlockX() - 0.5, block.getBlockY(), block.getBlockZ()) > thresh) {
if(orig.matches(DataUtil.WATER)) finalStair.setWaterlogged(true); stairNew.setFacing(BlockFace.WEST);
chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), finalStair); } else if(getInterpolatedNoise(block.getBlockX(), block.getBlockY(), block.getBlockZ() - 0.5) > thresh) {
stairNew.setFacing(BlockFace.NORTH);
} else if(getInterpolatedNoise(block.getBlockX(), block.getBlockY(), block.getBlockZ() + 0.5) > thresh) {
stairNew.setFacing(BlockFace.SOUTH);
} else if(getInterpolatedNoise(block.getBlockX() + 0.5, block.getBlockY(), block.getBlockZ()) > thresh) {
stairNew.setFacing(BlockFace.EAST);
} else stairNew = null;
if(stairNew != null) {
if(orig.matches(DataUtil.WATER)) stairNew.setWaterlogged(true);
chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), stairNew);
return; return;
} }
} }
@ -126,21 +131,6 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
} }
} }
private static Stairs getStair(double[] vals, Stairs stair, double thresh) {
if(vals.length != 4) throw new IllegalArgumentException();
Stairs stairNew = (Stairs) stair.clone();
if(vals[0] > thresh) {
stairNew.setFacing(BlockFace.WEST);
} else if(vals[1] > thresh) {
stairNew.setFacing(BlockFace.NORTH);
} else if(vals[2] > thresh) {
stairNew.setFacing(BlockFace.SOUTH);
} else if(vals[3] > thresh) {
stairNew.setFacing(BlockFace.EAST);
} else return null;
return stairNew;
}
private void load(World w) { private void load(World w) {
try { try {
popMan.loadBlocks(w); popMan.loadBlocks(w);

View File

@ -50,13 +50,13 @@ public class SnowPopulator extends GaeaBlockPopulator {
TerraBiomeGrid g = w.getGrid(); TerraBiomeGrid g = w.getGrid();
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++) {
if(random.nextInt(100) >= w.getConfig().getBiome((UserDefinedBiome) g.getBiome(origX+x, origZ+z, GenerationPhase.PALETTE_APPLY)).getSnowChance()) continue;
int y; int y;
Block b = null; Block b = null;
for(y = 254; y > 0; y--) { for(y = 254; y > 0; y--) {
b = chunk.getBlock(x, y, z); b = chunk.getBlock(x, y, z);
if(!b.getType().isAir()) break; if(!b.getType().isAir()) break;
} }
if(random.nextInt(100) >= w.getConfig().getBiome((UserDefinedBiome) g.getBiome(origX+x, origZ+z, GenerationPhase.PALETTE_APPLY)).getSnow().getSnowChance(y)) continue;
if(blacklistSpawn.contains(b.getType()) || b.isPassable()) continue; if(blacklistSpawn.contains(b.getType()) || b.isPassable()) continue;
chunk.getBlock(x, ++y, z).setBlockData(DataUtil.SNOW); chunk.getBlock(x, ++y, z).setBlockData(DataUtil.SNOW);
} }

View File

@ -2,6 +2,7 @@ package com.dfsek.terra.structure;
import com.dfsek.terra.Debug; import com.dfsek.terra.Debug;
import com.dfsek.terra.procgen.math.Vector2; import com.dfsek.terra.procgen.math.Vector2;
import com.dfsek.terra.util.structure.RotationUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
@ -31,8 +32,10 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -188,9 +191,13 @@ public class Structure implements Serializable {
org.bukkit.Axis newAxis = getRotatedAxis(((Orientable) data).getAxis(), r); org.bukkit.Axis newAxis = getRotatedAxis(((Orientable) data).getAxis(), r);
((Orientable) data).setAxis(newAxis); ((Orientable) data).setAxis(newAxis);
} else if(data instanceof RedstoneWire) { } else if(data instanceof RedstoneWire) {
Map<BlockFace, RedstoneWire.Connection> connections = new HashMap<>();
RedstoneWire rData = (RedstoneWire) data; RedstoneWire rData = (RedstoneWire) data;
for(BlockFace f : rData.getAllowedFaces()) { for(BlockFace f : rData.getAllowedFaces()) {
rData.setFace(getRotatedFace(f, r), rData.getFace(f)); connections.put(f, rData.getFace(f));
}
for(Map.Entry<BlockFace, RedstoneWire.Connection> e : connections.entrySet()) {
rData.setFace(RotationUtil.getRotatedFace(e.getKey(), r), e.getValue());
} }
} }
worldBlock.setBlockData(data, false); worldBlock.setBlockData(data, false);