mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-02-16 10:30:42 +00:00
Dump Gaea into Terra.
This commit is contained in:
@@ -18,6 +18,7 @@ repositories {
|
||||
maven { url = uri("http://maven.enginehub.org/repo/") }
|
||||
maven { url = uri("https://repo.codemc.org/repository/maven-public") }
|
||||
maven { url = uri("https://papermc.io/repo/repository/maven-public/") }
|
||||
maven { url = uri("https://repo.aikar.co/content/groups/aikar/") }
|
||||
}
|
||||
|
||||
java {
|
||||
@@ -30,9 +31,9 @@ val versionObj = Version("2", "2", "0", true)
|
||||
version = versionObj
|
||||
|
||||
dependencies {
|
||||
val gaeaVersion = "1.15.0"
|
||||
compileOnly("org.polydev.gaea:Gaea:${gaeaVersion}")
|
||||
testImplementation("org.polydev.gaea:Gaea:${gaeaVersion}")
|
||||
implementation("org.apache.commons:commons-rng-core:1.3")
|
||||
implementation("net.jafama:jafama:2.3.2")
|
||||
implementation("co.aikar:taskchain-bukkit:3.7.2")
|
||||
|
||||
compileOnly("org.jetbrains:annotations:20.1.0")
|
||||
|
||||
@@ -100,6 +101,8 @@ tasks.named<ShadowJar>("shadowJar") {
|
||||
relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib")
|
||||
relocate("net.jafama", "com.dfsek.terra.lib.jafama")
|
||||
relocate("com.dfsek.tectonic", "com.dfsek.terra.lib.tectonic")
|
||||
relocate("net.jafama", "com.dfsek.terra.lib.jafama")
|
||||
relocate("co.aikar.taskchain", "com.dfsek.terra.lib.taskchain")
|
||||
minimize()
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,11 @@ package com.dfsek.terra;
|
||||
|
||||
import com.dfsek.tectonic.loading.TypeRegistry;
|
||||
import com.dfsek.terra.api.bukkit.BukkitWorldHandle;
|
||||
import com.dfsek.terra.api.gaea.GaeaPlugin;
|
||||
import com.dfsek.terra.api.gaea.generation.GaeaChunkGenerator;
|
||||
import com.dfsek.terra.api.gaea.lang.Language;
|
||||
import com.dfsek.terra.api.gaea.math.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.gaea.math.Range;
|
||||
import com.dfsek.terra.api.generic.TerraPlugin;
|
||||
import com.dfsek.terra.api.generic.world.WorldHandle;
|
||||
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
|
||||
@@ -56,11 +61,6 @@ import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.polydev.gaea.GaeaPlugin;
|
||||
import org.polydev.gaea.generation.GaeaChunkGenerator;
|
||||
import org.polydev.gaea.lang.Language;
|
||||
import org.polydev.gaea.math.ProbabilityCollection;
|
||||
import org.polydev.gaea.math.Range;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.dfsek.terra;
|
||||
|
||||
import com.dfsek.terra.api.gaea.profiler.DataType;
|
||||
import com.dfsek.terra.api.gaea.profiler.Measurement;
|
||||
import com.dfsek.terra.api.gaea.profiler.WorldProfiler;
|
||||
import org.bukkit.World;
|
||||
import org.polydev.gaea.profiler.DataType;
|
||||
import org.polydev.gaea.profiler.Measurement;
|
||||
import org.polydev.gaea.profiler.WorldProfiler;
|
||||
|
||||
public class TerraProfiler extends WorldProfiler {
|
||||
public TerraProfiler(World w) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.dfsek.terra;
|
||||
|
||||
import com.dfsek.terra.api.gaea.biome.BiomeGrid;
|
||||
import com.dfsek.terra.biome.BiomeZone;
|
||||
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
|
||||
import com.dfsek.terra.biome.grid.master.TerraRadialBiomeGrid;
|
||||
@@ -11,7 +12,6 @@ import com.dfsek.terra.debug.Debug;
|
||||
import com.dfsek.terra.generation.TerraChunkGenerator;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.polydev.gaea.biome.BiomeGrid;
|
||||
|
||||
public class TerraWorld {
|
||||
private final TerraBiomeGrid grid;
|
||||
|
||||
26
src/main/java/com/dfsek/terra/api/gaea/Debug.java
Normal file
26
src/main/java/com/dfsek/terra/api/gaea/Debug.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package com.dfsek.terra.api.gaea;
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class Debug {
|
||||
public static JavaPlugin main;
|
||||
|
||||
public static void setMain(JavaPlugin main) {
|
||||
Debug.main = main;
|
||||
}
|
||||
|
||||
public static void info(String message) {
|
||||
if(Gaea.isDebug()) main.getLogger().info(message);
|
||||
}
|
||||
public static void warn(String message) {
|
||||
if(Gaea.isDebug()) main.getLogger().warning(message);
|
||||
}
|
||||
|
||||
public static void error(String message) {
|
||||
if(Gaea.isDebug()) main.getLogger().severe(message);
|
||||
}
|
||||
|
||||
public static void stack(Exception e) {
|
||||
if(Gaea.isDebug()) e.printStackTrace();
|
||||
}
|
||||
}
|
||||
19
src/main/java/com/dfsek/terra/api/gaea/Gaea.java
Normal file
19
src/main/java/com/dfsek/terra/api/gaea/Gaea.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.dfsek.terra.api.gaea;
|
||||
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class Gaea {
|
||||
private static boolean debug;
|
||||
|
||||
public static File getGaeaFolder(World w) {
|
||||
File f = new File(w.getWorldFolder(), "gaea");
|
||||
f.mkdirs();
|
||||
return f;
|
||||
}
|
||||
|
||||
public static boolean isDebug() {
|
||||
return debug;
|
||||
}
|
||||
}
|
||||
11
src/main/java/com/dfsek/terra/api/gaea/GaeaPlugin.java
Normal file
11
src/main/java/com/dfsek/terra/api/gaea/GaeaPlugin.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package com.dfsek.terra.api.gaea;
|
||||
|
||||
import com.dfsek.terra.api.gaea.generation.GaeaChunkGenerator;
|
||||
import com.dfsek.terra.api.gaea.lang.Language;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public abstract class GaeaPlugin extends JavaPlugin {
|
||||
public abstract boolean isDebug();
|
||||
public abstract Class<? extends GaeaChunkGenerator> getGeneratorClass();
|
||||
public abstract Language getLanguage();
|
||||
}
|
||||
40
src/main/java/com/dfsek/terra/api/gaea/biome/Biome.java
Normal file
40
src/main/java/com/dfsek/terra/api/gaea/biome/Biome.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package com.dfsek.terra.api.gaea.biome;
|
||||
|
||||
import org.bukkit.World;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by a custom generator's Biome enum.<br>
|
||||
* Represents a custom biome, and contains methods to retrieve information about each type.
|
||||
*/
|
||||
public interface Biome {
|
||||
|
||||
/**
|
||||
* Gets the Vanilla biome to represent the custom biome.
|
||||
*
|
||||
* @return Biome - The Vanilla biome.
|
||||
*/
|
||||
org.bukkit.block.Biome getVanillaBiome();
|
||||
|
||||
/**
|
||||
* Gets the BiomeTerrain instance used to generate the biome.
|
||||
*
|
||||
* @return BiomeTerrain - The terrain generation instance.
|
||||
*/
|
||||
Generator getGenerator();
|
||||
|
||||
/**
|
||||
* Returns the Decorator instance containing information about the population in the biome.
|
||||
*
|
||||
* @return Decorator - the Decorator instance.
|
||||
*/
|
||||
Decorator getDecorator();
|
||||
|
||||
/**
|
||||
* Gets the BiomeTerrain instance used to generate the biome in this world.
|
||||
*
|
||||
* @return BiomeTerrain - The terrain generation instance.
|
||||
*/
|
||||
default Generator getGenerator(World w) {
|
||||
return getGenerator();
|
||||
}
|
||||
}
|
||||
121
src/main/java/com/dfsek/terra/api/gaea/biome/BiomeGrid.java
Normal file
121
src/main/java/com/dfsek/terra/api/gaea/biome/BiomeGrid.java
Normal file
@@ -0,0 +1,121 @@
|
||||
package com.dfsek.terra.api.gaea.biome;
|
||||
|
||||
import com.dfsek.terra.api.gaea.generation.GenerationPhase;
|
||||
import com.dfsek.terra.api.gaea.math.FastNoiseLite;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
public abstract class BiomeGrid {
|
||||
private final FastNoiseLite noiseX;
|
||||
private final FastNoiseLite noiseZ;
|
||||
private final World world;
|
||||
private final int sizeX;
|
||||
private final int sizeZ;
|
||||
private Biome[][] grid;
|
||||
|
||||
|
||||
public BiomeGrid(World w, double freq1, double freq2, int sizeX, int sizeZ) {
|
||||
this.sizeX = sizeX;
|
||||
this.sizeZ = sizeZ;
|
||||
this.world = w;
|
||||
this.noiseX = new FastNoiseLite((int) w.getSeed());
|
||||
this.noiseZ = new FastNoiseLite((int) w.getSeed() + 1);
|
||||
this.noiseX.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
|
||||
this.noiseX.setFractalType(FastNoiseLite.FractalType.FBm);
|
||||
this.noiseX.setFractalOctaves(4);
|
||||
this.noiseZ.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
|
||||
this.noiseZ.setFractalType(FastNoiseLite.FractalType.FBm);
|
||||
this.noiseZ.setFractalOctaves(4);
|
||||
this.noiseX.setFrequency(freq1);
|
||||
this.noiseZ.setFrequency(freq2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the biome at a pair of coordinates.
|
||||
*
|
||||
* @param x - X-coordinate at which to fetch biome
|
||||
* @param z - Z-coordinate at which to fetch biome
|
||||
* @return Biome - Biome at the given coordinates.
|
||||
*/
|
||||
public Biome getBiome(int x, int z, GenerationPhase phase) {
|
||||
return grid[getBiomeNoiseX(x, z)][getBiomeNoiseZ(x, z)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the biome at a location.
|
||||
*
|
||||
* @param l - The location at which to fetch the biome.
|
||||
* @return Biome - Biome at the given coordinates.
|
||||
*/
|
||||
public Biome getBiome(Location l) {
|
||||
return getBiome(l, GenerationPhase.POST_GEN);
|
||||
}
|
||||
|
||||
public double[] getRawNoise(int x, int z) {
|
||||
return new double[] {noiseX.getNoise(x, z), noiseZ.getNoise(x, z)};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw X-noise for coordinates in the Grid.
|
||||
*
|
||||
* @param x X coordinate
|
||||
* @param z Z coordinate
|
||||
* @return Normalized noise
|
||||
*/
|
||||
public int getBiomeNoiseX(int x, int z) {
|
||||
return normalize(noiseX.getNoise(x, z), sizeX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw Z-noise for coordinates in the Grid.
|
||||
*
|
||||
* @param x X coordinate
|
||||
* @param z Z coordinate
|
||||
* @return Normalized noise
|
||||
*/
|
||||
public int getBiomeNoiseZ(int x, int z) {
|
||||
return normalize(noiseZ.getNoise(x, z), sizeZ);
|
||||
}
|
||||
|
||||
public Biome[][] getGrid() {
|
||||
return grid;
|
||||
}
|
||||
|
||||
public void setGrid(Biome[][] grid) {
|
||||
if(grid.length != sizeX) throw new IllegalArgumentException("Invalid length for grid, expected " + sizeX + ", got " + grid.length);
|
||||
for(Biome[] gridLayer : grid) {
|
||||
if(gridLayer.length != sizeZ) throw new IllegalArgumentException("Invalid length for grid layer, expected " + sizeZ + ", got " + gridLayer.length);
|
||||
}
|
||||
this.grid = grid;
|
||||
}
|
||||
|
||||
public Biome getBiome(Location l, GenerationPhase phase) {
|
||||
double biomeNoise = noiseX.getNoise(l.getBlockX(), l.getBlockZ());
|
||||
double climateNoise = noiseZ.getNoise(l.getBlockX(), l.getBlockZ());
|
||||
return grid[normalize(biomeNoise, sizeX)][normalize(climateNoise, sizeZ)];
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public int getSizeX() {
|
||||
return sizeX;
|
||||
}
|
||||
|
||||
public int getSizeZ() {
|
||||
return sizeZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a noise input and normalizes it to a value between 0 and 15 inclusive.
|
||||
*
|
||||
* @param i - The noise value to normalize.
|
||||
* @return int - The normalized value.
|
||||
*/
|
||||
protected int normalize(double i, int range) {
|
||||
return NormalizationUtil.normalize(i, range, 4);
|
||||
}
|
||||
|
||||
}
|
||||
22
src/main/java/com/dfsek/terra/api/gaea/biome/Decorator.java
Normal file
22
src/main/java/com/dfsek/terra/api/gaea/biome/Decorator.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.dfsek.terra.api.gaea.biome;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.gaea.tree.Tree;
|
||||
import com.dfsek.terra.api.gaea.world.Flora;
|
||||
|
||||
public abstract class Decorator {
|
||||
|
||||
|
||||
public abstract ProbabilityCollection<Tree> getTrees();
|
||||
|
||||
public abstract int getTreeDensity();
|
||||
|
||||
public abstract boolean overrideStructureChance();
|
||||
|
||||
public abstract org.bukkit.block.Biome getVanillaBiome();
|
||||
|
||||
public abstract ProbabilityCollection<Flora> getFlora();
|
||||
|
||||
public abstract int getFloraChance();
|
||||
|
||||
}
|
||||
52
src/main/java/com/dfsek/terra/api/gaea/biome/Generator.java
Normal file
52
src/main/java/com/dfsek/terra/api/gaea/biome/Generator.java
Normal file
@@ -0,0 +1,52 @@
|
||||
package com.dfsek.terra.api.gaea.biome;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.FastNoiseLite;
|
||||
import com.dfsek.terra.api.gaea.math.Interpolator;
|
||||
import com.dfsek.terra.api.gaea.world.palette.Palette;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
public abstract class Generator {
|
||||
/**
|
||||
* Gets the 2D noise at a pair of coordinates using the provided FastNoiseLite instance.
|
||||
*
|
||||
* @param gen - The FastNoiseLite instance to use.
|
||||
* @param x - The x coordinate.
|
||||
* @param z - The z coordinate.
|
||||
* @return double - Noise value at the specified coordinates.
|
||||
*/
|
||||
public abstract double getNoise(FastNoiseLite gen, World w, int x, int z);
|
||||
|
||||
/**
|
||||
* Gets the 3D noise at a pair of coordinates using the provided FastNoiseLite instance.
|
||||
*
|
||||
* @param gen - The FastNoiseLite instance to use.
|
||||
* @param x - The x coordinate.
|
||||
* @param y - The y coordinate.
|
||||
* @param z - The z coordinate.
|
||||
* @return double - Noise value at the specified coordinates.
|
||||
*/
|
||||
public abstract double getNoise(FastNoiseLite gen, World w, int x, int y, int z);
|
||||
|
||||
/**
|
||||
* Gets the BlocPalette to generate the biome with.
|
||||
*
|
||||
* @return BlocPalette - The biome's palette.
|
||||
*/
|
||||
public abstract Palette<BlockData> getPalette(int y);
|
||||
|
||||
/**
|
||||
* Returns true if the biome should be interpolated just once, false to use advanced interpolation + blending.
|
||||
* @return Whether biome should use minimal interpolation
|
||||
*/
|
||||
public abstract boolean useMinimalInterpolation();
|
||||
|
||||
|
||||
/**
|
||||
* Get the type of interpolation to use in this biome.
|
||||
* @return Interpolation type
|
||||
*/
|
||||
public Interpolator.Type getInterpolationType() {
|
||||
return Interpolator.Type.LINEAR;
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
111
src/main/java/com/dfsek/terra/api/gaea/command/Command.java
Normal file
111
src/main/java/com/dfsek/terra/api/gaea/command/Command.java
Normal file
@@ -0,0 +1,111 @@
|
||||
package com.dfsek.terra.api.gaea.command;
|
||||
|
||||
import com.dfsek.terra.api.gaea.GaeaPlugin;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a command or subcommand, can be nested via getSubCommands.
|
||||
*/
|
||||
public abstract class Command implements CommandExecutor, TabCompleter {
|
||||
private final GaeaPlugin main;
|
||||
public Command(GaeaPlugin main) {
|
||||
this.main = main;
|
||||
}
|
||||
public Command(com.dfsek.terra.api.gaea.command.Command parent) {
|
||||
main = parent.getMain();
|
||||
}
|
||||
|
||||
public GaeaPlugin getMain() {
|
||||
return main;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the command/subcommand
|
||||
* @return Name of command
|
||||
*/
|
||||
public abstract String getName();
|
||||
|
||||
/**
|
||||
* Gets a list of subcommands
|
||||
* @return List of subcommands
|
||||
*/
|
||||
public abstract List<com.dfsek.terra.api.gaea.command.Command> getSubCommands();
|
||||
|
||||
/**
|
||||
* Executes the given command, returning its success.
|
||||
* <br>
|
||||
* If false is returned, then the "usage" plugin.yml entry for this command
|
||||
* (if defined) will be sent to the player.
|
||||
*
|
||||
* @param sender Source of the command
|
||||
* @param command Command which was executed
|
||||
* @param label Alias of the command which was used
|
||||
* @param args Passed command arguments
|
||||
* @return true if a valid command, otherwise false
|
||||
*/
|
||||
|
||||
public abstract boolean execute(@NotNull CommandSender sender, @NotNull org.bukkit.command.Command command, @NotNull String label, @NotNull String[] args);
|
||||
/**
|
||||
* Gets the number of arguments
|
||||
* @return Number of arguments
|
||||
*/
|
||||
public abstract int arguments();
|
||||
|
||||
/**
|
||||
* Executes the given command, invoking subcommands if applicable and returning its success.
|
||||
* <br>
|
||||
* If false is returned, then the "usage" plugin.yml entry for this command
|
||||
* (if defined) will be sent to the player.
|
||||
*
|
||||
* @param sender Source of the command
|
||||
* @param command Command which was executed
|
||||
* @param label Alias of the command which was used
|
||||
* @param args Passed command arguments
|
||||
* @return true if a valid command, otherwise false
|
||||
*/
|
||||
@Override
|
||||
public final boolean onCommand(@NotNull CommandSender sender, @NotNull org.bukkit.command.Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if(this instanceof DebugCommand && ! main.isDebug()) {
|
||||
main.getLanguage().send("command.debug-only", sender);
|
||||
return true;
|
||||
}
|
||||
if(args.length > 0) {
|
||||
for(com.dfsek.terra.api.gaea.command.Command c : getSubCommands()) {
|
||||
if(c.getName().equals(args[0])) {
|
||||
return c.onCommand(sender, command, label, Arrays.stream(args, 1, args.length).toArray(String[]::new));
|
||||
}
|
||||
}
|
||||
if(args.length != arguments()) {
|
||||
main.getLanguage().send("command.invalid", sender, String.valueOf(arguments()), String.valueOf(args.length));
|
||||
return true;
|
||||
}
|
||||
return execute(sender, command, label, args);
|
||||
}
|
||||
if(args.length != arguments()) {
|
||||
main.getLanguage().send("command.invalid", sender, String.valueOf(arguments()), String.valueOf(args.length));
|
||||
return true;
|
||||
}
|
||||
return execute(sender, command, label, new String[] {});
|
||||
}
|
||||
|
||||
public abstract List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args);
|
||||
|
||||
@Override
|
||||
public final @Nullable List<String> onTabComplete(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String alias, @NotNull String[] args) {
|
||||
List<String> complete = new ArrayList<>();
|
||||
if(args.length > 0) for(com.dfsek.terra.api.gaea.command.Command c : getSubCommands()) {
|
||||
if(c.getName().startsWith(args[0])) complete.add(c.getName());
|
||||
if(c.getName().equals(args[0])) return c.onTabComplete(sender, command, alias, Arrays.stream(args, 1, args.length).toArray(String[]::new));
|
||||
}
|
||||
complete.addAll(getTabCompletions(sender, alias, args));
|
||||
return complete;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.dfsek.terra.api.gaea.command;
|
||||
|
||||
/**
|
||||
* Implementing this interface marks a command as debug-only.
|
||||
* If a parent command implements this interface, all child commands will be considered debug commands, regardless of whether they implement DebugCommand as well.
|
||||
*/
|
||||
public interface DebugCommand {
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.dfsek.terra.api.gaea.command;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A command that may only be executed by a player. If executor is not a player, a message will be displayed and no action will be performed.
|
||||
*/
|
||||
public abstract class PlayerCommand extends Command {
|
||||
public PlayerCommand(Command parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given command, returning its success.
|
||||
* <br>
|
||||
* If false is returned, then the "usage" plugin.yml entry for this command
|
||||
* (if defined) will be sent to the player.
|
||||
*
|
||||
* @param sender Source of the command
|
||||
* @param command Command which was executed
|
||||
* @param label Alias of the command which was used
|
||||
* @param args Passed command arguments
|
||||
* @return true if a valid command, otherwise false
|
||||
*/
|
||||
@Override
|
||||
public final boolean execute(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if(!(sender instanceof Player)) {
|
||||
getMain().getLanguage().send("command.players-only", sender);
|
||||
return true;
|
||||
}
|
||||
Player p = (Player) sender;
|
||||
return execute(p, command, label, args);
|
||||
}
|
||||
/**
|
||||
* Executes the given command, returning its success.
|
||||
* <br>
|
||||
* If false is returned, then the "usage" plugin.yml entry for this command
|
||||
* (if defined) will be sent to the player.
|
||||
*
|
||||
* @param sender Player that executed command
|
||||
* @param command Command which was executed
|
||||
* @param label Alias of the command which was used
|
||||
* @param args Passed command arguments
|
||||
* @return true if a valid command, otherwise false
|
||||
*/
|
||||
public abstract boolean execute(@NotNull Player sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.dfsek.terra.api.gaea.command;
|
||||
|
||||
import com.dfsek.terra.api.gaea.generation.GaeaChunkGenerator;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A command that must be executed by a player, in a Terra world.
|
||||
*/
|
||||
public abstract class WorldCommand extends PlayerCommand {
|
||||
public WorldCommand(com.dfsek.terra.api.gaea.command.Command parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given command, returning its success.
|
||||
* <br>
|
||||
* If false is returned, then the "usage" plugin.yml entry for this command
|
||||
* (if defined) will be sent to the player.
|
||||
*
|
||||
* @param sender Source of the command
|
||||
* @param command Command which was executed
|
||||
* @param label Alias of the command which was used
|
||||
* @param args Passed command arguments
|
||||
* @return true if a valid command, otherwise false
|
||||
*/
|
||||
@Override
|
||||
public final boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
Class<? extends GaeaChunkGenerator> clazz = getMain().getGeneratorClass();
|
||||
if(clazz.isInstance(sender.getWorld().getGenerator())) {
|
||||
return execute(sender, command, label, args, sender.getWorld());
|
||||
} else {
|
||||
getMain().getLanguage().send("command.world", sender);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given command, returning its success.
|
||||
* <br>
|
||||
* If false is returned, then the "usage" plugin.yml entry for this command
|
||||
* (if defined) will be sent to the player.
|
||||
*
|
||||
* @param sender Player that executed command
|
||||
* @param command Command which was executed
|
||||
* @param label Alias of the command which was used
|
||||
* @param args Passed command arguments
|
||||
* @param world World in which command was executed
|
||||
* @return true if a valid command, otherwise false
|
||||
*/
|
||||
public abstract boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world);
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.dfsek.terra.api.gaea.generation;
|
||||
|
||||
import com.dfsek.terra.api.gaea.biome.Biome;
|
||||
import com.dfsek.terra.api.gaea.math.ChunkInterpolator;
|
||||
import com.dfsek.terra.api.gaea.math.FastNoiseLite;
|
||||
import com.dfsek.terra.api.gaea.profiler.ProfileFuture;
|
||||
import com.dfsek.terra.api.gaea.profiler.WorldProfiler;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public abstract class GaeaChunkGenerator extends ChunkGenerator {
|
||||
private final ChunkInterpolator.InterpolationType interpolationType;
|
||||
private FastNoiseLite gen;
|
||||
private WorldProfiler profiler;
|
||||
|
||||
public GaeaChunkGenerator(ChunkInterpolator.InterpolationType type) {
|
||||
interpolationType = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, @NotNull BiomeGrid biome) {
|
||||
try(ProfileFuture ignore = measure("TotalChunkGenTime")) {
|
||||
if(gen == null) {
|
||||
gen = new FastNoiseLite((int) world.getSeed());
|
||||
gen.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
|
||||
gen.setFractalType(FastNoiseLite.FractalType.FBm);
|
||||
gen.setFractalOctaves(getNoiseOctaves(world));
|
||||
gen.setFrequency(getNoiseFrequency(world));
|
||||
}
|
||||
ChunkData chunk;
|
||||
ChunkInterpolator interp;
|
||||
try(ProfileFuture ignored = measure("ChunkBaseGenTime")) {
|
||||
interp = interpolationType.getInstance(world, chunkX, chunkZ, this.getBiomeGrid(world), gen);
|
||||
chunk = generateBase(world, random, chunkX, chunkZ, interp);
|
||||
}
|
||||
try(ProfileFuture ignored = measure("BiomeApplyTime")) {
|
||||
com.dfsek.terra.api.gaea.biome.BiomeGrid grid = getBiomeGrid(world);
|
||||
int xOrig = (chunkX << 4);
|
||||
int zOrig = (chunkZ << 4);
|
||||
for(byte x = 0; x < 4; x++) {
|
||||
for(byte z = 0; z < 4; z++) {
|
||||
int cx = xOrig + (x << 2);
|
||||
int cz = zOrig + (z << 2);
|
||||
Biome b = grid.getBiome(cx, cz, GenerationPhase.PALETTE_APPLY);
|
||||
biome.setBiome(x << 2, z << 2, b.getVanillaBiome());
|
||||
}
|
||||
}
|
||||
}
|
||||
for(GenerationPopulator g : getGenerationPopulators(world)) {
|
||||
g.populate(world, chunk, random, chunkX, chunkZ, interp);
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
|
||||
public void attachProfiler(WorldProfiler p) {
|
||||
this.profiler = p;
|
||||
}
|
||||
|
||||
public WorldProfiler getProfiler() {
|
||||
return profiler;
|
||||
}
|
||||
|
||||
private ProfileFuture measure(String id) {
|
||||
if(profiler != null) return profiler.measure(id);
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract ChunkData generateBase(@NotNull World world, @NotNull Random random, int x, int z, ChunkInterpolator noise);
|
||||
|
||||
public abstract int getNoiseOctaves(World w);
|
||||
|
||||
public abstract double getNoiseFrequency(World w);
|
||||
|
||||
public abstract List<GenerationPopulator> getGenerationPopulators(World w);
|
||||
|
||||
public abstract com.dfsek.terra.api.gaea.biome.BiomeGrid getBiomeGrid(World w);
|
||||
|
||||
public FastNoiseLite getNoiseGenerator() {
|
||||
return gen;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.dfsek.terra.api.gaea.generation;
|
||||
|
||||
/**
|
||||
* The phase of terrain generation. Used for modifying values based on the phase of generation.
|
||||
*/
|
||||
public enum GenerationPhase {
|
||||
BASE, POPULATE, GENERATION_POPULATE, PALETTE_APPLY, POST_GEN
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.dfsek.terra.api.gaea.generation;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.ChunkInterpolator;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public abstract class GenerationPopulator {
|
||||
public abstract void populate(World world, ChunkGenerator.ChunkData chunk, Random r, int chunkX, int chunkZ, ChunkInterpolator interp);
|
||||
}
|
||||
40
src/main/java/com/dfsek/terra/api/gaea/lang/Language.java
Normal file
40
src/main/java/com/dfsek/terra/api/gaea/lang/Language.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package com.dfsek.terra.api.gaea.lang;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class Language extends YamlConfiguration {
|
||||
public Language(File file) throws IOException, InvalidConfigurationException {
|
||||
load(file);
|
||||
}
|
||||
@Override
|
||||
public void load(@NotNull File file) throws IOException, InvalidConfigurationException {
|
||||
super.load(file);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public Message getMessage(String id) {
|
||||
Object m = get(id);
|
||||
Message temp;
|
||||
if(m instanceof List) {
|
||||
temp = new MultiLineMessage((List<String>) m);
|
||||
} else if(m instanceof String) {
|
||||
temp = new SingleLineMessage((String) m);
|
||||
} else return new SingleLineMessage("message:" + id + ":translation_undefined");
|
||||
if(temp.isEmpty()) return new SingleLineMessage("message:" + id + ":translation_undefined");
|
||||
return temp;
|
||||
}
|
||||
public void log(String messageID, Level level, Logger logger, String... args) {
|
||||
getMessage(messageID).log(logger, level, args);
|
||||
}
|
||||
public void send(String messageID, CommandSender sender, String... args) {
|
||||
getMessage(messageID).send(sender, args);
|
||||
}
|
||||
}
|
||||
12
src/main/java/com/dfsek/terra/api/gaea/lang/Message.java
Normal file
12
src/main/java/com/dfsek/terra/api/gaea/lang/Message.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.dfsek.terra.api.gaea.lang;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public interface Message {
|
||||
void log(Logger logger, Level level, String... args);
|
||||
void send(CommandSender sender, String... args);
|
||||
boolean isEmpty();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.dfsek.terra.api.gaea.lang;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class MultiLineMessage implements Message {
|
||||
private final List<String> message;
|
||||
public MultiLineMessage(List<String> message) {
|
||||
this.message = message;
|
||||
}
|
||||
@Override
|
||||
public void log(Logger logger, Level level, String... args) {
|
||||
for(String line: message) {
|
||||
logger.log(level, ChatColor.translateAlternateColorCodes('&', String.format(line, Arrays.asList(args).toArray())));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(CommandSender sender, String... args) {
|
||||
for(String line: message) {
|
||||
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', String.format(line, Arrays.asList(args).toArray())));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return message == null || message.isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.dfsek.terra.api.gaea.lang;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class SingleLineMessage implements Message {
|
||||
private final String message;
|
||||
public SingleLineMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
@Override
|
||||
public void log(Logger logger, Level level, String... args) {
|
||||
logger.log(level, ChatColor.translateAlternateColorCodes('&', String.format(message, Arrays.asList(args).toArray())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(CommandSender sender, String... args) {
|
||||
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', String.format(message, Arrays.asList(args).toArray())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return message == null || message.equals("");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.dfsek.terra.api.gaea.math;
|
||||
|
||||
import com.dfsek.terra.api.gaea.biome.BiomeGrid;
|
||||
import org.bukkit.World;
|
||||
|
||||
public interface ChunkInterpolator {
|
||||
double getNoise(double x, double z);
|
||||
|
||||
double getNoise(double x, double y, double z);
|
||||
|
||||
enum InterpolationType {
|
||||
/**
|
||||
* 2D (Bilinear) interpolation
|
||||
*/
|
||||
BILINEAR {
|
||||
@Override
|
||||
public com.dfsek.terra.api.gaea.math.ChunkInterpolator getInstance(World w, int chunkX, int chunkZ, BiomeGrid grid, FastNoiseLite noise) {
|
||||
return new ChunkInterpolator2(w, chunkX, chunkZ, grid, noise);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 3D (Trilinear) interpolation
|
||||
*/
|
||||
TRILINEAR {
|
||||
@Override
|
||||
public com.dfsek.terra.api.gaea.math.ChunkInterpolator getInstance(World w, int chunkX, int chunkZ, BiomeGrid grid, FastNoiseLite noise) {
|
||||
return new ChunkInterpolator3(w, chunkX, chunkZ, grid, noise);
|
||||
}
|
||||
};
|
||||
public abstract com.dfsek.terra.api.gaea.math.ChunkInterpolator getInstance(World w, int chunkX, int chunkZ, BiomeGrid grid, FastNoiseLite noise);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.dfsek.terra.api.gaea.math;
|
||||
|
||||
import com.dfsek.terra.api.gaea.biome.BiomeGrid;
|
||||
import com.dfsek.terra.api.gaea.biome.Generator;
|
||||
import com.dfsek.terra.api.gaea.generation.GenerationPhase;
|
||||
import org.bukkit.World;
|
||||
|
||||
/**
|
||||
* Class to abstract away the 16 Interpolators needed to generate a chunk.<br>
|
||||
* Contains method to get interpolated noise at a coordinate within the chunk.
|
||||
*/
|
||||
public class ChunkInterpolator2 implements ChunkInterpolator {
|
||||
private final Interpolator[][] interpGrid = new Interpolator[4][4];
|
||||
|
||||
private final int xOrigin;
|
||||
private final int zOrigin;
|
||||
private final FastNoiseLite noise;
|
||||
private final World w;
|
||||
|
||||
/**
|
||||
* Instantiates a ChunkInterpolator at a pair of chunk coordinates, with a BiomeGrid and FastNoiseLite instance.
|
||||
*
|
||||
* @param chunkX X coordinate of the chunk.
|
||||
* @param chunkZ Z coordinate of the chunk.
|
||||
* @param grid BiomeGrid to use for noise fetching.
|
||||
* @param noise FastNoiseLite instance to use.
|
||||
*/
|
||||
public ChunkInterpolator2(World w, int chunkX, int chunkZ, BiomeGrid grid, FastNoiseLite noise) {
|
||||
this.xOrigin = chunkX << 4;
|
||||
this.zOrigin = chunkZ << 4;
|
||||
this.noise = noise;
|
||||
this.w = w;
|
||||
Generator[][] gridTemp = new Generator[8][8];
|
||||
for(int x = - 2; x < 6; x++) {
|
||||
for(int z = - 2; z < 6; z++) {
|
||||
gridTemp[x + 2][z + 2] = grid.getBiome(xOrigin + (x << 2), zOrigin + (z << 2), GenerationPhase.BASE).getGenerator();
|
||||
}
|
||||
}
|
||||
for(byte x = 0; x < 4; x++) {
|
||||
for(byte z = 0; z < 4; z++) {
|
||||
interpGrid[x][z] = new Interpolator(biomeAvg(x, z, gridTemp),
|
||||
biomeAvg(x + 1, z, gridTemp),
|
||||
biomeAvg(x, z + 1, gridTemp),
|
||||
biomeAvg(x + 1, z + 1, gridTemp), gridTemp[x+1][z+1].getInterpolationType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private double biomeAvg(int x, int z, Generator[][] g) {
|
||||
return (g[x + 3][z + 2].getNoise(noise, w, (x << 2) + xOrigin, (z << 2) + zOrigin)
|
||||
+ g[x + 1][z + 2].getNoise(noise, w, (x << 2) + xOrigin, (z << 2) + zOrigin)
|
||||
+ g[x + 2][z + 3].getNoise(noise, w, (x << 2) + xOrigin, (z << 2) + zOrigin)
|
||||
+ g[x + 2][z + 1].getNoise(noise, w, (x << 2) + xOrigin, (z << 2) + zOrigin)) / 4D;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the noise at a pair of internal chunk coordinates.
|
||||
*
|
||||
* @param x The internal X coordinate (0-15).
|
||||
* @param z The internal Z coordinate (0-15).
|
||||
* @return double - The interpolated noise at the coordinates.
|
||||
*/
|
||||
@Override
|
||||
public double getNoise(double x, double z) {
|
||||
return interpGrid[((int) x) / 4][((int) z) / 4].bilerp((x % 4) / 4, (z % 4) / 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoise(double x, double y, double z) {
|
||||
return getNoise(x, z);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.dfsek.terra.api.gaea.math;
|
||||
|
||||
import com.dfsek.terra.api.gaea.biome.BiomeGrid;
|
||||
import com.dfsek.terra.api.gaea.biome.Generator;
|
||||
import com.dfsek.terra.api.gaea.generation.GenerationPhase;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.World;
|
||||
|
||||
/**
|
||||
* Class to abstract away the 16 Interpolators needed to generate a chunk.<br>
|
||||
* Contains method to get interpolated noise at a coordinate within the chunk.
|
||||
*/
|
||||
public class ChunkInterpolator3 implements ChunkInterpolator {
|
||||
private final Interpolator3[][][] interpGrid = new Interpolator3[4][64][4];
|
||||
private final Generator[][] gens = new Generator[7][7];
|
||||
private final boolean[][] needsBiomeInterp = new boolean[5][5];
|
||||
private final double[][][] noiseStorage = new double[7][7][65];
|
||||
private final FastNoiseLite noise;
|
||||
private final int xOrigin;
|
||||
private final int zOrigin;
|
||||
private final World w;
|
||||
|
||||
/**
|
||||
* Instantiates a 3D ChunkInterpolator at a pair of chunk coordinates, with a BiomeGrid and FastNoiseLite instance.
|
||||
*
|
||||
* @param chunkX X coordinate of the chunk.
|
||||
* @param chunkZ Z coordinate of the chunk.
|
||||
* @param grid BiomeGrid to use for noise fetching.
|
||||
* @param noise FastNoiseLite instance to use.
|
||||
*/
|
||||
public ChunkInterpolator3(World w, int chunkX, int chunkZ, BiomeGrid grid, FastNoiseLite noise) {
|
||||
this.xOrigin = chunkX << 4;
|
||||
this.zOrigin = chunkZ << 4;
|
||||
this.noise = noise;
|
||||
this.w = w;
|
||||
|
||||
|
||||
for(int x = - 1; x < 6; x++) {
|
||||
for(int z = - 1; z < 6; z++) {
|
||||
gens[x + 1][z + 1] = grid.getBiome(xOrigin + (x << 2), zOrigin + (z << 2), GenerationPhase.BASE).getGenerator();
|
||||
}
|
||||
}
|
||||
for(int x = 0; x < 5; x++) {
|
||||
for(int z = 0; z < 5; z++) {
|
||||
needsBiomeInterp[x][z] = compareGens(x+1, z+1);
|
||||
}
|
||||
}
|
||||
|
||||
storeNoise();
|
||||
|
||||
for(byte x = 0; x < 4; x++) {
|
||||
for(byte z = 0; z < 4; z++) {
|
||||
for(int y = 0; y < 64; y++) {
|
||||
interpGrid[x][y][z] = new Interpolator3(
|
||||
biomeAvg(x, y, z),
|
||||
biomeAvg(x + 1, y, z),
|
||||
biomeAvg(x, y + 1, z),
|
||||
biomeAvg(x + 1, y + 1, z),
|
||||
biomeAvg(x, y, z + 1),
|
||||
biomeAvg(x + 1, y, z + 1),
|
||||
biomeAvg(x, y + 1, z + 1),
|
||||
biomeAvg(x + 1, y + 1, z + 1), gens[x+1][z+1].getInterpolationType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean compareGens(int x, int z) {
|
||||
Generator comp = gens[x][z];
|
||||
if(!comp.equals(gens[x+1][z])) return true;
|
||||
|
||||
if(!comp.equals(gens[x][z+1])) return true;
|
||||
|
||||
if(!comp.equals(gens[x-1][z])) return true;
|
||||
|
||||
if(!comp.equals(gens[x][z-1])) return true;
|
||||
|
||||
if(!comp.equals(gens[x+1][z+1])) return true;
|
||||
|
||||
if(!comp.equals(gens[x-1][z-1])) return true;
|
||||
|
||||
if(!comp.equals(gens[x+1][z-1])) return true;
|
||||
|
||||
return !comp.equals(gens[x - 1][z + 1]);
|
||||
}
|
||||
private void storeNoise() {
|
||||
for(byte x = - 1; x < 6; x++) {
|
||||
for(byte z = - 1; z < 6; z++) {
|
||||
for(int y = 0; y < 64; y++) {
|
||||
noiseStorage[x + 1][z + 1][y] = gens[x + 1][z + 1].getNoise(noise, w, (x << 2) + xOrigin, y << 2, (z << 2) + zOrigin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private double biomeAvg(int x, int y, int z) {
|
||||
if(needsBiomeInterp[x][z]) return (noiseStorage[x + 2][z + 1][y]
|
||||
+ noiseStorage[x][z + 1][y]
|
||||
+ noiseStorage[x + 1][z + 2][y]
|
||||
+ noiseStorage[x + 1][z][y]
|
||||
+ noiseStorage[x][z][y]
|
||||
+ noiseStorage[x + 2][z + 2][y]
|
||||
+ noiseStorage[x + 2][z][y]
|
||||
+ noiseStorage[x][z + 2][y]
|
||||
+ noiseStorage[x + 1][z + 1][y]
|
||||
) / 9D;
|
||||
else {
|
||||
if(gens[x+1][z+1].useMinimalInterpolation()) return noiseStorage[x+1][z+1][y];
|
||||
else return (noiseStorage[x + 2][z + 1][y]
|
||||
+ noiseStorage[x][z + 1][y]
|
||||
+ noiseStorage[x + 1][z + 2][y]
|
||||
+ noiseStorage[x + 1][z][y]
|
||||
+ noiseStorage[x+1][z+1][y]) / 5D;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoise(double x, double z) {
|
||||
return getNoise(x, 0, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the noise at a pair of internal chunk coordinates.
|
||||
*
|
||||
* @param x The internal X coordinate (0-15).
|
||||
* @param z The internal Z coordinate (0-15).
|
||||
* @return double - The interpolated noise at the coordinates.
|
||||
*/
|
||||
@Override
|
||||
public double getNoise(double x, double y, double z) {
|
||||
return interpGrid[reRange(((int) x) / 4, 3)][reRange(((int) y) / 4, 63)][reRange(((int) z) / 4, 3)].trilerp((x % 4) / 4, (y % 4) / 4, (z % 4) / 4);
|
||||
}
|
||||
|
||||
private static int reRange(int value, int high) {
|
||||
return FastMath.max(FastMath.min(value, high), 0);
|
||||
}
|
||||
}
|
||||
2599
src/main/java/com/dfsek/terra/api/gaea/math/FastNoiseLite.java
Normal file
2599
src/main/java/com/dfsek/terra/api/gaea/math/FastNoiseLite.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
package com.dfsek.terra.api.gaea.math;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
|
||||
/**
|
||||
* Class for bilinear interpolation of values arranged on a unit square.
|
||||
*/
|
||||
public class Interpolator {
|
||||
private final double v0, v1, v2, v3;
|
||||
private final Type type;
|
||||
|
||||
/**
|
||||
* Constructs an interpolator with given values as vertices of a unit square.
|
||||
*
|
||||
* @param v0 - (0,0)
|
||||
* @param v1 - (1,0)
|
||||
* @param v2 - (0,1)
|
||||
* @param v3 - (1,1)
|
||||
*/
|
||||
public Interpolator(double v0, double v1, double v2, double v3, Type type) {
|
||||
this.v0 = v0;
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
this.v3 = v3;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1D Linear interpolation between 2 points 1 unit apart.
|
||||
*
|
||||
* @param t - Distance from v0. Total distance between v0 and v1 is 1 unit.
|
||||
* @param v0 - Value at v0.
|
||||
* @param v1 - Value at v1.
|
||||
* @return double - The interpolated value.
|
||||
*/
|
||||
public static double lerp(double t, double v0, double v1, Type type) {
|
||||
switch(type) {
|
||||
case LINEAR: return v0 + t * (v1 - v0);
|
||||
case NEAREST_NEIGHBOR: return FastMath.abs(v0-t) > FastMath.abs(v1-t) ? v1 : v0;
|
||||
default: throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 2D Bilinear interpolation between 4 points on a unit square.
|
||||
*
|
||||
* @param s - X value
|
||||
* @param t - Z value
|
||||
* @return double - The interpolated value.
|
||||
*/
|
||||
public double bilerp(double s, double t) {
|
||||
double v01 = lerp(s, v0, v1, type);
|
||||
double v23 = lerp(s, v2, v3, type);
|
||||
double v = lerp(t, v01, v23, type);
|
||||
return v;
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
LINEAR, NEAREST_NEIGHBOR
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.dfsek.terra.api.gaea.math;
|
||||
|
||||
/**
|
||||
* Class for bilinear interpolation of values arranged on a unit square.
|
||||
*/
|
||||
public class Interpolator3 {
|
||||
private final double _000, _100, _010, _110, _001, _101, _011, _111;
|
||||
private final Interpolator.Type type;
|
||||
|
||||
/**
|
||||
* Constructs an interpolator with given values as vertices of a unit cube.
|
||||
* * @param _000 The value at <code>(t, u, v) = (0, 0, 0)</code>.
|
||||
* * @param _100 The value at <code>(t, u, v) = (1, 0, 0)</code>.
|
||||
* * @param _010 The value at <code>(t, u, v) = (0, 1, 0)</code>.
|
||||
* * @param _110 The value at <code>(t, u, v) = (1, 1, 0)</code>.
|
||||
* * @param _001 The value at <code>(t, u, v) = (0, 0, 1)</code>.
|
||||
* * @param _101 The value at <code>(t, u, v) = (1, 0, 1)</code>.
|
||||
* * @param _011 The value at <code>(t, u, v) = (0, 1, 1)</code>.
|
||||
* * @param _111 The value at <code>(t, u, v) = (1, 1, 1)</code>.
|
||||
*/
|
||||
public Interpolator3(double _000, double _100,
|
||||
double _010, double _110, double _001, double _101,
|
||||
double _011, double _111, Interpolator.Type type) {
|
||||
this._000 = _000;
|
||||
this._001 = _001;
|
||||
this._010 = _010;
|
||||
this._011 = _011;
|
||||
this._100 = _100;
|
||||
this._101 = _101;
|
||||
this._110 = _110;
|
||||
this._111 = _111;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public double trilerp(double x, double y, double z) {
|
||||
Interpolator top = new Interpolator(_000, _010, _001, _011, type);
|
||||
Interpolator bottom = new Interpolator(_100, _110, _101, _111, type);
|
||||
return Interpolator.lerp(x, top.bilerp(y, z), bottom.bilerp(y, z), type);
|
||||
}
|
||||
}
|
||||
58
src/main/java/com/dfsek/terra/api/gaea/math/MathUtil.java
Normal file
58
src/main/java/com/dfsek/terra/api/gaea/math/MathUtil.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package com.dfsek.terra.api.gaea.math;
|
||||
|
||||
import com.dfsek.terra.api.gaea.util.FastRandom;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Utility class for mathematical functions.
|
||||
*/
|
||||
public class MathUtil {
|
||||
/**
|
||||
* Gets the standard deviation of an array of doubles.
|
||||
*
|
||||
* @param numArray The array of numbers to calculate the standard deviation of.
|
||||
* @return double - The standard deviation.
|
||||
*/
|
||||
public static double standardDeviation(double[] numArray) {
|
||||
double sum = 0.0, standardDeviation = 0.0;
|
||||
int length = numArray.length;
|
||||
|
||||
for(double num : numArray) {
|
||||
sum += num;
|
||||
}
|
||||
|
||||
double mean = sum / length;
|
||||
|
||||
for(double num : numArray) {
|
||||
standardDeviation += FastMath.pow(num - mean, 2);
|
||||
}
|
||||
|
||||
return FastMath.sqrt(standardDeviation / length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the carver seed for a chunk.
|
||||
*
|
||||
* @param chunkX Chunk's X coordinate
|
||||
* @param chunkZ Chunk's Z coordinate
|
||||
* @param seed World seed
|
||||
* @return long - The carver seed.
|
||||
*/
|
||||
public static long getCarverChunkSeed(int chunkX, int chunkZ, long seed) {
|
||||
Random r = new FastRandom(seed);
|
||||
return chunkX * r.nextLong() ^ chunkZ * r.nextLong() ^ seed;
|
||||
}
|
||||
|
||||
public static long hashToLong(String s) {
|
||||
if(s == null) {
|
||||
return 0;
|
||||
}
|
||||
long hash = 0;
|
||||
for(char c : s.toCharArray()) {
|
||||
hash = 31L * hash + c;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.dfsek.terra.api.gaea.math;
|
||||
|
||||
import com.dfsek.terra.api.gaea.biome.NormalizationUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ProbabilityCollection<E> {
|
||||
private final Set<Object> cont = new HashSet<>();
|
||||
private Object[] array = new Object[0];
|
||||
private int size;
|
||||
|
||||
public com.dfsek.terra.api.gaea.math.ProbabilityCollection<E> add(E item, int probability) {
|
||||
if(!cont.contains(item)) size++;
|
||||
cont.add(item);
|
||||
int oldLength = array.length;
|
||||
Object[] newArray = new Object[array.length + probability];
|
||||
System.arraycopy(array, 0, newArray, 0, array.length); // Expand array.
|
||||
array = newArray;
|
||||
for(int i = oldLength; i < array.length; i++) array[i] = item;
|
||||
return this;
|
||||
}
|
||||
|
||||
public E get() {
|
||||
if(array.length == 0) return null;
|
||||
return (E) array[ThreadLocalRandom.current().nextInt(array.length)];
|
||||
}
|
||||
|
||||
public E get(Random r) {
|
||||
if(array.length == 0) return null;
|
||||
return (E) array[r.nextInt(array.length)];
|
||||
}
|
||||
|
||||
public E get(FastNoiseLite n, double x, double z) {
|
||||
if(array.length == 0) return null;
|
||||
return (E) array[NormalizationUtil.normalize(n.getNoise(x, z), array.length, 1)];
|
||||
}
|
||||
|
||||
public int getTotalProbability() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
123
src/main/java/com/dfsek/terra/api/gaea/math/Range.java
Normal file
123
src/main/java/com/dfsek/terra/api/gaea/math/Range.java
Normal file
@@ -0,0 +1,123 @@
|
||||
package com.dfsek.terra.api.gaea.math;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
|
||||
public class Range implements Iterable<Integer> {
|
||||
private int min;
|
||||
private int max;
|
||||
|
||||
public Range(int min, int max) {
|
||||
if(min > max) throw new IllegalArgumentException("Minimum must not be grater than maximum!");
|
||||
this.max = max;
|
||||
this.min = min;
|
||||
}
|
||||
|
||||
public boolean isInRange(int test) {
|
||||
return test >= min && test < max;
|
||||
}
|
||||
|
||||
public int getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
public com.dfsek.terra.api.gaea.math.Range setMax(int max) {
|
||||
this.max = max;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getMin() {
|
||||
return min;
|
||||
}
|
||||
|
||||
public com.dfsek.terra.api.gaea.math.Range setMin(int min) {
|
||||
this.min = min;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getRange() {
|
||||
return max - min;
|
||||
}
|
||||
|
||||
public com.dfsek.terra.api.gaea.math.Range multiply(int mult) {
|
||||
min *= mult;
|
||||
max *= mult;
|
||||
return this;
|
||||
}
|
||||
|
||||
public com.dfsek.terra.api.gaea.math.Range reflect(int pt) {
|
||||
return new com.dfsek.terra.api.gaea.math.Range(2 * pt - this.getMax(), 2 * pt - this.getMin());
|
||||
}
|
||||
|
||||
public int get(Random r) {
|
||||
return r.nextInt((max - min) + 1) + min;
|
||||
}
|
||||
|
||||
public com.dfsek.terra.api.gaea.math.Range intersects(com.dfsek.terra.api.gaea.math.Range other) {
|
||||
try {
|
||||
return new com.dfsek.terra.api.gaea.math.Range(FastMath.max(this.getMin(), other.getMin()), FastMath.min(this.getMax(), other.getMax()));
|
||||
} catch(IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public com.dfsek.terra.api.gaea.math.Range add(int add) {
|
||||
this.min += add;
|
||||
this.max += add;
|
||||
return this;
|
||||
}
|
||||
|
||||
public com.dfsek.terra.api.gaea.math.Range sub(int sub) {
|
||||
this.min -= sub;
|
||||
this.max -= sub;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Min: " + getMin() + ", Max:" + getMax();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return min * 31 + max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(! (obj instanceof com.dfsek.terra.api.gaea.math.Range)) return false;
|
||||
com.dfsek.terra.api.gaea.math.Range other = (com.dfsek.terra.api.gaea.math.Range) obj;
|
||||
return other.getMin() == this.getMin() && other.getMax() == this.getMax();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<Integer> iterator() {
|
||||
return new RangeIterator(this);
|
||||
}
|
||||
|
||||
private static class RangeIterator implements Iterator<Integer> {
|
||||
private final com.dfsek.terra.api.gaea.math.Range m;
|
||||
private Integer current;
|
||||
|
||||
public RangeIterator(com.dfsek.terra.api.gaea.math.Range m) {
|
||||
this.m = m;
|
||||
current = m.getMin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return current < m.getMax();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer next() {
|
||||
current++;
|
||||
return current - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.dfsek.terra.api.gaea.population;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ChunkCoordinate implements Serializable {
|
||||
public static final long serialVersionUID = 7102462856296750285L;
|
||||
private final int x;
|
||||
private final int z;
|
||||
private final UUID worldID;
|
||||
|
||||
public ChunkCoordinate(int x, int z, UUID worldID) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.worldID = worldID;
|
||||
}
|
||||
|
||||
public ChunkCoordinate(Chunk c) {
|
||||
this.x = c.getX();
|
||||
this.z = c.getZ();
|
||||
this.worldID = c.getWorld().getUID();
|
||||
}
|
||||
|
||||
public UUID getWorldID() {
|
||||
return worldID;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return x * 31 + z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(! (obj instanceof com.dfsek.terra.api.gaea.population.ChunkCoordinate)) return false;
|
||||
com.dfsek.terra.api.gaea.population.ChunkCoordinate other = (com.dfsek.terra.api.gaea.population.ChunkCoordinate) obj;
|
||||
return other.getX() == x && other.getZ() == z;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.dfsek.terra.api.gaea.population;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public abstract class GaeaBlockPopulator {
|
||||
public abstract void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk);
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.dfsek.terra.api.gaea.population;
|
||||
|
||||
import com.dfsek.terra.api.gaea.Gaea;
|
||||
import com.dfsek.terra.api.gaea.profiler.ProfileFuture;
|
||||
import com.dfsek.terra.api.gaea.profiler.WorldProfiler;
|
||||
import com.dfsek.terra.api.gaea.util.FastRandom;
|
||||
import com.dfsek.terra.api.gaea.util.GlueList;
|
||||
import com.dfsek.terra.api.gaea.util.SerializationUtil;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class PopulationManager extends BlockPopulator {
|
||||
private final List<GaeaBlockPopulator> attachedPopulators = new GlueList<>();
|
||||
private final HashSet<ChunkCoordinate> needsPop = new HashSet<>();
|
||||
private final JavaPlugin main;
|
||||
private final Object popLock = new Object();
|
||||
private WorldProfiler profiler;
|
||||
|
||||
public PopulationManager(JavaPlugin main) {
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
public void attach(GaeaBlockPopulator populator) {
|
||||
this.attachedPopulators.add(populator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||
try(ProfileFuture ignored = measure()) {
|
||||
needsPop.add(new ChunkCoordinate(chunk));
|
||||
int x = chunk.getX();
|
||||
int z = chunk.getZ();
|
||||
if(main.isEnabled()) {
|
||||
for(int xi = - 1; xi <= 1; xi++) {
|
||||
for(int zi = - 1; zi <= 1; zi++) {
|
||||
if(xi == 0 && zi == 0) continue;
|
||||
if(world.isChunkGenerated(xi + x, zi + z)) checkNeighbors(xi + x, zi + z, world);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ProfileFuture measure() {
|
||||
if(profiler != null) return profiler.measure("PopulationManagerTime");
|
||||
return null;
|
||||
}
|
||||
|
||||
public void attachProfiler(WorldProfiler p) {
|
||||
this.profiler = p;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized void saveBlocks(World w) throws IOException {
|
||||
File f = new File(Gaea.getGaeaFolder(w), "chunks.bin");
|
||||
f.createNewFile();
|
||||
SerializationUtil.toFile((HashSet<ChunkCoordinate>) needsPop.clone(), f);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized void loadBlocks(World w) throws IOException, ClassNotFoundException {
|
||||
File f = new File(Gaea.getGaeaFolder(w), "chunks.bin");
|
||||
needsPop.addAll((HashSet<ChunkCoordinate>) SerializationUtil.fromFile(f));
|
||||
}
|
||||
|
||||
|
||||
// Synchronize to prevent chunks from being queued for population multiple times.
|
||||
public synchronized void checkNeighbors(int x, int z, World w) {
|
||||
ChunkCoordinate c = new ChunkCoordinate(x, z, w.getUID());
|
||||
if(w.isChunkGenerated(x + 1, z)
|
||||
&& w.isChunkGenerated(x - 1, z)
|
||||
&& w.isChunkGenerated(x, z + 1)
|
||||
&& w.isChunkGenerated(x, z - 1) && needsPop.contains(c)) {
|
||||
Random random = new FastRandom(w.getSeed());
|
||||
long xRand = (random.nextLong() / 2L << 1L) + 1L;
|
||||
long zRand = (random.nextLong() / 2L << 1L) + 1L;
|
||||
random.setSeed((long) x * xRand + (long) z * zRand ^ w.getSeed());
|
||||
Chunk currentChunk = w.getChunkAt(x, z);
|
||||
for(GaeaBlockPopulator r : attachedPopulators) {
|
||||
r.populate(w, random, currentChunk);
|
||||
}
|
||||
needsPop.remove(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.dfsek.terra.api.gaea.profiler;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
/**
|
||||
* Class to hold a profiler data value. Contains formatting method to highlight value based on desired range.
|
||||
*/
|
||||
public class DataHolder {
|
||||
private final long desired;
|
||||
private final DataType type;
|
||||
private final double desiredRangePercent;
|
||||
|
||||
/**
|
||||
* Constructs a DataHolder with a DataType and a desired value, including a percentage around the desired value considered acceptable
|
||||
*
|
||||
* @param type The type of data held in this instance.
|
||||
* @param desired The desired value. This should be the average value of whatever is being measured.
|
||||
* @param desiredRangePercent The percentage around the desired value to be considered acceptable.
|
||||
*/
|
||||
public DataHolder(DataType type, long desired, double desiredRangePercent) {
|
||||
this.desired = desired;
|
||||
this.type = type;
|
||||
this.desiredRangePercent = desiredRangePercent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String, formatted with Bungee ChatColors.<br>
|
||||
* GREEN if the value is better than desired and outside of acceptable range.<br>
|
||||
* YELLOW if the value is better or worse than desired, and within acceptable range.<br>
|
||||
* RED if the value is worse than desired and outside of acceptable range.<br>
|
||||
*
|
||||
* @param data The data to format.
|
||||
* @return String - The formatted data.
|
||||
*/
|
||||
public String getFormattedData(long data) {
|
||||
double range = desiredRangePercent * desired;
|
||||
ChatColor color = ChatColor.YELLOW;
|
||||
if(FastMath.abs(data - desired) > range) {
|
||||
if(data > desired) color = type.getDesire().getHighColor();
|
||||
else color = type.getDesire().getLowColor();
|
||||
}
|
||||
return color + type.getFormatted(data) + ChatColor.RESET;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.dfsek.terra.api.gaea.profiler;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
|
||||
public enum DataType {
|
||||
PERIOD_MILLISECONDS(Desire.LOW, 1000000, "ms"), PERIOD_NANOSECONDS(Desire.LOW, 1, "ns");
|
||||
private final Desire desire;
|
||||
private final long divisor;
|
||||
private final String unit;
|
||||
|
||||
DataType(Desire d, long divisor, String unit) {
|
||||
this.desire = d;
|
||||
this.divisor = divisor;
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
public String getFormatted(long value) {
|
||||
return (double) FastMath.round(((double) value / divisor) * 100D) / 100D + unit;
|
||||
}
|
||||
|
||||
public Desire getDesire() {
|
||||
return desire;
|
||||
}
|
||||
}
|
||||
36
src/main/java/com/dfsek/terra/api/gaea/profiler/Desire.java
Normal file
36
src/main/java/com/dfsek/terra/api/gaea/profiler/Desire.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package com.dfsek.terra.api.gaea.profiler;
|
||||
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
/**
|
||||
* Enum to represent the "goal" of a value, whether it is desirable for the value to be high (e.g. Frequency), or low (e.g. Period)
|
||||
*/
|
||||
public enum Desire {
|
||||
LOW(ChatColor.RED, ChatColor.GREEN), HIGH(ChatColor.GREEN, ChatColor.RED);
|
||||
|
||||
private final ChatColor high;
|
||||
private final ChatColor low;
|
||||
|
||||
Desire(ChatColor high, ChatColor low) {
|
||||
this.high = high;
|
||||
this.low = low;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the color to display when the numerical value is higher than desired.
|
||||
*
|
||||
* @return ChatColor - color of the value.
|
||||
*/
|
||||
public ChatColor getHighColor() {
|
||||
return high;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the color to display when the numerical value is lower than desired.
|
||||
*
|
||||
* @return ChatColor - color of the value.
|
||||
*/
|
||||
public ChatColor getLowColor() {
|
||||
return low;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.dfsek.terra.api.gaea.profiler;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.MathUtil;
|
||||
import com.dfsek.terra.api.gaea.util.GlueList;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class to record and hold all data for a single type of measurement performed by the profiler.
|
||||
*/
|
||||
public class Measurement {
|
||||
private final List<Long> measurements;
|
||||
private final long desirable;
|
||||
private final DataType type;
|
||||
private long min = Long.MAX_VALUE;
|
||||
private long max = Long.MIN_VALUE;
|
||||
|
||||
/**
|
||||
* Constructs a new Measurement with a desired value and DataType.
|
||||
*
|
||||
* @param desirable The desired value of the measurement.
|
||||
* @param type The type of data the measurement is holding.
|
||||
*/
|
||||
public Measurement(long desirable, DataType type) {
|
||||
this.desirable = desirable;
|
||||
this.type = type;
|
||||
measurements = new GlueList<>();
|
||||
}
|
||||
|
||||
public void record(long value) {
|
||||
max = FastMath.max(value, max);
|
||||
min = FastMath.min(value, min);
|
||||
if(value / 1000000 > 5000) Bukkit.getLogger().warning("Measurement took " + type.getFormatted(value));
|
||||
measurements.add(value);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return measurements.size();
|
||||
}
|
||||
|
||||
public ProfileFuture beginMeasurement() {
|
||||
ProfileFuture future = new ProfileFuture();
|
||||
long current = System.nanoTime();
|
||||
future.thenRun(() -> record(System.nanoTime() - current));
|
||||
return future;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
min = Long.MAX_VALUE;
|
||||
max = Long.MIN_VALUE;
|
||||
measurements.clear();
|
||||
}
|
||||
|
||||
public DataHolder getDataHolder() {
|
||||
return new DataHolder(type, desirable, 0.25);
|
||||
}
|
||||
|
||||
public long getMin() {
|
||||
if(min == Long.MAX_VALUE) return 0;
|
||||
return min;
|
||||
}
|
||||
|
||||
public long getMax() {
|
||||
if(max == Long.MIN_VALUE) return 0;
|
||||
return max;
|
||||
}
|
||||
|
||||
public long average() {
|
||||
BigInteger running = new BigInteger("0");
|
||||
List<Long> mTemp = new GlueList<>(measurements);
|
||||
for(Long l : mTemp) {
|
||||
running = running.add(BigInteger.valueOf(l));
|
||||
}
|
||||
if(measurements.size() == 0) return 0;
|
||||
return running.divide(BigInteger.valueOf(measurements.size())).longValue();
|
||||
}
|
||||
|
||||
public double getStdDev() {
|
||||
List<Long> mTemp = new GlueList<>(measurements);
|
||||
double[] vals = new double[mTemp.size()];
|
||||
for(int i = 0; i < mTemp.size(); i++) {
|
||||
vals[i] = mTemp.get(i);
|
||||
}
|
||||
return MathUtil.standardDeviation(vals);
|
||||
}
|
||||
|
||||
public int entries() {
|
||||
return measurements.size();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.dfsek.terra.api.gaea.profiler;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ProfileFuture extends CompletableFuture<Boolean> implements AutoCloseable {
|
||||
public ProfileFuture() {
|
||||
super();
|
||||
}
|
||||
|
||||
public boolean complete() {
|
||||
return super.complete(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.complete();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.dfsek.terra.api.gaea.profiler;
|
||||
|
||||
import com.dfsek.terra.api.gaea.generation.GaeaChunkGenerator;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class WorldProfiler {
|
||||
private final BiMap<String, Measurement> measures = HashBiMap.create();
|
||||
private final World world;
|
||||
private boolean isProfiling;
|
||||
|
||||
public WorldProfiler(World w) {
|
||||
if(! (w.getGenerator() instanceof GaeaChunkGenerator))
|
||||
throw new IllegalArgumentException("Attempted to instantiate profiler on non-Gaea managed world!");
|
||||
this.addMeasurement(new Measurement(2500000, DataType.PERIOD_MILLISECONDS), "TotalChunkGenTime")
|
||||
.addMeasurement(new Measurement(2500000, DataType.PERIOD_MILLISECONDS), "ChunkBaseGenTime")
|
||||
.addMeasurement(new Measurement(2000000, DataType.PERIOD_MILLISECONDS), "BiomeApplyTime")
|
||||
.addMeasurement(new Measurement(2000000, DataType.PERIOD_MILLISECONDS), "PopulationManagerTime");
|
||||
isProfiling = false;
|
||||
this.world = w;
|
||||
((GaeaChunkGenerator) w.getGenerator()).attachProfiler(this);
|
||||
}
|
||||
|
||||
public String getResultsFormatted() {
|
||||
if(! isProfiling) return "Profiler is not currently running.";
|
||||
StringBuilder result = new StringBuilder(ChatColor.GOLD + "Gaea World Profiler Results (Min / Avg / Max / Std Dev): \n");
|
||||
for(Map.Entry<String, Measurement> e : measures.entrySet()) {
|
||||
result.append(ChatColor.GOLD)
|
||||
.append(e.getKey())
|
||||
.append(": ")
|
||||
.append(e.getValue().getDataHolder().getFormattedData(e.getValue().getMin()))
|
||||
.append(ChatColor.GOLD)
|
||||
.append(" / ")
|
||||
.append(e.getValue().getDataHolder().getFormattedData(e.getValue().average()))
|
||||
.append(ChatColor.GOLD)
|
||||
.append(" / ")
|
||||
.append(e.getValue().getDataHolder().getFormattedData(e.getValue().getMax()))
|
||||
.append(ChatColor.GOLD)
|
||||
.append(" / ")
|
||||
.append(ChatColor.GREEN)
|
||||
.append((double) FastMath.round((e.getValue().getStdDev() / 1000000) * 100D) / 100D)
|
||||
.append("ms")
|
||||
.append(ChatColor.GOLD).append(" (x").append(e.getValue().size()).append(")\n");
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
for(Map.Entry<String, Measurement> e : measures.entrySet()) {
|
||||
e.getValue().reset();
|
||||
}
|
||||
}
|
||||
|
||||
public com.dfsek.terra.api.gaea.profiler.WorldProfiler addMeasurement(Measurement m, String name) {
|
||||
measures.put(name, m);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setMeasurement(String id, long value) {
|
||||
if(isProfiling) measures.get(id).record(value);
|
||||
}
|
||||
|
||||
public ProfileFuture measure(String id) {
|
||||
if(isProfiling) return measures.get(id).beginMeasurement();
|
||||
else return null;
|
||||
}
|
||||
|
||||
public String getID(Measurement m) {
|
||||
return measures.inverse().get(m);
|
||||
}
|
||||
|
||||
public boolean isProfiling() {
|
||||
return isProfiling;
|
||||
}
|
||||
|
||||
public void setProfiling(boolean enabled) {
|
||||
this.isProfiling = enabled;
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.dfsek.terra.api.gaea.serial;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class MovedObjectInputStream extends ObjectInputStream {
|
||||
private final String oldNameSpace;
|
||||
private final String newNameSpace;
|
||||
|
||||
public MovedObjectInputStream(InputStream in, String oldNameSpace, String newNameSpace) throws IOException {
|
||||
super(in);
|
||||
this.oldNameSpace = oldNameSpace;
|
||||
this.newNameSpace = newNameSpace;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
|
||||
ObjectStreamClass result = super.readClassDescriptor();
|
||||
try {
|
||||
if (result.getName().contains(oldNameSpace)) {
|
||||
String newClassName = result.getName().replace(oldNameSpace, newNameSpace);
|
||||
Class localClass = Class.forName(newClassName);
|
||||
|
||||
Field nameField = ObjectStreamClass.class.getDeclaredField("name");
|
||||
nameField.setAccessible(true);
|
||||
nameField.set(result, newClassName);
|
||||
|
||||
ObjectStreamClass localClassDescriptor = ObjectStreamClass.lookup(localClass);
|
||||
Field suidField = ObjectStreamClass.class.getDeclaredField("suid");
|
||||
suidField.setAccessible(true);
|
||||
suidField.set(result, localClassDescriptor.getSerialVersionUID());
|
||||
}
|
||||
} catch(Exception e) {
|
||||
throw new IOException("Exception when trying to replace namespace", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
|
||||
if (desc.getName().contains(oldNameSpace)) {
|
||||
String newClassName = desc.getName().replace(oldNameSpace, newNameSpace);
|
||||
return Class.forName(newClassName);
|
||||
}
|
||||
return super.resolveClass(desc);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.dfsek.terra.api.gaea.structures.loot;
|
||||
|
||||
import com.dfsek.terra.api.gaea.structures.loot.functions.AmountFunction;
|
||||
import com.dfsek.terra.api.gaea.structures.loot.functions.DamageFunction;
|
||||
import com.dfsek.terra.api.gaea.structures.loot.functions.EnchantWithLevelsFunction;
|
||||
import com.dfsek.terra.api.gaea.structures.loot.functions.Function;
|
||||
import com.dfsek.terra.api.gaea.util.GlueList;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Representation of a single item entry within a Loot Table pool.
|
||||
*/
|
||||
public class Entry {
|
||||
private final Material item;
|
||||
private final long weight;
|
||||
private final List<Function> functions = new GlueList<>();
|
||||
|
||||
/**
|
||||
* Instantiates an Entry from a JSON representation.
|
||||
*
|
||||
* @param entry The JSON Object to instantiate from.
|
||||
*/
|
||||
public Entry(JSONObject entry) {
|
||||
|
||||
String id = entry.get("name").toString();
|
||||
this.item = Material.matchMaterial(id);
|
||||
|
||||
long weight1;
|
||||
try {
|
||||
weight1 = (long) entry.get("weight");
|
||||
} catch(NullPointerException e) {
|
||||
weight1 = 1;
|
||||
}
|
||||
|
||||
this.weight = weight1;
|
||||
if(entry.containsKey("functions")) {
|
||||
for(Object function : (JSONArray) entry.get("functions")) {
|
||||
switch(((String) ((JSONObject) function).get("function"))) {
|
||||
case "minecraft:set_count":
|
||||
case "set_count":
|
||||
Object loot = ((JSONObject) function).get("count");
|
||||
long max, min;
|
||||
if(loot instanceof Long) {
|
||||
max = (Long) loot;
|
||||
min = (Long) loot;
|
||||
} else {
|
||||
max = (long) ((JSONObject) loot).get("max");
|
||||
min = (long) ((JSONObject) loot).get("min");
|
||||
}
|
||||
functions.add(new AmountFunction(FastMath.toIntExact(min), FastMath.toIntExact(max)));
|
||||
break;
|
||||
case "minecraft:set_damage":
|
||||
case "set_damage":
|
||||
long maxDamage = (long) ((JSONObject) ((JSONObject) function).get("damage")).get("max");
|
||||
long minDamage = (long) ((JSONObject) ((JSONObject) function).get("damage")).get("min");
|
||||
functions.add(new DamageFunction(FastMath.toIntExact(minDamage), FastMath.toIntExact(maxDamage)));
|
||||
break;
|
||||
case "minecraft:enchant_with_levels":
|
||||
case "enchant_with_levels":
|
||||
long maxEnchant = (long) ((JSONObject) ((JSONObject) function).get("levels")).get("max");
|
||||
long minEnchant = (long) ((JSONObject) ((JSONObject) function).get("levels")).get("min");
|
||||
JSONArray disabled = null;
|
||||
if(((JSONObject) function).containsKey("disabled_enchants"))
|
||||
disabled = (JSONArray) ((JSONObject) function).get("disabled_enchants");
|
||||
functions.add(new EnchantWithLevelsFunction(FastMath.toIntExact(minEnchant), FastMath.toIntExact(maxEnchant), disabled));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a single ItemStack from the Entry, applying all functions to it.
|
||||
*
|
||||
* @param r The Random instance to apply functions with
|
||||
* @return ItemStack - The ItemStack with all functions applied.
|
||||
*/
|
||||
public ItemStack getItem(Random r) {
|
||||
ItemStack item = new ItemStack(this.item, 1);
|
||||
for(Function f : functions) {
|
||||
item = f.apply(item, r);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the weight attribute of the Entry.
|
||||
*
|
||||
* @return long - The weight of the Entry.
|
||||
*/
|
||||
public long getWeight() {
|
||||
return this.weight;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.dfsek.terra.api.gaea.structures.loot;
|
||||
|
||||
import com.dfsek.terra.api.gaea.util.GlueList;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Class representation of a Loot Table to populate chest loot.
|
||||
*/
|
||||
public class LootTable {
|
||||
private final List<Pool> pools = new GlueList<>();
|
||||
|
||||
/**
|
||||
* Instantiates a LootTable from a JSON String.
|
||||
*
|
||||
* @param json The JSON String representing the loot table.
|
||||
* @throws ParseException if malformed JSON is passed.
|
||||
*/
|
||||
public LootTable(String json) throws ParseException {
|
||||
JSONParser jsonParser = new JSONParser();
|
||||
Object tableJSON = jsonParser.parse(json);
|
||||
JSONArray poolArray = (JSONArray) ((JSONObject) tableJSON).get("pools");
|
||||
for(Object pool : poolArray) {
|
||||
pools.add(new Pool((JSONObject) pool));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a list of ItemStacks from the loot table using the given Random instance.
|
||||
*
|
||||
* @param r The Random instance to use.
|
||||
* @return List<ItemStack> - The list of loot fetched.
|
||||
*/
|
||||
public List<ItemStack> getLoot(Random r) {
|
||||
List<ItemStack> itemList = new GlueList<>();
|
||||
for(Pool pool : pools) {
|
||||
itemList.addAll(pool.getItems(r));
|
||||
}
|
||||
return itemList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills an Inventory with loot.
|
||||
*
|
||||
* @param i The Inventory to fill.
|
||||
* @param r The The Random instance to use.
|
||||
*/
|
||||
public void fillInventory(Inventory i, Random r) {
|
||||
List<ItemStack> loot = getLoot(r);
|
||||
for(ItemStack stack : loot) {
|
||||
int attempts = 0;
|
||||
while(stack.getAmount() != 0 && attempts < 10) {
|
||||
ItemStack newStack = stack.clone();
|
||||
newStack.setAmount(1);
|
||||
int slot = r.nextInt(i.getSize());
|
||||
ItemStack slotItem = i.getItem(slot);
|
||||
if(slotItem == null) {
|
||||
i.setItem(slot, newStack);
|
||||
stack.setAmount(stack.getAmount() - 1);
|
||||
} else if(slotItem.getType() == newStack.getType()) {
|
||||
ItemStack dep = newStack.clone();
|
||||
dep.setAmount(newStack.getAmount() + slotItem.getAmount());
|
||||
i.setItem(slot, dep);
|
||||
stack.setAmount(stack.getAmount() - 1);
|
||||
}
|
||||
attempts++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.dfsek.terra.api.gaea.structures.loot;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.gaea.util.GlueList;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Representation of a Loot Table pool, or a set of items to be fetched independently.
|
||||
*/
|
||||
public class Pool {
|
||||
private final int max;
|
||||
private final int min;
|
||||
private final ProbabilityCollection<Entry> entries = new ProbabilityCollection<>();
|
||||
|
||||
/**
|
||||
* Instantiates a Pool from a JSON representation.
|
||||
*
|
||||
* @param pool The JSON Object to instantiate from.
|
||||
*/
|
||||
public Pool(JSONObject pool) {
|
||||
Object amount = pool.get("rolls");
|
||||
if(amount instanceof Long) {
|
||||
max = FastMath.toIntExact((Long) amount);
|
||||
min = FastMath.toIntExact((Long) amount);
|
||||
} else {
|
||||
max = FastMath.toIntExact((Long) ((JSONObject) amount).get("max"));
|
||||
min = FastMath.toIntExact((Long) ((JSONObject) amount).get("min"));
|
||||
}
|
||||
|
||||
for(Object entryJSON : (JSONArray) pool.get("entries")) {
|
||||
Entry entry = new Entry((JSONObject) entryJSON);
|
||||
entries.add(entry, FastMath.toIntExact(entry.getWeight()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a list of items from the pool using the provided Random instance.
|
||||
*
|
||||
* @param r The Random instance to use.
|
||||
* @return List<ItemStack> - The list of items fetched.
|
||||
*/
|
||||
public List<ItemStack> getItems(Random r) {
|
||||
|
||||
int rolls = r.nextInt(max - min + 1) + min;
|
||||
List<ItemStack> items = new GlueList<>();
|
||||
for(int i = 0; i < rolls; i++) {
|
||||
items.add(entries.get(r).getItem(r));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.dfsek.terra.api.gaea.structures.loot.functions;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Loot Function fot setting the amount of an item.
|
||||
*/
|
||||
public class AmountFunction implements Function {
|
||||
private final int max;
|
||||
private final int min;
|
||||
|
||||
/**
|
||||
* Instantiates an AmountFunction.
|
||||
*
|
||||
* @param min Minimum amount.
|
||||
* @param max Maximum amount.
|
||||
*/
|
||||
public AmountFunction(int min, int max) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the function to an ItemStack.
|
||||
*
|
||||
* @param original The ItemStack on which to apply the function.
|
||||
* @param r The Random instance to use.
|
||||
* @return - ItemStack - The mutated ItemStack.
|
||||
*/
|
||||
@Override
|
||||
public ItemStack apply(ItemStack original, Random r) {
|
||||
original.setAmount(r.nextInt(max - min + 1) + min);
|
||||
return original;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.dfsek.terra.api.gaea.structures.loot.functions;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.Damageable;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Loot Function for setting the damage on items in Loot Tables
|
||||
*/
|
||||
public class DamageFunction implements Function {
|
||||
private final int max;
|
||||
private final int min;
|
||||
|
||||
/**
|
||||
* Instantiates a DamageFunction.
|
||||
*
|
||||
* @param min Minimum amount of damage (percentage, out of 100)
|
||||
* @param max Maximum amount of damage (percentage, out of 100)
|
||||
*/
|
||||
public DamageFunction(int min, int max) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the function to an ItemStack.
|
||||
*
|
||||
* @param original The ItemStack on which to apply the function.
|
||||
* @param r The Random instance to use.
|
||||
* @return - ItemStack - The mutated ItemStack.
|
||||
*/
|
||||
@Override
|
||||
public ItemStack apply(ItemStack original, Random r) {
|
||||
double itemDurability = (r.nextDouble() * (max - min)) + min;
|
||||
Damageable damage = (Damageable) original.getItemMeta();
|
||||
damage.setDamage((int) (original.getType().getMaxDurability() - (itemDurability / 100) * original.getType().getMaxDurability()));
|
||||
original.setItemMeta((ItemMeta) damage);
|
||||
return original;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.dfsek.terra.api.gaea.structures.loot.functions;
|
||||
|
||||
import com.dfsek.terra.api.gaea.util.GlueList;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.json.simple.JSONArray;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class EnchantWithLevelsFunction implements Function {
|
||||
private final int min;
|
||||
private final int max;
|
||||
private final JSONArray disabled;
|
||||
|
||||
|
||||
public EnchantWithLevelsFunction(int min, int max, JSONArray disabled) {
|
||||
this.max = max;
|
||||
this.min = min;
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the function to an ItemStack.
|
||||
*
|
||||
* @param original The ItemStack on which to apply the function.
|
||||
* @param r The Random instance to use.
|
||||
* @return - ItemStack - The mutated ItemStack.
|
||||
*/
|
||||
@Override
|
||||
public ItemStack apply(ItemStack original, Random r) {
|
||||
double enchant = (r.nextDouble() * (max - min)) + min;
|
||||
List<Enchantment> possible = new GlueList<>();
|
||||
for(Enchantment ench : Enchantment.values()) {
|
||||
if(ench.canEnchantItem(original) && (disabled == null || !this.disabled.contains(ench.getName()))) {
|
||||
possible.add(ench);
|
||||
}
|
||||
}
|
||||
int numEnchant = (r.nextInt((int) FastMath.abs(enchant)) / 10 + 1);
|
||||
if(possible.size() >= numEnchant) {
|
||||
Collections.shuffle(possible);
|
||||
iter:
|
||||
for(int i = 0; i < numEnchant; i++) {
|
||||
Enchantment chosen = possible.get(i);
|
||||
for(Enchantment ench : original.getEnchantments().keySet()) {
|
||||
if(chosen.conflictsWith(ench)) continue iter;
|
||||
}
|
||||
int lvl = r.nextInt(1 + (int) (((enchant / 40 > 1) ? 1 : enchant / 40) * (chosen.getMaxLevel())));
|
||||
try {
|
||||
original.addEnchantment(chosen, FastMath.max(lvl, 1));
|
||||
} catch(IllegalArgumentException e) {
|
||||
Bukkit.getLogger().warning("[Gaea] Attempted to enchant " + original.getType() + " with " + chosen + " at level " + FastMath.max(lvl, 1) + ", but an unexpected exception occurred! Usually this is caused by a misbehaving enchantment plugin.");
|
||||
}
|
||||
}
|
||||
}
|
||||
return original;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.dfsek.terra.api.gaea.structures.loot.functions;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Interface for mutating items in Loot Tables.
|
||||
*/
|
||||
public interface Function {
|
||||
/**
|
||||
* Applies the function to an ItemStack.
|
||||
*
|
||||
* @param original The ItemStack on which to apply the function.
|
||||
* @param r The Random instance to use.
|
||||
* @return - ItemStack - The mutated ItemStack.
|
||||
*/
|
||||
ItemStack apply(ItemStack original, Random r);
|
||||
}
|
||||
66
src/main/java/com/dfsek/terra/api/gaea/tree/CustomTreeType.java
Executable file
66
src/main/java/com/dfsek/terra/api/gaea/tree/CustomTreeType.java
Executable file
@@ -0,0 +1,66 @@
|
||||
package com.dfsek.terra.api.gaea.tree;
|
||||
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.TreeGetter;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.trees.Cactus;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.trees.IceSpike;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.trees.OakTree;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.trees.ShatteredPillar;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.trees.ShatteredTree;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.trees.SmallShatteredPillar;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.trees.SmallShatteredTree;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.trees.SpruceTree;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public enum CustomTreeType implements TreeGetter {
|
||||
SHATTERED_SMALL {
|
||||
@Override
|
||||
public FractalTree getTree(Location l, Random r) {
|
||||
return new SmallShatteredTree(l, r);
|
||||
}
|
||||
},
|
||||
SHATTERED_LARGE {
|
||||
@Override
|
||||
public FractalTree getTree(Location l, Random r) {
|
||||
return new ShatteredTree(l, r);
|
||||
}
|
||||
},
|
||||
GIANT_OAK {
|
||||
@Override
|
||||
public FractalTree getTree(Location l, Random r) {
|
||||
return new OakTree(l, r);
|
||||
}
|
||||
},
|
||||
GIANT_SPRUCE {
|
||||
@Override
|
||||
public FractalTree getTree(Location l, Random r) {
|
||||
return new SpruceTree(l, r);
|
||||
}
|
||||
},
|
||||
SMALL_SHATTERED_PILLAR {
|
||||
@Override
|
||||
public FractalTree getTree(Location l, Random r) {
|
||||
return new SmallShatteredPillar(l, r);
|
||||
}
|
||||
},
|
||||
LARGE_SHATTERED_PILLAR {
|
||||
@Override
|
||||
public FractalTree getTree(Location l, Random r) {
|
||||
return new ShatteredPillar(l, r);
|
||||
}
|
||||
},
|
||||
CACTUS {
|
||||
@Override
|
||||
public FractalTree getTree(Location l, Random r) {
|
||||
return new Cactus(l, r);
|
||||
}
|
||||
},
|
||||
ICE_SPIKE {
|
||||
@Override
|
||||
public FractalTree getTree(Location l, Random r) {
|
||||
return new IceSpike(l, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/main/java/com/dfsek/terra/api/gaea/tree/Tree.java
Normal file
14
src/main/java/com/dfsek/terra/api/gaea/tree/Tree.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.dfsek.terra.api.gaea.tree;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
public interface Tree {
|
||||
boolean plant(Location l, Random r, JavaPlugin main);
|
||||
|
||||
Set<Material> getSpawnable();
|
||||
}
|
||||
105
src/main/java/com/dfsek/terra/api/gaea/tree/TreeType.java
Normal file
105
src/main/java/com/dfsek/terra/api/gaea/tree/TreeType.java
Normal file
@@ -0,0 +1,105 @@
|
||||
package com.dfsek.terra.api.gaea.tree;
|
||||
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
public enum TreeType implements Tree {
|
||||
SHATTERED_SMALL(null, Collections.singleton(Material.END_STONE)),
|
||||
SHATTERED_LARGE(null, Collections.singleton(Material.END_STONE)),
|
||||
GIANT_OAK(null, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
GIANT_SPRUCE(null, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
SMALL_SHATTERED_PILLAR(null, Collections.singleton(Material.END_STONE)),
|
||||
LARGE_SHATTERED_PILLAR(null, Collections.singleton(Material.END_STONE)),
|
||||
CACTUS(null, Sets.newHashSet(Material.SAND, Material.RED_SAND)),
|
||||
ICE_SPIKE(null, Sets.newHashSet(Material.SNOW_BLOCK, Material.SNOW, Material.STONE, Material.GRASS_BLOCK)),
|
||||
OAK(org.bukkit.TreeType.TREE, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
LARGE_OAK(org.bukkit.TreeType.BIG_TREE, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
SPRUCE(org.bukkit.TreeType.REDWOOD, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
LARGE_SPRUCE(org.bukkit.TreeType.TALL_REDWOOD, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
MEGA_SPRUCE(org.bukkit.TreeType.MEGA_REDWOOD, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
BIRCH(org.bukkit.TreeType.BIRCH, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
CHORUS_PLANT(org.bukkit.TreeType.CHORUS_PLANT, Sets.newHashSet(Material.END_STONE)),
|
||||
ACACIA(org.bukkit.TreeType.ACACIA, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
TALL_BIRCH(org.bukkit.TreeType.TALL_BIRCH, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
JUNGLE(org.bukkit.TreeType.JUNGLE, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
SMALL_JUNGLE(org.bukkit.TreeType.SMALL_JUNGLE, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
JUNGLE_COCOA(org.bukkit.TreeType.COCOA_TREE, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
JUNGLE_BUSH(org.bukkit.TreeType.JUNGLE_BUSH, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
DARK_OAK(org.bukkit.TreeType.DARK_OAK, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
BROWN_MUSHROOM(org.bukkit.TreeType.BROWN_MUSHROOM, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL, Material.MYCELIUM, Material.NETHERRACK, Material.CRIMSON_NYLIUM, Material.WARPED_NYLIUM)),
|
||||
RED_MUSHROOM(org.bukkit.TreeType.RED_MUSHROOM, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL, Material.MYCELIUM, Material.NETHERRACK, Material.CRIMSON_NYLIUM, Material.WARPED_NYLIUM)),
|
||||
SWAMP_OAK(org.bukkit.TreeType.SWAMP, Sets.newHashSet(Material.GRASS_BLOCK, Material.DIRT, Material.PODZOL)),
|
||||
WARPED_FUNGUS(org.bukkit.TreeType.WARPED_FUNGUS, Collections.singleton(Material.WARPED_NYLIUM)),
|
||||
CRIMSON_FUNGUS(org.bukkit.TreeType.CRIMSON_FUNGUS, Collections.singleton(Material.CRIMSON_NYLIUM));
|
||||
|
||||
private final org.bukkit.TreeType vanillaType;
|
||||
private final Set<Material> spawnable;
|
||||
|
||||
TreeType(org.bukkit.TreeType vanillaType, Set<Material> spawnable) {
|
||||
this.vanillaType = vanillaType;
|
||||
this.spawnable = spawnable;
|
||||
}
|
||||
|
||||
public static com.dfsek.terra.api.gaea.tree.TreeType fromBukkit(org.bukkit.TreeType type) {
|
||||
switch(type) {
|
||||
case TREE: return OAK;
|
||||
case BIRCH: return BIRCH;
|
||||
case ACACIA: return ACACIA;
|
||||
case SWAMP: return SWAMP_OAK;
|
||||
case JUNGLE: return JUNGLE;
|
||||
case REDWOOD: return SPRUCE;
|
||||
case BIG_TREE: return LARGE_OAK;
|
||||
case DARK_OAK: return DARK_OAK;
|
||||
case COCOA_TREE: return JUNGLE_COCOA;
|
||||
case TALL_BIRCH: return TALL_BIRCH;
|
||||
case JUNGLE_BUSH: return JUNGLE_BUSH;
|
||||
case CHORUS_PLANT: return CHORUS_PLANT;
|
||||
case MEGA_REDWOOD: return MEGA_SPRUCE;
|
||||
case RED_MUSHROOM: return RED_MUSHROOM;
|
||||
case SMALL_JUNGLE: return SMALL_JUNGLE;
|
||||
case TALL_REDWOOD: return LARGE_SPRUCE;
|
||||
case WARPED_FUNGUS: return WARPED_FUNGUS;
|
||||
case BROWN_MUSHROOM: return BROWN_MUSHROOM;
|
||||
case CRIMSON_FUNGUS: return CRIMSON_FUNGUS;
|
||||
default: throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCustom() {
|
||||
return this.vanillaType == null;
|
||||
}
|
||||
|
||||
public org.bukkit.TreeType getVanillaTreeType() {
|
||||
return vanillaType;
|
||||
}
|
||||
|
||||
public CustomTreeType getCustomTreeType() {
|
||||
if(getVanillaTreeType() != null) return null;
|
||||
return CustomTreeType.valueOf(this.toString());
|
||||
}
|
||||
|
||||
public boolean plant(Location l, Random r, JavaPlugin main) {
|
||||
if(this.getVanillaTreeType() == null) {
|
||||
if(!spawnable.contains(l.subtract(0, 1, 0).getBlock().getType())) return false;
|
||||
FractalTree tree = getCustomTreeType().getTree(l, r);
|
||||
if(main.isEnabled()) co.aikar.taskchain.BukkitTaskChainFactory.create(main).newChain()
|
||||
.async(tree::grow)
|
||||
.sync(tree::plant)
|
||||
.execute();
|
||||
return true;
|
||||
}
|
||||
return l.getWorld().generateTree(l, this.getVanillaTreeType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Material> getSpawnable() {
|
||||
return spawnable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.util.Consumer;
|
||||
|
||||
|
||||
public class EntitySpawnHolder {
|
||||
private final Location l;
|
||||
private final Class<? extends Entity> e;
|
||||
private final Consumer<Entity> c;
|
||||
|
||||
public EntitySpawnHolder(Location l, Class<? extends Entity> e, Consumer<Entity> c) {
|
||||
this.l = l;
|
||||
this.e = e;
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Class getEntity() {
|
||||
return e;
|
||||
}
|
||||
|
||||
public Consumer<Entity> getConsumer() {
|
||||
return c;
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal;
|
||||
|
||||
import com.dfsek.terra.api.gaea.util.GlueList;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.util.Consumer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
public abstract class FractalTree {
|
||||
private final Map<Location, BlockData> treeAssembler = new HashMap<>();
|
||||
private final List<EntitySpawnHolder> entities = new GlueList<>();
|
||||
private final Location origin;
|
||||
private final Random random;
|
||||
private final List<Material> replaceable = Arrays.asList(Material.AIR, Material.GRASS_BLOCK, Material.DIRT, Material.STONE, Material.COARSE_DIRT, Material.GRAVEL, Material.PODZOL,
|
||||
Material.GRASS, Material.TALL_GRASS, Material.FERN, Material.POPPY, Material.LARGE_FERN, Material.BLUE_ORCHID, Material.AZURE_BLUET, Material.END_STONE, Material.SNOW, Material.SAND, Material.STONE_BUTTON, Material.DEAD_BUSH);
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates a TreeGrower at an origin location.
|
||||
*
|
||||
* @param origin - The origin location.
|
||||
* @param random - The random object to use whilst generating the tree.
|
||||
*/
|
||||
public FractalTree(Location origin, Random random) {
|
||||
this.origin = origin.add(0, 1, 0);
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw tree map.
|
||||
*
|
||||
* @return HashMap<Location, BlockData> - The raw dictionary representation of the tree.
|
||||
*/
|
||||
public Map<Location, BlockData> getTree() {
|
||||
return treeAssembler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the Random object used to generate the tree.
|
||||
*
|
||||
* @return Random - The Random object.
|
||||
*/
|
||||
public Random getRandom() {
|
||||
return random;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the origin location.
|
||||
*
|
||||
* @return Location - The origin location specified upon instantiation.
|
||||
*/
|
||||
public Location getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a block in the tree's storage map to a material.
|
||||
*
|
||||
* @param l - The location to set.
|
||||
* @param m - The material to which it will be set.
|
||||
*/
|
||||
public void setBlock(Location l, Material m) {
|
||||
treeAssembler.put(l, m.createBlockData());
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows the tree in memory. Intended to be invoked from an async thread.
|
||||
*/
|
||||
public abstract void grow();
|
||||
|
||||
/**
|
||||
* Pastes the tree in the world. Must be invoked from main thread.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void plant() {
|
||||
for(Map.Entry<Location, BlockData> entry : treeAssembler.entrySet()) {
|
||||
if(replaceable.contains(entry.getKey().getBlock().getType()))
|
||||
entry.getKey().getBlock().setBlockData(entry.getValue(), false);
|
||||
}
|
||||
for(EntitySpawnHolder e : entities) {
|
||||
Objects.requireNonNull(e.getLocation().getWorld()).spawn(e.getLocation(), e.getEntity(), e.getConsumer());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes, unchecked")
|
||||
public void spawnEntity(Location spawn, Class clazz, Consumer<Entity> consumer) {
|
||||
entities.add(new EntitySpawnHolder(spawn, clazz, consumer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the material at the specified block.
|
||||
* Returns air if no material has been set.
|
||||
*
|
||||
* @param l - The location at which to check.
|
||||
* @return Material - The material at the specified block.
|
||||
*/
|
||||
public Material getMaterial(Location l) {
|
||||
return treeAssembler.getOrDefault(l, Material.AIR.createBlockData()).getMaterial();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.ProbabilityCollection;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class TreeGeometry {
|
||||
private final FractalTree tree;
|
||||
|
||||
public TreeGeometry(FractalTree tree) {
|
||||
this.tree = tree;
|
||||
}
|
||||
|
||||
public static Vector getPerpendicular(Vector v) {
|
||||
return v.getZ() < v.getX() ? new Vector(v.getY(), - v.getX(), 0) : new Vector(0, - v.getZ(), v.getY());
|
||||
}
|
||||
|
||||
public FractalTree getTree() {
|
||||
return tree;
|
||||
}
|
||||
|
||||
public void generateSphere(Location l, Material m, int radius, boolean overwrite) {
|
||||
generateSphere(l, new ProbabilityCollection<Material>().add(m, 1), radius, overwrite);
|
||||
}
|
||||
|
||||
public void generateCylinder(Location l, Material m, int radius, int height, boolean overwrite) {
|
||||
generateCylinder(l, new ProbabilityCollection<Material>().add(m, 1), radius, height, overwrite);
|
||||
}
|
||||
|
||||
public void generateSphere(Location l, ProbabilityCollection<Material> m, int radius, boolean overwrite) {
|
||||
for(int x = - radius; x <= radius; x++) {
|
||||
for(int y = - radius; y <= radius; y++) {
|
||||
for(int z = - radius; z <= radius; z++) {
|
||||
Vector position = l.toVector().clone().add(new Vector(x, y, z));
|
||||
if(l.toVector().distance(position) <= radius + 0.5 && (overwrite || tree.getMaterial(position.toLocation(l.getWorld())).isAir()))
|
||||
tree.setBlock(position.toLocation(l.getWorld()), m.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void generateSponge(Location l, ProbabilityCollection<Material> m, int radius, boolean overwrite, int sponginess) {
|
||||
for(int x = - radius; x <= radius; x++) {
|
||||
for(int y = - radius; y <= radius; y++) {
|
||||
for(int z = - radius; z <= radius; z++) {
|
||||
Vector position = l.toVector().clone().add(new Vector(x, y, z));
|
||||
if(tree.getRandom().nextInt(100) < sponginess && l.toVector().distance(position) <= radius + 0.5 && (overwrite || tree.getMaterial(position.toLocation(l.getWorld())).isAir()))
|
||||
tree.setBlock(position.toLocation(l.getWorld()), m.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void generateCylinder(Location l, ProbabilityCollection<Material> m, int radius, int height, boolean overwrite) {
|
||||
for(int x = - radius; x <= radius; x++) {
|
||||
for(int y = 0; y <= height; y++) {
|
||||
for(int z = - radius; z <= radius; z++) {
|
||||
Vector position = l.toVector().clone().add(new Vector(x, 0, z));
|
||||
if(l.toVector().distance(position) <= radius + 0.5 && (overwrite || tree.getMaterial(position.toLocation(l.getWorld())).isAir()))
|
||||
tree.setBlock(position.toLocation(l.getWorld()), m.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public interface TreeGetter {
|
||||
FractalTree getTree(Location l, Random r);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal.trees;
|
||||
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class Cactus extends FractalTree {
|
||||
/**
|
||||
* Instantiates a TreeGrower at an origin location.
|
||||
*
|
||||
* @param origin - The origin location.
|
||||
* @param random - The random object to use whilst generating the tree.
|
||||
*/
|
||||
public Cactus(Location origin, Random random) {
|
||||
super(origin, random);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows the tree in memory. Intended to be invoked from an async thread.
|
||||
*/
|
||||
@Override
|
||||
public void grow() {
|
||||
int h = super.getRandom().nextInt(4) + 1;
|
||||
for(int i = 0; i < h; i++) setBlock(super.getOrigin().clone().add(0, i, 0), Material.CACTUS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal.trees;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.TreeGeometry;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
public class IceSpike extends FractalTree {
|
||||
private final TreeGeometry geo;
|
||||
private static final ProbabilityCollection<Material> ice = new ProbabilityCollection<Material>().add(Material.PACKED_ICE, 95).add(Material.BLUE_ICE, 5);
|
||||
|
||||
/**
|
||||
* Instantiates a TreeGrower at an origin location.
|
||||
*
|
||||
* @param origin - The origin location.
|
||||
* @param random - The random object to use whilst generating the tree.
|
||||
*/
|
||||
public IceSpike(Location origin, Random random) {
|
||||
super(origin, random);
|
||||
geo = new TreeGeometry(this);
|
||||
}
|
||||
|
||||
private double getOffset() {
|
||||
return (getRandom().nextDouble() - 0.5D);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows the tree in memory. Intended to be invoked from an async thread.
|
||||
*/
|
||||
@Override
|
||||
public void grow() {
|
||||
Vector direction = new Vector(getOffset(), 0, getOffset());
|
||||
Location l1 = super.getOrigin().clone();
|
||||
int h = super.getRandom().nextInt(16) + 8;
|
||||
for(int i = 0; i < h; i++) {
|
||||
geo.generateSponge(l1.clone().add(0, i, 0).add(direction.clone().multiply(i)), ice, (int) ((1 - ((double) i / h)) * 2 + 1), true, 80);
|
||||
}
|
||||
for(int i = 0; i < h/3; i++) {
|
||||
setBlock(l1.clone().add(0, h + i, 0).add(direction.clone().multiply(h + i)), ice.get(super.getRandom()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal.trees;
|
||||
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.TreeGeometry;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
public class OakTree extends FractalTree {
|
||||
private final TreeGeometry geo;
|
||||
|
||||
/**
|
||||
* Instantiates a TreeGrower at an origin location.
|
||||
*
|
||||
* @param origin - The origin location.
|
||||
* @param random - The random object to use whilst generating the tree.
|
||||
*/
|
||||
public OakTree(Location origin, Random random) {
|
||||
super(origin, random);
|
||||
geo = new TreeGeometry(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows the tree in memory. Intended to be invoked from an async thread.
|
||||
*/
|
||||
@Override
|
||||
public void grow() {
|
||||
growBranch(super.getOrigin().clone(), new Vector(super.getRandom().nextInt(5) - 2, super.getRandom().nextInt(4) + 6, super.getRandom().nextInt(5) - 2), 2, 0);
|
||||
}
|
||||
|
||||
private void growBranch(Location l1, Vector diff, double d1, int recursions) {
|
||||
if(recursions > 1) {
|
||||
geo.generateSphere(l1, Material.OAK_LEAVES, 1 + super.getRandom().nextInt(2) + (3 - recursions), false);
|
||||
if(recursions > 2) return;
|
||||
}
|
||||
if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI);
|
||||
int d = (int) diff.length();
|
||||
for(int i = 0; i < d; i++) {
|
||||
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), Material.OAK_WOOD, FastMath.max((int) d1, 0), true);
|
||||
}
|
||||
double runningAngle = (double) 45 / (recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.75).rotateAroundX(FastMath.toRadians(runningAngle + getNoise())).rotateAroundZ(FastMath.toRadians(getNoise())),
|
||||
d1 - 1, recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.75).rotateAroundX(FastMath.toRadians(- runningAngle + getNoise())).rotateAroundZ(FastMath.toRadians(getNoise())),
|
||||
d1 - 1, recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.75).rotateAroundZ(FastMath.toRadians(runningAngle + getNoise())).rotateAroundX(FastMath.toRadians(getNoise())),
|
||||
d1 - 1, recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.75).rotateAroundZ(FastMath.toRadians(- runningAngle + getNoise())).rotateAroundX(FastMath.toRadians(getNoise())),
|
||||
d1 - 1, recursions + 1);
|
||||
}
|
||||
|
||||
private int getNoise() {
|
||||
return super.getRandom().nextInt(60) - 30;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal.trees;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.FastNoiseLite;
|
||||
import com.dfsek.terra.api.gaea.math.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.TreeGeometry;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
public class Rock extends FractalTree {
|
||||
private final TreeGeometry geo;
|
||||
private final FastNoiseLite noise;
|
||||
private final FastNoiseLite rock;
|
||||
private static final ProbabilityCollection<Material> ice = new ProbabilityCollection<Material>().add(Material.PACKED_ICE, 95).add(Material.BLUE_ICE, 5);
|
||||
|
||||
/**
|
||||
* Instantiates a TreeGrower at an origin location.
|
||||
*
|
||||
* @param origin - The origin location.
|
||||
* @param random - The random object to use whilst generating the tree.
|
||||
*/
|
||||
public Rock(Location origin, Random random) {
|
||||
super(origin, random);
|
||||
int seed = origin.hashCode();
|
||||
this.noise = new FastNoiseLite(seed);
|
||||
this.rock = new FastNoiseLite(++seed);
|
||||
geo = new TreeGeometry(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows the tree in memory. Intended to be invoked from an async thread.
|
||||
*/
|
||||
@Override
|
||||
public void grow() {
|
||||
Location l1 = super.getOrigin().clone();
|
||||
int h = super.getRandom().nextInt(16) + 8;
|
||||
for(int i = 0; i < h; i++) {
|
||||
geo.generateSponge(l1.clone().add(0, i, 0), ice, (int) ((1-((double) i / h))*2+1), true, 70);
|
||||
}
|
||||
for(int i = 0; i < h/3; i++) {
|
||||
setBlock(l1.clone().add(0, h+i, 0), ice.get(super.getRandom()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal.trees;
|
||||
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.EnderCrystal;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class ShatteredPillar extends FractalTree {
|
||||
/**
|
||||
* Instantiates a TreeGrower at an origin location.
|
||||
*
|
||||
* @param origin - The origin location.
|
||||
* @param random - The random object to use whilst generating the tree.
|
||||
*/
|
||||
public ShatteredPillar(Location origin, Random random) {
|
||||
super(origin, random);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows the tree in memory. Intended to be invoked from an async thread.
|
||||
*/
|
||||
@Override
|
||||
public void grow() {
|
||||
int h = super.getRandom().nextInt(5) + 8;
|
||||
int max = h;
|
||||
for(int i = - h; i < h; i++) setBlock(super.getOrigin().clone().add(0, i, 0), Material.OBSIDIAN);
|
||||
h = h + (getRandom().nextBoolean() ? getRandom().nextInt(3) + 1 : - (getRandom().nextInt(3) + 1));
|
||||
int[] crystalLoc = new int[] {0, 0};
|
||||
if(h > max) {
|
||||
max = h;
|
||||
crystalLoc = new int[] {1, 0};
|
||||
}
|
||||
for(int i = - h; i < h; i++) setBlock(super.getOrigin().clone().add(1, i, 0), Material.OBSIDIAN);
|
||||
h = h + (getRandom().nextBoolean() ? getRandom().nextInt(3) + 1 : - (getRandom().nextInt(3) + 1));
|
||||
if(h > max) {
|
||||
max = h;
|
||||
crystalLoc = new int[] {0, 1};
|
||||
}
|
||||
for(int i = - h; i < h; i++) setBlock(super.getOrigin().clone().add(0, i, 1), Material.OBSIDIAN);
|
||||
h = h + (getRandom().nextBoolean() ? getRandom().nextInt(3) + 1 : - (getRandom().nextInt(3) + 1));
|
||||
if(h > max) {
|
||||
max = h;
|
||||
crystalLoc = new int[] {1, 1};
|
||||
}
|
||||
for(int i = - h; i < h; i++) setBlock(super.getOrigin().clone().add(1, i, 1), Material.OBSIDIAN);
|
||||
if(getRandom().nextInt(100) < 25)
|
||||
spawnEntity(getOrigin().add(crystalLoc[0] + 0.5, max, crystalLoc[1] + 0.5), EnderCrystal.class,
|
||||
enderCrystal -> ((EnderCrystal) enderCrystal).setShowingBottom(false));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal.trees;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.TreeGeometry;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class ShatteredTree extends FractalTree {
|
||||
private final TreeGeometry geo;
|
||||
private final ProbabilityCollection<Material> bark = new ProbabilityCollection<Material>()
|
||||
.add(Material.OBSIDIAN, 1)
|
||||
.add(Material.BLACK_CONCRETE, 1);
|
||||
private final ProbabilityCollection<Material> leaves = new ProbabilityCollection<Material>()
|
||||
.add(Material.PURPLE_STAINED_GLASS, 1)
|
||||
.add(Material.MAGENTA_STAINED_GLASS, 1);
|
||||
|
||||
/**
|
||||
* Instantiates a TreeGrower at an origin location.
|
||||
*
|
||||
* @param origin - The origin location.
|
||||
* @param random - The random object to use whilst generating the tree.
|
||||
*/
|
||||
public ShatteredTree(Location origin, Random random) {
|
||||
super(origin, random);
|
||||
geo = new TreeGeometry(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows the tree in memory. Intended to be invoked from an async thread.
|
||||
*/
|
||||
@Override
|
||||
public void grow() {
|
||||
growBranch(super.getOrigin().clone(), new Vector(super.getRandom().nextInt(5) - 2, super.getRandom().nextInt(4) + 6, super.getRandom().nextInt(5) - 2), 1, 0);
|
||||
|
||||
}
|
||||
|
||||
private void growBranch(Location l1, Vector diff, double d1, int recursions) {
|
||||
if(recursions > 2) {
|
||||
geo.generateSphere(l1, leaves, 1 + super.getRandom().nextInt(2), false);
|
||||
return;
|
||||
}
|
||||
if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI);
|
||||
int d = (int) diff.length();
|
||||
for(int i = 0; i < d; i++) {
|
||||
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), bark, FastMath.max((int) d1, 0), true);
|
||||
}
|
||||
double runningAngle = (double) 45 / (recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.9).rotateAroundX(FastMath.toRadians(runningAngle + getNoise())).rotateAroundZ(FastMath.toRadians(getNoise())),
|
||||
d1 - 1, recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.9).rotateAroundX(FastMath.toRadians(- runningAngle + getNoise())).rotateAroundZ(FastMath.toRadians(getNoise())),
|
||||
d1 - 1, recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.9).rotateAroundZ(FastMath.toRadians(runningAngle + getNoise())).rotateAroundX(FastMath.toRadians(getNoise())),
|
||||
d1 - 1, recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.9).rotateAroundZ(FastMath.toRadians(- runningAngle + getNoise())).rotateAroundX(FastMath.toRadians(getNoise())),
|
||||
d1 - 1, recursions + 1);
|
||||
}
|
||||
|
||||
private int getNoise() {
|
||||
return super.getRandom().nextInt(90) - 45;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal.trees;
|
||||
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class SmallShatteredPillar extends FractalTree {
|
||||
/**
|
||||
* Instantiates a TreeGrower at an origin location.
|
||||
*
|
||||
* @param origin - The origin location.
|
||||
* @param random - The random object to use whilst generating the tree.
|
||||
*/
|
||||
public SmallShatteredPillar(Location origin, Random random) {
|
||||
super(origin, random);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows the tree in memory. Intended to be invoked from an async thread.
|
||||
*/
|
||||
@Override
|
||||
public void grow() {
|
||||
int h = super.getRandom().nextInt(5) + 5;
|
||||
for(int i = - h; i < h; i++) setBlock(super.getOrigin().clone().add(0, i, 0), Material.OBSIDIAN);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal.trees;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.TreeGeometry;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class SmallShatteredTree extends FractalTree {
|
||||
private final TreeGeometry geo;
|
||||
private final ProbabilityCollection<Material> bark = new ProbabilityCollection<Material>()
|
||||
.add(Material.OBSIDIAN, 1)
|
||||
.add(Material.BLACK_CONCRETE, 1);
|
||||
private final ProbabilityCollection<Material> leaves = new ProbabilityCollection<Material>()
|
||||
.add(Material.PURPLE_STAINED_GLASS, 1)
|
||||
.add(Material.MAGENTA_STAINED_GLASS, 1);
|
||||
|
||||
/**
|
||||
* Instantiates a TreeGrower at an origin location.
|
||||
*
|
||||
* @param origin - The origin location.
|
||||
* @param random - The random object to use whilst generating the tree.
|
||||
*/
|
||||
public SmallShatteredTree(Location origin, Random random) {
|
||||
super(origin, random);
|
||||
geo = new TreeGeometry(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows the tree in memory. Intended to be invoked from an async thread.
|
||||
*/
|
||||
@Override
|
||||
public void grow() {
|
||||
growBranch(super.getOrigin().clone(), new Vector(super.getRandom().nextInt(5) - 2, super.getRandom().nextInt(3) + 4, super.getRandom().nextInt(5) - 2), 1.5, 0);
|
||||
|
||||
}
|
||||
|
||||
private void growBranch(Location l1, Vector diff, double d1, int recursions) {
|
||||
if(recursions > 2) {
|
||||
geo.generateSphere(l1, leaves, 1 + super.getRandom().nextInt(2) + (3 - recursions), false);
|
||||
return;
|
||||
}
|
||||
if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI);
|
||||
int d = (int) diff.length();
|
||||
for(int i = 0; i < d; i++) {
|
||||
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), bark, FastMath.max((int) d1, 0), true);
|
||||
}
|
||||
double runningAngle = (double) 45 / (recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.7).rotateAroundX(FastMath.toRadians(runningAngle + getNoise())).rotateAroundZ(FastMath.toRadians(getNoise())),
|
||||
d1 - 1, recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.7).rotateAroundX(FastMath.toRadians(- runningAngle + getNoise())).rotateAroundZ(FastMath.toRadians(getNoise())),
|
||||
d1 - 1, recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.7).rotateAroundZ(FastMath.toRadians(runningAngle + getNoise())).rotateAroundX(FastMath.toRadians(getNoise())),
|
||||
d1 - 1, recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.7).rotateAroundZ(FastMath.toRadians(- runningAngle + getNoise())).rotateAroundX(FastMath.toRadians(getNoise())),
|
||||
d1 - 1, recursions + 1);
|
||||
}
|
||||
|
||||
private int getNoise() {
|
||||
return super.getRandom().nextInt(90) - 45;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal.trees;
|
||||
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.TreeGeometry;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class SpruceTree extends FractalTree {
|
||||
private final TreeGeometry geo;
|
||||
|
||||
/**
|
||||
* Instantiates a TreeGrower at an origin location.
|
||||
*
|
||||
* @param origin - The origin location.
|
||||
* @param random - The random object to use whilst generating the tree.
|
||||
*/
|
||||
public SpruceTree(Location origin, Random random) {
|
||||
super(origin, random);
|
||||
geo = new TreeGeometry(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows the tree in memory. Intended to be invoked from an async thread.
|
||||
*/
|
||||
@Override
|
||||
public void grow() {
|
||||
growTrunk(super.getOrigin().clone(), new Vector(0, 16 + super.getRandom().nextInt(5), 0));
|
||||
}
|
||||
|
||||
private void growTrunk(Location l1, Vector diff) {
|
||||
if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI);
|
||||
int d = (int) diff.length();
|
||||
int rad = 7;
|
||||
for(int i = 0; i < d; i++) {
|
||||
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), Material.SPRUCE_WOOD, (int) ((i > d * 0.65) ? 0.5 : 1.5), true);
|
||||
if(i > 3)
|
||||
geo.generateCylinder(l1.clone().add(diff.clone().multiply((double) i / d)), Material.SPRUCE_LEAVES, (int) (((6 - (i % 4))) * (1.25 - ((double) i / d))), 1, false);
|
||||
}
|
||||
setBlock(l1.clone().add(diff), Material.SPRUCE_LEAVES);
|
||||
setBlock(l1.clone().add(diff).add(0, 1, 0), Material.SPRUCE_LEAVES);
|
||||
}
|
||||
}
|
||||
64
src/main/java/com/dfsek/terra/api/gaea/util/FastRandom.java
Normal file
64
src/main/java/com/dfsek/terra/api/gaea/util/FastRandom.java
Normal file
@@ -0,0 +1,64 @@
|
||||
package com.dfsek.terra.api.gaea.util;
|
||||
|
||||
import org.apache.commons.rng.core.source64.XoRoShiRo128PlusPlus;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.SplittableRandom;
|
||||
|
||||
public class FastRandom extends Random {
|
||||
|
||||
private XoRoShiRo128PlusPlus random;
|
||||
|
||||
public FastRandom() {
|
||||
super();
|
||||
SplittableRandom randomseed = new SplittableRandom();
|
||||
this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong());
|
||||
}
|
||||
|
||||
public FastRandom(long seed) {
|
||||
super(seed);
|
||||
SplittableRandom randomseed = new SplittableRandom(seed);
|
||||
this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean nextBoolean() {
|
||||
return random.nextBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextInt() {
|
||||
return random.nextInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float nextFloat() {
|
||||
return (float) random.nextDouble();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double nextDouble() {
|
||||
return random.nextDouble();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setSeed(long seed) {
|
||||
SplittableRandom randomseed = new SplittableRandom(seed);
|
||||
this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nextBytes(byte[] bytes) {
|
||||
random.nextBytes(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextInt(int bound) {
|
||||
return random.nextInt(bound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextLong() {
|
||||
return random.nextLong();
|
||||
}
|
||||
}
|
||||
1048
src/main/java/com/dfsek/terra/api/gaea/util/GlueList.java
Normal file
1048
src/main/java/com/dfsek/terra/api/gaea/util/GlueList.java
Normal file
File diff suppressed because it is too large
Load Diff
38
src/main/java/com/dfsek/terra/api/gaea/util/JarUtil.java
Normal file
38
src/main/java/com/dfsek/terra/api/gaea/util/JarUtil.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package com.dfsek.terra.api.gaea.util;
|
||||
|
||||
import com.dfsek.terra.api.gaea.Debug;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class JarUtil {
|
||||
public static void copyResourcesToDirectory(JarFile fromJar, String sourceDir, String destDir) throws IOException {
|
||||
for(Enumeration<JarEntry> entries = fromJar.entries(); entries.hasMoreElements(); ) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
if(entry.getName().startsWith(sourceDir + "/") && ! entry.isDirectory()) {
|
||||
File dest = new File(destDir + File.separator + entry.getName().substring(sourceDir.length() + 1));
|
||||
if(dest.exists()) continue;
|
||||
File parent = dest.getParentFile();
|
||||
if(parent != null) {
|
||||
parent.mkdirs();
|
||||
}
|
||||
Debug.info("Output does not already exist. Creating... ");
|
||||
try(FileOutputStream out = new FileOutputStream(dest); InputStream in = fromJar.getInputStream(entry)) {
|
||||
byte[] buffer = new byte[(8192)];
|
||||
|
||||
int s;
|
||||
while((s = in.read(buffer)) > 0) {
|
||||
out.write(buffer, 0, s);
|
||||
}
|
||||
} catch(IOException e) {
|
||||
throw new IOException("Could not copy asset from jar file", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.dfsek.terra.api.gaea.util;
|
||||
|
||||
import com.dfsek.terra.api.gaea.serial.MovedObjectInputStream;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class SerializationUtil {
|
||||
public static Object fromFile(File f) throws IOException, ClassNotFoundException {
|
||||
ObjectInputStream ois = new MovedObjectInputStream(new FileInputStream(f), "com.dfsek.betterend.gaea", "com.dfsek.terra.api.gaea"); // Backwards compat with old BetterEnd shade location
|
||||
Object o = ois.readObject();
|
||||
ois.close();
|
||||
return o;
|
||||
}
|
||||
|
||||
public static void toFile(Serializable o, File f) throws IOException {
|
||||
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
|
||||
oos.writeObject(o);
|
||||
oos.close();
|
||||
}
|
||||
}
|
||||
46
src/main/java/com/dfsek/terra/api/gaea/util/WorldUtil.java
Normal file
46
src/main/java/com/dfsek/terra/api/gaea/util/WorldUtil.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package com.dfsek.terra.api.gaea.util;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class WorldUtil {
|
||||
public static int getHighestValidSpawnAt(Chunk chunk, int x, int z) {
|
||||
int y;
|
||||
for(y = chunk.getWorld().getMaxHeight() - 1; (chunk.getBlock(x, y, z).getType() != Material.GRASS_BLOCK
|
||||
&& chunk.getBlock(x, y, z).getType() != Material.GRAVEL
|
||||
&& chunk.getBlock(x, y, z).getType() != Material.PODZOL
|
||||
&& chunk.getBlock(x, y, z).getType() != Material.END_STONE
|
||||
&& chunk.getBlock(x, y, z).getType() != Material.DIRT
|
||||
&& chunk.getBlock(x, y, z).getType() != Material.STONE
|
||||
&& chunk.getBlock(x, y, z).getType() != Material.SAND
|
||||
&& chunk.getBlock(x, y, z).getType() != Material.RED_SAND
|
||||
&& chunk.getBlock(x, y, z).getType() != Material.COARSE_DIRT) && y > 0; y--)
|
||||
;
|
||||
return y;
|
||||
}
|
||||
|
||||
public static int getHighestBlockAt(Chunk chunk, int x, int z) {
|
||||
int y;
|
||||
for(y = chunk.getWorld().getMaxHeight() - 1; (chunk.getBlock(x, y, z).getType().isAir()) && y > 0; y--) ;
|
||||
return y;
|
||||
}
|
||||
|
||||
public static List<Location> getLocationListBetween(Location loc1, Location loc2) {
|
||||
int lowX = FastMath.min(loc1.getBlockX(), loc2.getBlockX());
|
||||
int lowY = FastMath.min(loc1.getBlockY(), loc2.getBlockY());
|
||||
int lowZ = FastMath.min(loc1.getBlockZ(), loc2.getBlockZ());
|
||||
List<Location> locs = new GlueList<>();
|
||||
for(int x = 0; x <= FastMath.abs(loc1.getBlockX() - loc2.getBlockX()); x++) {
|
||||
for(int y = 0; y <= FastMath.abs(loc1.getBlockY() - loc2.getBlockY()); y++) {
|
||||
for(int z = 0; z <= FastMath.abs(loc1.getBlockZ() - loc2.getBlockZ()); z++) {
|
||||
locs.add(new Location(loc1.getWorld(), (double) lowX + x, (double) lowY + y, (double) lowZ + z));
|
||||
}
|
||||
}
|
||||
}
|
||||
return locs;
|
||||
}
|
||||
}
|
||||
14
src/main/java/com/dfsek/terra/api/gaea/world/Flora.java
Normal file
14
src/main/java/com/dfsek/terra/api/gaea/world/Flora.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.dfsek.terra.api.gaea.world;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.Range;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface Flora {
|
||||
List<Block> getValidSpawnsAt(Chunk chunk, int x, int z, Range check);
|
||||
|
||||
boolean plant(Location l);
|
||||
}
|
||||
86
src/main/java/com/dfsek/terra/api/gaea/world/FloraType.java
Normal file
86
src/main/java/com/dfsek/terra/api/gaea/world/FloraType.java
Normal file
@@ -0,0 +1,86 @@
|
||||
package com.dfsek.terra.api.gaea.world;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.Range;
|
||||
import com.dfsek.terra.api.gaea.util.GlueList;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.bukkit.Bukkit;
|
||||
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 java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public enum FloraType implements Flora {
|
||||
TALL_GRASS(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:tall_grass[half=lower]"), Bukkit.createBlockData("minecraft:tall_grass[half=upper]")),
|
||||
TALL_FERN(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:large_fern[half=lower]"), Bukkit.createBlockData("minecraft:large_fern[half=upper]")),
|
||||
SUNFLOWER(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:sunflower[half=lower]"), Bukkit.createBlockData("minecraft:sunflower[half=upper]")),
|
||||
ROSE_BUSH(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:rose_bush[half=lower]"), Bukkit.createBlockData("minecraft:rose_bush[half=upper]")),
|
||||
LILAC(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:lilac[half=lower]"), Bukkit.createBlockData("minecraft:lilac[half=upper]")),
|
||||
PEONY(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:peony[half=lower]"), Bukkit.createBlockData("minecraft:peony[half=upper]")),
|
||||
GRASS(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:grass")),
|
||||
FERN(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:fern")),
|
||||
AZURE_BLUET(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:azure_bluet")),
|
||||
LILY_OF_THE_VALLEY(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:lily_of_the_valley")),
|
||||
BLUE_ORCHID(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:blue_orchid")),
|
||||
POPPY(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:poppy")),
|
||||
DANDELION(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:dandelion")),
|
||||
WITHER_ROSE(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:wither_rose")),
|
||||
DEAD_BUSH(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL, Material.SAND, Material.RED_SAND,
|
||||
Material.TERRACOTTA, Material.BLACK_TERRACOTTA, Material.BLUE_TERRACOTTA, Material.BROWN_TERRACOTTA, Material.CYAN_TERRACOTTA, Material.GRAY_TERRACOTTA,
|
||||
Material.GREEN_TERRACOTTA, Material.LIGHT_BLUE_TERRACOTTA, Material.LIGHT_GRAY_TERRACOTTA, Material.LIME_TERRACOTTA, Material.MAGENTA_TERRACOTTA,
|
||||
Material.ORANGE_TERRACOTTA, Material.PINK_TERRACOTTA, Material.PURPLE_TERRACOTTA, Material.RED_TERRACOTTA, Material.RED_TERRACOTTA, Material.WHITE_TERRACOTTA,
|
||||
Material.YELLOW_TERRACOTTA), Bukkit.createBlockData("minecraft:dead_bush")),
|
||||
RED_TULIP(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:red_tulip")),
|
||||
ORANGE_TULIP(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:orange_tulip")),
|
||||
WHITE_TULIP(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:white_tulip")),
|
||||
PINK_TULIP(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:pink_tulip")),
|
||||
OXEYE_DAISY(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:oxeye_daisy")),
|
||||
ALLIUM(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:allium")),
|
||||
CORNFLOWER(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL), Bukkit.createBlockData("minecraft:cornflower")),
|
||||
LILY_PAD(Sets.newHashSet(Material.WATER), Bukkit.createBlockData("minecraft:lily_pad")),
|
||||
RED_MUSHROOM(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL, Material.DIRT, Material.STONE, Material.NETHERRACK, Material.MYCELIUM), Bukkit.createBlockData("minecraft:red_mushroom")),
|
||||
BROWN_MUSHROOM(Sets.newHashSet(Material.GRASS_BLOCK, Material.PODZOL, Material.DIRT, Material.STONE, Material.NETHERRACK, Material.MYCELIUM), Bukkit.createBlockData("minecraft:brown_mushroom")),
|
||||
;
|
||||
|
||||
private final List<BlockData> data = new GlueList<>();
|
||||
|
||||
private final Set<Material> spawns;
|
||||
|
||||
FloraType(Set<Material> validSpawns, BlockData... type) {
|
||||
data.addAll(Arrays.asList(type));
|
||||
this.spawns = validSpawns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Block> getValidSpawnsAt(Chunk chunk, int x, int z, Range check) {
|
||||
List<Block> blocks = new GlueList<>();
|
||||
for(int y : check) {
|
||||
Block block = chunk.getBlock(x, y, z);
|
||||
if(spawns.contains(block.getType()) && valid(block)) {
|
||||
blocks.add(chunk.getBlock(x, y, z));
|
||||
}
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
private boolean valid(Block block) {
|
||||
for(int i = 1; i < data.size() + 1; i++) {
|
||||
block = block.getRelative(BlockFace.UP);
|
||||
if(!block.isEmpty()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean plant(Location l) {
|
||||
for(int i = 1; i < data.size() + 1; i++) {
|
||||
l.clone().add(0, i, 0).getBlock().setBlockData(data.get(i - 1), false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
21
src/main/java/com/dfsek/terra/api/gaea/world/Ore.java
Executable file
21
src/main/java/com/dfsek/terra/api/gaea/world/Ore.java
Executable file
@@ -0,0 +1,21 @@
|
||||
package com.dfsek.terra.api.gaea.world;
|
||||
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
public class Ore {
|
||||
private final int contChance;
|
||||
private final BlockData oreMaterial;
|
||||
|
||||
public Ore(BlockData oreMaterial, int contChance) {
|
||||
this.contChance = contChance;
|
||||
this.oreMaterial = oreMaterial;
|
||||
}
|
||||
|
||||
public int getContChance() {
|
||||
return contChance;
|
||||
}
|
||||
|
||||
public BlockData getType() {
|
||||
return oreMaterial;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.dfsek.terra.api.gaea.world.carving;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.MathUtil;
|
||||
import com.dfsek.terra.api.gaea.util.FastRandom;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public abstract class Carver {
|
||||
private final int minY;
|
||||
private final int maxY;
|
||||
private final double sixtyFourSq = FastMath.pow(64, 2);
|
||||
private int carvingRadius = 4;
|
||||
|
||||
public Carver(int minY, int maxY) {
|
||||
this.minY = minY;
|
||||
this.maxY = maxY;
|
||||
}
|
||||
|
||||
public void carve(int chunkX, int chunkZ, World w, BiConsumer<Vector, CarvingType> consumer) {
|
||||
for(int x = chunkX - carvingRadius; x <= chunkX + carvingRadius; x++) {
|
||||
for(int z = chunkZ - carvingRadius; z <= chunkZ + carvingRadius; z++) {
|
||||
if(isChunkCarved(w, x, z, new FastRandom(MathUtil.hashToLong(this.getClass().getName() + "_" + x + "&" + z)))) {
|
||||
long seed = MathUtil.getCarverChunkSeed(x, z, w.getSeed());
|
||||
Random r = new FastRandom(seed);
|
||||
Worm carving = getWorm(seed, new Vector((x << 4) + r.nextInt(16), r.nextInt(maxY - minY + 1) + minY, (z << 4) + r.nextInt(16)));
|
||||
Vector origin = carving.getOrigin();
|
||||
for(int i = 0; i < carving.getLength(); i++) {
|
||||
carving.step();
|
||||
if(carving.getRunning().clone().setY(0).distanceSquared(origin.clone().setY(0)) > sixtyFourSq)
|
||||
break;
|
||||
if(FastMath.floorDiv(origin.getBlockX(), 16) != chunkX && FastMath.floorDiv(origin.getBlockZ(), 16) != chunkZ)
|
||||
continue;
|
||||
carving.getPoint().carve(chunkX, chunkZ, consumer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getCarvingRadius() {
|
||||
return carvingRadius;
|
||||
}
|
||||
|
||||
public void setCarvingRadius(int carvingRadius) {
|
||||
this.carvingRadius = carvingRadius;
|
||||
}
|
||||
|
||||
public abstract Worm getWorm(long seed, Vector l);
|
||||
|
||||
public abstract boolean isChunkCarved(World w, int chunkX, int chunkZ, Random r);
|
||||
|
||||
public enum CarvingType {
|
||||
CENTER, WALL, TOP, BOTTOM
|
||||
}
|
||||
}
|
||||
119
src/main/java/com/dfsek/terra/api/gaea/world/carving/Worm.java
Normal file
119
src/main/java/com/dfsek/terra/api/gaea/world/carving/Worm.java
Normal file
@@ -0,0 +1,119 @@
|
||||
package com.dfsek.terra.api.gaea.world.carving;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public abstract class Worm {
|
||||
private final Random r;
|
||||
private final Vector origin;
|
||||
private final Vector running;
|
||||
private final int length;
|
||||
private int topCut = 0;
|
||||
private int bottomCut = 0;
|
||||
private int[] radius = new int[] {0, 0, 0};
|
||||
|
||||
public Worm(int length, Random r, Vector origin) {
|
||||
this.r = r;
|
||||
this.length = length;
|
||||
this.origin = origin;
|
||||
this.running = origin;
|
||||
}
|
||||
|
||||
public void setBottomCut(int bottomCut) {
|
||||
this.bottomCut = bottomCut;
|
||||
}
|
||||
|
||||
public void setTopCut(int topCut) {
|
||||
this.topCut = topCut;
|
||||
}
|
||||
|
||||
public Vector getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public Vector getRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
public WormPoint getPoint() {
|
||||
return new WormPoint(running, radius, topCut, bottomCut);
|
||||
}
|
||||
|
||||
public int[] getRadius() {
|
||||
return radius;
|
||||
}
|
||||
|
||||
public void setRadius(int[] radius) {
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
public Random getRandom() {
|
||||
return r;
|
||||
}
|
||||
|
||||
public abstract void step();
|
||||
|
||||
public static class WormPoint {
|
||||
private final Vector origin;
|
||||
private final int topCut;
|
||||
private final int bottomCut;
|
||||
private final int[] rad;
|
||||
|
||||
public WormPoint(Vector origin, int[] rad, int topCut, int bottomCut) {
|
||||
this.origin = origin;
|
||||
this.rad = rad;
|
||||
this.topCut = topCut;
|
||||
this.bottomCut = bottomCut;
|
||||
}
|
||||
|
||||
private static double ellipseEquation(int x, int y, int z, double xr, double yr, double zr) {
|
||||
return (FastMath.pow2(x) / FastMath.pow2(xr + 0.5D)) + (FastMath.pow2(y) / FastMath.pow2(yr + 0.5D)) + (FastMath.pow2(z) / FastMath.pow2(zr + 0.5D));
|
||||
}
|
||||
|
||||
public Vector getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public int getRadius(int index) {
|
||||
return rad[index];
|
||||
}
|
||||
|
||||
public void carve(int chunkX, int chunkZ, BiConsumer<Vector, Carver.CarvingType> consumer) {
|
||||
int xRad = getRadius(0);
|
||||
int yRad = getRadius(1);
|
||||
int zRad = getRadius(2);
|
||||
int originX = (chunkX << 4);
|
||||
int originZ = (chunkZ << 4);
|
||||
for(int x = -xRad - 1; x <= xRad + 1; x++) {
|
||||
if(!(FastMath.floorDiv(origin.getBlockX() + x, 16) == chunkX)) continue;
|
||||
for(int z = -zRad - 1; z <= zRad + 1; z++) {
|
||||
if(!(FastMath.floorDiv(origin.getBlockZ() + z, 16) == chunkZ)) continue;
|
||||
for(int y = -yRad - 1; y <= yRad + 1; y++) {
|
||||
Vector position = origin.clone().add(new Vector(x, y, z));
|
||||
if(position.getY() < 0 || position.getY() > 255) continue;
|
||||
double eq = ellipseEquation(x, y, z, xRad, yRad, zRad);
|
||||
if(eq <= 1 &&
|
||||
y >= -yRad - 1 + bottomCut && y <= yRad + 1 - topCut) {
|
||||
consumer.accept(new Vector(position.getBlockX() - originX, position.getBlockY(), position.getBlockZ() - originZ), Carver.CarvingType.CENTER);
|
||||
} else if(eq <= 1.5) {
|
||||
Carver.CarvingType type = Carver.CarvingType.WALL;
|
||||
if(y <= -yRad - 1 + bottomCut) {
|
||||
type = Carver.CarvingType.BOTTOM;
|
||||
} else if(y >= yRad + 1 - topCut) {
|
||||
type = Carver.CarvingType.TOP;
|
||||
}
|
||||
consumer.accept(new Vector(position.getBlockX() - originX, position.getBlockY(), position.getBlockZ() - originZ), type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.dfsek.terra.api.gaea.world.palette;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.FastNoiseLite;
|
||||
import com.dfsek.terra.api.gaea.math.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.gaea.util.GlueList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* A class representation of a "slice" of the world.
|
||||
* Used to get a section of blocks, based on the depth at which they are found.
|
||||
*/
|
||||
public abstract class Palette<E> {
|
||||
private final List<PaletteLayer<E>> pallet = new GlueList<>();
|
||||
|
||||
/**
|
||||
* Constructs a blank palette.
|
||||
*/
|
||||
public Palette() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a material to the palette, for a number of layers.
|
||||
*
|
||||
* @param m - The material to add to the palette.
|
||||
* @param layers - The number of layers the material occupies.
|
||||
* @return - BlockPalette instance for chaining.
|
||||
*/
|
||||
public com.dfsek.terra.api.gaea.world.palette.Palette<E> add(E m, int layers) {
|
||||
for(int i = 0; i < layers; i++) {
|
||||
pallet.add(new PaletteLayer<>(m));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a ProbabilityCollection to the palette, for a number of layers.
|
||||
*
|
||||
* @param m - The ProbabilityCollection to add to the palette.
|
||||
* @param layers - The number of layers the material occupies.
|
||||
* @return - BlockPalette instance for chaining.
|
||||
*/
|
||||
public com.dfsek.terra.api.gaea.world.palette.Palette<E> add(ProbabilityCollection<E> m, int layers) {
|
||||
for(int i = 0; i < layers; i++) {
|
||||
pallet.add(new PaletteLayer<>(m));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a material from the palette, at a given layer.
|
||||
*
|
||||
* @param layer - The layer at which to fetch the material.
|
||||
* @return BlockData - The material fetched.
|
||||
*/
|
||||
public abstract E get(int layer, int x, int z);
|
||||
|
||||
|
||||
public int getSize() {
|
||||
return pallet.size();
|
||||
}
|
||||
|
||||
public List<PaletteLayer<E>> getLayers() {
|
||||
return pallet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representation of a layer of a BlockPalette.
|
||||
*/
|
||||
public static class PaletteLayer<E> {
|
||||
private final boolean col; // Is layer using a collection?
|
||||
private ProbabilityCollection<E> collection;
|
||||
private E m;
|
||||
|
||||
/**
|
||||
* Constructs a PaletteLayer with a ProbabilityCollection of materials and a number of layers.
|
||||
*
|
||||
* @param type - The collection of materials to choose from.
|
||||
*/
|
||||
public PaletteLayer(ProbabilityCollection<E> type) {
|
||||
this.col = true;
|
||||
this.collection = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PaletteLayer with a single Material and a number of layers.
|
||||
*
|
||||
* @param type - The material to use.
|
||||
*/
|
||||
public PaletteLayer(E type) {
|
||||
this.col = false;
|
||||
this.m = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a material from the layer.
|
||||
*
|
||||
* @return Material - the material..
|
||||
*/
|
||||
public E get(Random random) {
|
||||
if(col) return this.collection.get(random);
|
||||
return m;
|
||||
}
|
||||
|
||||
public E get(FastNoiseLite random, int x, int z) {
|
||||
if(col) return this.collection.get(random, x, z);
|
||||
return m;
|
||||
}
|
||||
|
||||
public ProbabilityCollection<E> getCollection() {
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.dfsek.terra.api.gaea.world.palette;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class RandomPalette<E> extends Palette<E> {
|
||||
private final Random r;
|
||||
|
||||
public RandomPalette(Random r) {
|
||||
this.r = r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(int layer, int x, int z) {
|
||||
if(layer > this.getSize()) return this.getLayers().get(this.getLayers().size() - 1).get(r);
|
||||
List<PaletteLayer<E>> pl = getLayers();
|
||||
if(layer >= pl.size()) return pl.get(pl.size() - 1).get(r);
|
||||
return pl.get(layer).get(r);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.dfsek.terra.api.gaea.world.palette;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.FastNoiseLite;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SimplexPalette<E> extends Palette<E> {
|
||||
private final FastNoiseLite r;
|
||||
|
||||
public SimplexPalette(FastNoiseLite r) {
|
||||
this.r = r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(int layer, int x, int z) {
|
||||
if(layer > this.getSize()) return this.getLayers().get(this.getLayers().size() - 1).get(r, x, z);
|
||||
List<PaletteLayer<E>> pl = getLayers();
|
||||
if(layer >= pl.size()) return pl.get(pl.size() - 1).get(r, x, z);
|
||||
return pl.get(layer).get(r, x, z);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,27 @@
|
||||
package com.dfsek.terra.api.generic.generator;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ChunkGenerator {
|
||||
public boolean isParallelCapable() {
|
||||
return false;
|
||||
}
|
||||
public boolean shouldGenerateCaves() {
|
||||
return false;
|
||||
}
|
||||
public boolean shouldGenerateDecorations() {
|
||||
return false;
|
||||
}
|
||||
public boolean shouldGenerateMobs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldGenerateStructures() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<BlockPopulator> getDefaultPopulators() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.dfsek.terra.async;
|
||||
|
||||
import com.dfsek.terra.Terra;
|
||||
import com.dfsek.terra.api.gaea.biome.Biome;
|
||||
import com.dfsek.terra.api.gaea.generation.GenerationPhase;
|
||||
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.dfsek.terra.async;
|
||||
|
||||
import com.dfsek.terra.Terra;
|
||||
import com.dfsek.terra.api.gaea.util.FastRandom;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
|
||||
import com.dfsek.terra.generation.items.TerraStructure;
|
||||
@@ -11,7 +12,6 @@ import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package com.dfsek.terra.biome;
|
||||
|
||||
import com.dfsek.terra.api.gaea.biome.BiomeGrid;
|
||||
import com.dfsek.terra.api.gaea.biome.NormalizationUtil;
|
||||
import com.dfsek.terra.api.gaea.math.FastNoiseLite;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.base.ConfigPackTemplate;
|
||||
import com.dfsek.terra.image.ImageLoader;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.polydev.gaea.biome.BiomeGrid;
|
||||
import org.polydev.gaea.biome.NormalizationUtil;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
package com.dfsek.terra.biome;
|
||||
|
||||
import com.dfsek.terra.api.gaea.biome.Biome;
|
||||
import com.dfsek.terra.api.gaea.biome.Decorator;
|
||||
import com.dfsek.terra.api.gaea.biome.Generator;
|
||||
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.bukkit.World;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.biome.Decorator;
|
||||
import org.polydev.gaea.biome.Generator;
|
||||
import org.polydev.gaea.structures.features.Feature;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class representing a config-defined biome
|
||||
@@ -54,15 +51,6 @@ public class UserDefinedBiome implements Biome {
|
||||
return gen.build(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of Structure Features to be applied to all structures in the biome.
|
||||
*
|
||||
* @return List<Feature> - The list of Features.
|
||||
*/
|
||||
@Override
|
||||
public List<Feature> getStructureFeatures() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Decorator instance containing information about the population in the biome.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.dfsek.terra.biome.grid;
|
||||
|
||||
import com.dfsek.terra.api.gaea.biome.Biome;
|
||||
import com.dfsek.terra.api.gaea.biome.BiomeGrid;
|
||||
import com.dfsek.terra.api.gaea.generation.GenerationPhase;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.biome.BiomeGrid;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
|
||||
/**
|
||||
* BiomeGrid implementation that holds a single biome.
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package com.dfsek.terra.biome.grid;
|
||||
|
||||
import com.dfsek.terra.api.gaea.biome.Biome;
|
||||
import com.dfsek.terra.api.gaea.biome.BiomeGrid;
|
||||
import com.dfsek.terra.api.gaea.biome.NormalizationUtil;
|
||||
import com.dfsek.terra.api.gaea.generation.GenerationPhase;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.base.ConfigPackTemplate;
|
||||
import com.dfsek.terra.image.ImageLoader;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.biome.BiomeGrid;
|
||||
import org.polydev.gaea.biome.NormalizationUtil;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
|
||||
public class UserDefinedGrid extends BiomeGrid {
|
||||
private final ImageLoader imageLoader;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.dfsek.terra.biome.grid.master;
|
||||
|
||||
import com.dfsek.terra.api.gaea.biome.BiomeGrid;
|
||||
import com.dfsek.terra.biome.grid.UserDefinedGrid;
|
||||
import org.bukkit.World;
|
||||
import org.polydev.gaea.biome.BiomeGrid;
|
||||
|
||||
public abstract class TerraBiomeGrid extends BiomeGrid {
|
||||
public TerraBiomeGrid(World w, double freq1, double freq2, int sizeX, int sizeZ) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.dfsek.terra.biome.grid.master;
|
||||
|
||||
import com.dfsek.terra.api.gaea.biome.Biome;
|
||||
import com.dfsek.terra.api.gaea.biome.BiomeGrid;
|
||||
import com.dfsek.terra.api.gaea.generation.GenerationPhase;
|
||||
import com.dfsek.terra.api.generic.world.vector.Vector2;
|
||||
import com.dfsek.terra.biome.BiomeZone;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
@@ -11,9 +14,6 @@ import com.dfsek.terra.config.base.ConfigPackTemplate;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.biome.BiomeGrid;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
|
||||
public class TerraRadialBiomeGrid extends TerraBiomeGrid {
|
||||
private static final int failNum = 0;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.dfsek.terra.biome.grid.master;
|
||||
|
||||
import com.dfsek.terra.api.gaea.biome.Biome;
|
||||
import com.dfsek.terra.api.gaea.generation.GenerationPhase;
|
||||
import com.dfsek.terra.api.generic.world.vector.Vector2;
|
||||
import com.dfsek.terra.biome.BiomeZone;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
@@ -10,8 +12,6 @@ import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.base.ConfigPackTemplate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
|
||||
public class TerraStandardBiomeGrid extends TerraBiomeGrid {
|
||||
private static final int failNum = 0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.dfsek.terra.biome.palette;
|
||||
|
||||
import com.dfsek.terra.api.gaea.world.palette.Palette;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
|
||||
public class PaletteHolder {
|
||||
private final Palette<BlockData>[] palettes;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.dfsek.terra.biome.palette;
|
||||
|
||||
import com.dfsek.terra.api.gaea.world.palette.Palette;
|
||||
import com.dfsek.terra.util.PaletteUtil;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.dfsek.terra.biome.palette;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.ProbabilityCollection;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.math.ProbabilityCollection;
|
||||
|
||||
public class PaletteLayer {
|
||||
private final ProbabilityCollection<BlockData> layer;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.dfsek.terra.biome.palette;
|
||||
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
import com.dfsek.terra.api.gaea.world.palette.Palette;
|
||||
|
||||
public class SinglePalette<E> extends Palette<E> {
|
||||
private final E item;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.dfsek.terra.biome.postprocessing;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.FastNoiseLite;
|
||||
import com.dfsek.terra.api.generic.world.vector.Vector2;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
|
||||
/**
|
||||
* Offset a coordinate pair by an amount.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.dfsek.terra.biome.postprocessing;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.FastNoiseLite;
|
||||
import net.jafama.FastMath;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
|
||||
/**
|
||||
* Class to hold noise function to determine erosion.
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
package com.dfsek.terra.carving;
|
||||
|
||||
import com.dfsek.terra.Terra;
|
||||
import com.dfsek.terra.api.gaea.biome.Biome;
|
||||
import com.dfsek.terra.api.gaea.generation.GenerationPhase;
|
||||
import com.dfsek.terra.api.gaea.math.MathUtil;
|
||||
import com.dfsek.terra.api.gaea.util.FastRandom;
|
||||
import com.dfsek.terra.api.gaea.util.GlueList;
|
||||
import com.dfsek.terra.api.gaea.world.carving.Worm;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.math.MathUtil;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
import org.polydev.gaea.util.GlueList;
|
||||
import org.polydev.gaea.world.carving.Worm;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.dfsek.terra.carving;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.ProbabilityCollection;
|
||||
import com.dfsek.terra.util.MaterialSet;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.polydev.gaea.math.ProbabilityCollection;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.dfsek.terra.carving;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.FastNoiseLite;
|
||||
import com.dfsek.terra.api.gaea.math.MathUtil;
|
||||
import com.dfsek.terra.api.gaea.util.FastRandom;
|
||||
import com.dfsek.terra.procgen.GridSpawn;
|
||||
import com.dfsek.terra.procgen.voxel.DeformedSphere;
|
||||
import com.dfsek.terra.procgen.voxel.Tube;
|
||||
@@ -7,9 +10,6 @@ import com.dfsek.terra.procgen.voxel.VoxelGeometry;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
import org.polydev.gaea.math.MathUtil;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package com.dfsek.terra.carving;
|
||||
|
||||
import com.dfsek.terra.Terra;
|
||||
import com.dfsek.terra.api.gaea.generation.GenerationPhase;
|
||||
import com.dfsek.terra.api.gaea.math.Range;
|
||||
import com.dfsek.terra.api.gaea.util.FastRandom;
|
||||
import com.dfsek.terra.api.gaea.world.carving.Carver;
|
||||
import com.dfsek.terra.api.gaea.world.carving.Worm;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.config.templates.BiomeTemplate;
|
||||
import com.dfsek.terra.config.templates.CarverTemplate;
|
||||
@@ -8,11 +13,6 @@ import com.dfsek.terra.math.RandomFunction;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.math.Range;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
import org.polydev.gaea.world.carving.Carver;
|
||||
import org.polydev.gaea.world.carving.Worm;
|
||||
import parsii.eval.Expression;
|
||||
import parsii.eval.Parser;
|
||||
import parsii.eval.Scope;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package com.dfsek.terra.command;
|
||||
|
||||
import com.dfsek.terra.api.gaea.command.WorldCommand;
|
||||
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.command.WorldCommand;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class FixChunkCommand extends WorldCommand {
|
||||
public FixChunkCommand(org.polydev.gaea.command.Command parent) {
|
||||
public FixChunkCommand(com.dfsek.terra.api.gaea.command.Command parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class FixChunkCommand extends WorldCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<org.polydev.gaea.command.Command> getSubCommands() {
|
||||
public List<com.dfsek.terra.api.gaea.command.Command> getSubCommands() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package com.dfsek.terra.command;
|
||||
|
||||
import com.dfsek.terra.api.gaea.command.WorldCommand;
|
||||
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.command.WorldCommand;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class OreCommand extends WorldCommand {
|
||||
public OreCommand(org.polydev.gaea.command.Command parent) {
|
||||
public OreCommand(com.dfsek.terra.api.gaea.command.Command parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class OreCommand extends WorldCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<org.polydev.gaea.command.Command> getSubCommands() {
|
||||
public List<com.dfsek.terra.api.gaea.command.Command> getSubCommands() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user