diff --git a/src/main/java/com/dfsek/terra/config/base/ConfigPack.java b/src/main/java/com/dfsek/terra/config/base/ConfigPack.java index 91a6eb680..a3bcb3b3e 100644 --- a/src/main/java/com/dfsek/terra/config/base/ConfigPack.java +++ b/src/main/java/com/dfsek/terra/config/base/ConfigPack.java @@ -28,6 +28,7 @@ import com.dfsek.terra.registry.StructureRegistry; import com.dfsek.terra.util.ConfigUtil; import org.polydev.gaea.biome.Biome; import org.polydev.gaea.world.palette.Palette; +import parsii.eval.Scope; import java.io.File; import java.io.FileInputStream; @@ -35,6 +36,7 @@ import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.logging.Level; @@ -49,6 +51,8 @@ public class ConfigPack { private final CarverRegistry carverRegistry = new CarverRegistry(); private final PaletteRegistry paletteRegistry = new PaletteRegistry(); + private final Scope varScope; + public ConfigPack(File folder) throws ConfigException { long l = System.nanoTime(); @@ -63,6 +67,11 @@ public class ConfigPack { throw new FileMissingException("No pack.yml file found in " + folder.getAbsolutePath(), e); } + varScope = new Scope(); + + for(Map.Entry var : template.getVariables().entrySet()) { + varScope.create(var.getKey()).setValue(var.getValue()); + } AbstractConfigLoader abstractConfigLoader = new AbstractConfigLoader(); abstractConfigLoader @@ -91,7 +100,7 @@ public class ConfigPack { }); List biomeTemplates = abstractConfigLoader.load(ConfigUtil.loadFromPath(new File(folder, "biomes").toPath()), () -> new BiomeTemplate(this)); - BiomeFactory biomeFactory = new BiomeFactory(); + BiomeFactory biomeFactory = new BiomeFactory(this); biomeTemplates.forEach(biome -> { biomeRegistry.add(biome.getID(), biomeFactory.build(biome)); Debug.info("Loaded biome " + biome.getID()); @@ -146,4 +155,8 @@ public class ConfigPack { public ConfigPackTemplate getTemplate() { return template; } + + public Scope getVarScope() { + return varScope; + } } diff --git a/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java b/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java index cbeb19f3a..b84443d07 100644 --- a/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java +++ b/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java @@ -1,12 +1,19 @@ package com.dfsek.terra.config.factories; import com.dfsek.terra.biome.UserDefinedBiome; +import com.dfsek.terra.config.base.ConfigPack; import com.dfsek.terra.config.builder.GeneratorBuilder; import com.dfsek.terra.config.templates.BiomeTemplate; import com.dfsek.terra.generation.UserDefinedDecorator; import org.polydev.gaea.math.ProbabilityCollection; public class BiomeFactory implements TerraFactory { + private final ConfigPack pack; + + public BiomeFactory(ConfigPack pack) { + this.pack = pack; + } + @Override public UserDefinedBiome build(BiomeTemplate template) { UserDefinedDecorator decorator = new UserDefinedDecorator(new ProbabilityCollection<>(), new ProbabilityCollection<>(), 0, 0); @@ -16,6 +23,7 @@ public class BiomeFactory implements TerraFactory floraPalette; + private PaletteHolder floraPalette; @Value("physics") @Abstractable @@ -51,7 +51,7 @@ public class FloraTemplate implements ConfigTemplate { return id; } - public Palette getFloraPalette() { + public PaletteHolder getFloraPalette() { return floraPalette; } diff --git a/src/main/java/com/dfsek/terra/generation/items/TerraFlora.java b/src/main/java/com/dfsek/terra/generation/items/TerraFlora.java index 295ea18ce..b77b3313e 100644 --- a/src/main/java/com/dfsek/terra/generation/items/TerraFlora.java +++ b/src/main/java/com/dfsek/terra/generation/items/TerraFlora.java @@ -1,21 +1,80 @@ package com.dfsek.terra.generation.items; +import net.jafama.FastMath; import org.bukkit.Chunk; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.BlockData; import org.polydev.gaea.math.Range; import org.polydev.gaea.world.Flora; +import org.polydev.gaea.world.palette.Palette; +import java.util.ArrayList; import java.util.List; +import java.util.Set; public class TerraFlora implements Flora { - @Override - public List getValidSpawnsAt(Chunk chunk, int i, int i1, Range range) { - return null; + private final Palette floraPalette; + private final boolean physics; + private final boolean ceiling; + + private final Set irrigable; + + private final Set spawnable; + private final Set replaceable; + + public TerraFlora(Palette floraPalette, boolean physics, boolean ceiling, Set irrigable, Set spawnable, Set replaceable) { + this.floraPalette = floraPalette; + this.physics = physics; + this.ceiling = ceiling; + this.irrigable = irrigable; + this.spawnable = spawnable; + this.replaceable = replaceable; } + @Override + public List getValidSpawnsAt(Chunk chunk, int x, int z, Range range) { + int size = floraPalette.getSize(); + Block current = chunk.getBlock(x, range.getMin(), z); + List blocks = new ArrayList<>(); + for(int y : range) { + if(y > 255 || y < 0) continue; + current = current.getRelative(BlockFace.UP); + if(spawnable.contains(current.getType()) && isIrrigated(current) && valid(size, current)) { + blocks.add(current); + } + } + return blocks; + } + + private boolean valid(int size, Block block) { + for(int i = 0; i < size; i++) { // Down if ceiling, up if floor + if(block.getY() + 1 > 255 || block.getY() < 0) return false; + block = block.getRelative(ceiling ? BlockFace.DOWN : BlockFace.UP); + if(!replaceable.contains(block.getType())) return false; + } + return true; + } + + private boolean isIrrigated(Block b) { + if(irrigable == null) return true; + return irrigable.contains(b.getRelative(BlockFace.NORTH).getType()) + || irrigable.contains(b.getRelative(BlockFace.SOUTH).getType()) + || irrigable.contains(b.getRelative(BlockFace.EAST).getType()) + || irrigable.contains(b.getRelative(BlockFace.WEST).getType()); + } + + @Override public boolean plant(Location location) { - return false; + int size = floraPalette.getSize(); + int c = ceiling ? -1 : 1; + for(int i = 0; FastMath.abs(i) < size; i += c) { // Down if ceiling, up if floor + int lvl = (FastMath.abs(i)); + location.clone().add(0, i + c, 0).getBlock().setBlockData(floraPalette.get((ceiling ? lvl : size - lvl - 1), location.getBlockX(), location.getBlockZ()), physics); + } + return true; } } diff --git a/src/main/java/com/dfsek/terra/generation/items/TerraTree.java b/src/main/java/com/dfsek/terra/generation/items/TerraTree.java index aeff63bcf..fa2dc7874 100644 --- a/src/main/java/com/dfsek/terra/generation/items/TerraTree.java +++ b/src/main/java/com/dfsek/terra/generation/items/TerraTree.java @@ -1,14 +1,66 @@ package com.dfsek.terra.generation.items; +import com.dfsek.terra.procgen.math.Vector2; +import com.dfsek.terra.structure.Rotation; +import com.dfsek.terra.structure.Structure; +import com.dfsek.terra.structure.StructureContainedBlock; +import com.dfsek.terra.structure.StructureInfo; +import com.dfsek.terra.util.structure.RotationUtil; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.plugin.java.JavaPlugin; +import org.polydev.gaea.math.ProbabilityCollection; import org.polydev.gaea.tree.Tree; import java.util.Random; +import java.util.Set; public class TerraTree implements Tree { + private final Set spawnable; + private final String id; + private final int yOffset; + private final ProbabilityCollection structure; + + public TerraTree(Set spawnable, String id, int yOffset, ProbabilityCollection structure) { + this.spawnable = spawnable; + this.id = id; + this.yOffset = yOffset; + this.structure = structure; + } + @Override public boolean plant(Location location, Random random, JavaPlugin javaPlugin) { - return false; + location.subtract(0, 1, 0); + Location mut = location.clone().subtract(0, yOffset, 0); + if(!spawnable.contains(location.getBlock().getType())) return false; + Structure struc = structure.get(random); + Rotation rotation = Rotation.fromDegrees(random.nextInt(4) * 90); + if(!struc.checkSpawns(mut, rotation)) return false; + struc.paste(mut, rotation); + return true; + } + + public boolean plantBlockCheck(Location location, Random random) { + location.subtract(0, 1, 0); + Location mut = location.clone().subtract(0, yOffset, 0); + if(!spawnable.contains(location.getBlock().getType())) return false; + Structure struc = structure.get(random); + Rotation rotation = Rotation.fromDegrees(random.nextInt(4) * 90); + StructureInfo info = struc.getStructureInfo(); + for(StructureContainedBlock spawn : struc.getSpawns()) { + Vector2 rot = RotationUtil.getRotatedCoords(new Vector2(spawn.getX() - info.getCenterX(), spawn.getZ() - info.getCenterZ()), rotation); + int x = (int) rot.getX(); + int z = (int) rot.getZ(); + switch(spawn.getRequirement()) { + case AIR: + if(!mut.clone().add(x, spawn.getY() - 1, z).getBlock().isPassable()) return false; + break; + case LAND: + if(!mut.clone().add(x, spawn.getY() - 1, z).getBlock().getType().isSolid()) return false; + break; + } + } + struc.paste(mut, rotation); + return true; } } diff --git a/src/main/java/com/dfsek/terra/registry/TerraRegistry.java b/src/main/java/com/dfsek/terra/registry/TerraRegistry.java index 385a388d1..be7c0b3cd 100644 --- a/src/main/java/com/dfsek/terra/registry/TerraRegistry.java +++ b/src/main/java/com/dfsek/terra/registry/TerraRegistry.java @@ -1,5 +1,6 @@ package com.dfsek.terra.registry; +import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; @@ -14,8 +15,11 @@ public abstract class TerraRegistry implements TypeLoader { private final Map objects = new HashMap<>(); @Override - public T load(Type type, Object o, ConfigLoader configLoader) { - return get((String) o); + public T load(Type type, Object o, ConfigLoader configLoader) throws LoadException { + T obj = get((String) o); + if(obj == null) + throw new LoadException("No such " + type + " matching \"" + o + "\" was found in this registry."); + return obj; } /**