diff --git a/src/main/java/com/dfsek/terra/command/biome/BiomeCommand.java b/src/main/java/com/dfsek/terra/command/biome/BiomeCommand.java index 34da56a73..adf7193c8 100644 --- a/src/main/java/com/dfsek/terra/command/biome/BiomeCommand.java +++ b/src/main/java/com/dfsek/terra/command/biome/BiomeCommand.java @@ -32,7 +32,7 @@ public class BiomeCommand extends WorldCommand { @Override public List getSubCommands() { - return Arrays.asList(new BiomeLocateCommand(true), new BiomeLocateCommand(false)); + return Arrays.asList(new BiomeLocateCommand(true), new BiomeLocateCommand(false), new BiomeInfoCommand()); } @Override diff --git a/src/main/java/com/dfsek/terra/command/biome/BiomeInfoCommand.java b/src/main/java/com/dfsek/terra/command/biome/BiomeInfoCommand.java new file mode 100644 index 000000000..6ee7c6f65 --- /dev/null +++ b/src/main/java/com/dfsek/terra/command/biome/BiomeInfoCommand.java @@ -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 structureConfigs = cfg.getBiome(b).getStructures(); + + for(StructureConfig c : structureConfigs) { + sender.sendMessage(" - " + c.getID()); + } + + return true; + } + + @Override + public String getName() { + return "info"; + } + + @Override + public List getSubCommands() { + return Collections.emptyList(); + } + + @Override + public int arguments() { + return 1; + } + + @Override + public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { + if(!(sender instanceof Player) || !(((Player) sender).getWorld().getGenerator() instanceof TerraChunkGenerator)) return Collections.emptyList(); + List 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(); + } +} diff --git a/src/main/java/com/dfsek/terra/config/genconfig/biome/AbstractBiomeConfig.java b/src/main/java/com/dfsek/terra/config/genconfig/biome/AbstractBiomeConfig.java index 460a7d06d..41b53dd52 100644 --- a/src/main/java/com/dfsek/terra/config/genconfig/biome/AbstractBiomeConfig.java +++ b/src/main/java/com/dfsek/terra/config/genconfig/biome/AbstractBiomeConfig.java @@ -12,17 +12,8 @@ import java.util.Map; public class AbstractBiomeConfig extends TerraConfig { private final String biomeID; - private final int floraChance; - private final int treeChance; - private final int treeDensity; private final String equation; - private final int floraAttempts; - private final int snowChance; - private double slabThreshold; private BiomeSlabConfig slabs; - private final boolean floraSimplex; - private final int floraSeed; - private final float floraFreq; private final int seaLevel; private List structureConfigs; private BiomePaletteConfig palette; @@ -31,6 +22,7 @@ public class AbstractBiomeConfig extends TerraConfig { private BiomeTreeConfig trees; private BiomeOreConfig ores; private BiomeOceanConfig ocean; + private BiomeSnowConfig snow; public AbstractBiomeConfig(File file, ConfigPack config) throws IOException, InvalidConfigurationException { super(file, config); @@ -38,16 +30,8 @@ public class AbstractBiomeConfig extends TerraConfig { if(!contains("id")) throw new ConfigException("Abstract Biome ID unspecified!", "null"); 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"); - 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); - snowChance = getInt("snow-chance", 0); 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("structures")) structureConfigs = getStringList("structures"); + + if(contains("snow")) snow = new BiomeSnowConfig(this); } @Override @@ -71,42 +57,10 @@ public class AbstractBiomeConfig extends TerraConfig { 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() { 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() { return palette; } @@ -143,7 +97,7 @@ public class AbstractBiomeConfig extends TerraConfig { return structureConfigs; } - public int getSnowChance() { - return snowChance; + public BiomeSnowConfig getSnow() { + return snow; } } diff --git a/src/main/java/com/dfsek/terra/config/genconfig/biome/BiomeConfig.java b/src/main/java/com/dfsek/terra/config/genconfig/biome/BiomeConfig.java index 8472976d0..f2dcb88cc 100644 --- a/src/main/java/com/dfsek/terra/config/genconfig/biome/BiomeConfig.java +++ b/src/main/java/com/dfsek/terra/config/genconfig/biome/BiomeConfig.java @@ -3,35 +3,25 @@ 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.base.ConfigPack; 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.NotFoundException; -import com.dfsek.terra.config.genconfig.OreConfig; import com.dfsek.terra.config.genconfig.StructureConfig; import com.dfsek.terra.generation.UserDefinedDecorator; 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.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; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Objects; -import java.util.Random; public class BiomeConfig extends TerraConfig { @@ -43,9 +33,9 @@ public class BiomeConfig extends TerraConfig { private final BiomeTreeConfig tree; private final BiomeOceanConfig ocean; private final BiomeSlabConfig slab; + private final BiomeSnowConfig snow; private String eq; - private int snowChance; private final List structures; private final ConfigPack config; @@ -73,10 +63,8 @@ public class BiomeConfig extends TerraConfig { // Get various simple values using getOrDefault config methods. try { - snowChance = getInt("snow-chance", Objects.requireNonNull(abstractBiome).getSnowChance()); eq = getString("noise-equation", Objects.requireNonNull(abstractBiome).getEquation()); } catch(NullPointerException e) { - snowChance = getInt("snow-chance", 0); eq = getString("noise-equation", null); } @@ -126,6 +114,12 @@ public class BiomeConfig extends TerraConfig { Debug.info("Using super ocean"); } 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 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)); } - public int getSnowChance() { - return snowChance; + public BiomeSnowConfig getSnow() { + return snow; } } diff --git a/src/main/java/com/dfsek/terra/config/genconfig/biome/BiomeSnowConfig.java b/src/main/java/com/dfsek/terra/config/genconfig/biome/BiomeSnowConfig.java new file mode 100644 index 000000000..c6d9ba78b --- /dev/null +++ b/src/main/java/com/dfsek/terra/config/genconfig/biome/BiomeSnowConfig.java @@ -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> 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; + } +} diff --git a/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java b/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java index c63d85cc9..c108d2a3d 100644 --- a/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java +++ b/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java @@ -102,18 +102,23 @@ public class TerraChunkGenerator extends GaeaChunkGenerator { private void prepareBlockPart(BlockData down, BlockData orig, ChunkData chunk, Vector block, Map> slabs, Map> stairs, double thresh) { double _11 = getInterpolatedNoise(block.getBlockX(), block.getBlockY() - 0.4, block.getBlockZ()); 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) { Palette stairPalette = stairs.get(down.getMaterial()); if(stairPalette != null) { BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ()); - Stairs finalStair = getStair(new double[] {_01, _10, _12, _21}, (Stairs) stair, thresh); - if(finalStair != null) { - if(orig.matches(DataUtil.WATER)) finalStair.setWaterlogged(true); - chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), finalStair); + Stairs stairNew = (Stairs) stair.clone(); + if(getInterpolatedNoise(block.getBlockX() - 0.5, block.getBlockY(), block.getBlockZ()) > thresh) { + stairNew.setFacing(BlockFace.WEST); + } 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; } } @@ -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) { try { popMan.loadBlocks(w); diff --git a/src/main/java/com/dfsek/terra/population/SnowPopulator.java b/src/main/java/com/dfsek/terra/population/SnowPopulator.java index d1a916009..d9726c2d9 100644 --- a/src/main/java/com/dfsek/terra/population/SnowPopulator.java +++ b/src/main/java/com/dfsek/terra/population/SnowPopulator.java @@ -50,13 +50,13 @@ public class SnowPopulator extends GaeaBlockPopulator { TerraBiomeGrid g = w.getGrid(); for(int x = 0; x < 16; x++) { 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; Block b = null; for(y = 254; y > 0; y--) { b = chunk.getBlock(x, y, z); 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; chunk.getBlock(x, ++y, z).setBlockData(DataUtil.SNOW); } diff --git a/src/main/java/com/dfsek/terra/structure/Structure.java b/src/main/java/com/dfsek/terra/structure/Structure.java index 2082dab66..29a41443d 100644 --- a/src/main/java/com/dfsek/terra/structure/Structure.java +++ b/src/main/java/com/dfsek/terra/structure/Structure.java @@ -2,6 +2,7 @@ package com.dfsek.terra.structure; import com.dfsek.terra.Debug; import com.dfsek.terra.procgen.math.Vector2; +import com.dfsek.terra.util.structure.RotationUtil; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -31,8 +32,10 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.UUID; import java.util.function.Consumer; @@ -188,9 +191,13 @@ public class Structure implements Serializable { org.bukkit.Axis newAxis = getRotatedAxis(((Orientable) data).getAxis(), r); ((Orientable) data).setAxis(newAxis); } else if(data instanceof RedstoneWire) { + Map connections = new HashMap<>(); RedstoneWire rData = (RedstoneWire) data; for(BlockFace f : rData.getAllowedFaces()) { - rData.setFace(getRotatedFace(f, r), rData.getFace(f)); + connections.put(f, rData.getFace(f)); + } + for(Map.Entry e : connections.entrySet()) { + rData.setFace(RotationUtil.getRotatedFace(e.getKey(), r), e.getValue()); } } worldBlock.setBlockData(data, false);