mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-13 11:16:05 +00:00
Look ma, no Bukkit API in the core package
This commit is contained in:
@@ -1,19 +0,0 @@
|
||||
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 com.dfsek.terra.api.generic.world.World;
|
||||
|
||||
public class TerraProfiler extends WorldProfiler {
|
||||
public TerraProfiler(World w) {
|
||||
super(w);
|
||||
this
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "FloraTime")
|
||||
.addMeasurement(new Measurement(10000000, DataType.PERIOD_MILLISECONDS), "TreeTime")
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "OreTime")
|
||||
.addMeasurement(new Measurement(5000000, DataType.PERIOD_MILLISECONDS), "CaveTime")
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "StructureTime")
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "ElevationTime");
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
package com.dfsek.terra;
|
||||
|
||||
import com.dfsek.terra.api.gaea.biome.BiomeGrid;
|
||||
import com.dfsek.terra.api.generic.TerraPlugin;
|
||||
import com.dfsek.terra.api.generic.world.World;
|
||||
import com.dfsek.terra.api.implementations.bukkit.generator.BukkitChunkGenerator;
|
||||
import com.dfsek.terra.biome.BiomeZone;
|
||||
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
|
||||
import com.dfsek.terra.biome.grid.master.TerraRadialBiomeGrid;
|
||||
import com.dfsek.terra.biome.grid.master.TerraStandardBiomeGrid;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.base.ConfigPackTemplate;
|
||||
import com.dfsek.terra.config.builder.biomegrid.BiomeGridBuilder;
|
||||
import com.dfsek.terra.debug.Debug;
|
||||
|
||||
public class TerraWorld {
|
||||
private final TerraBiomeGrid grid;
|
||||
private final BiomeZone zone;
|
||||
private final ConfigPack config;
|
||||
private boolean safe;
|
||||
private final TerraProfiler profiler;
|
||||
|
||||
|
||||
public TerraWorld(World w, ConfigPack c, TerraPlugin main) {
|
||||
safe = true;
|
||||
config = c;
|
||||
profiler = new TerraProfiler(w);
|
||||
|
||||
ConfigPackTemplate template = config.getTemplate();
|
||||
|
||||
int zoneSize = template.getGrids().size();
|
||||
|
||||
BiomeGrid[] definedGrids = new BiomeGrid[zoneSize];
|
||||
for(int i = 0; i < zoneSize; i++) {
|
||||
String partName = template.getGrids().get(i);
|
||||
try {
|
||||
BiomeGridBuilder g = config.getBiomeGrid(partName);
|
||||
BiomeGrid b = g.build(w, c);
|
||||
definedGrids[i] = b;
|
||||
} catch(NullPointerException e) {
|
||||
safe = false;
|
||||
Debug.stack(e);
|
||||
main.getLogger().severe("No such BiomeGrid " + partName);
|
||||
main.getLogger().severe("Please check configuration files for errors. Configuration errors will have been reported during initialization.");
|
||||
main.getLogger().severe("ONLY report this to Terra if you are SURE your config is error-free.");
|
||||
main.getLogger().severe("Terrain will NOT generate properly at this point. Correct your config before using your server!");
|
||||
}
|
||||
}
|
||||
zone = new BiomeZone(w, c, definedGrids);
|
||||
|
||||
if(template.getGridType().equals(TerraBiomeGrid.Type.RADIAL)) {
|
||||
BiomeGrid internal = config.getBiomeGrid(template.getRadialInternalGrid()).build(w, c);
|
||||
grid = new TerraRadialBiomeGrid(w, template.getGridFreqX(), template.getGridFreqZ(), zone, config, template.getRadialGridRadius(), internal);
|
||||
} else grid = new TerraStandardBiomeGrid(w, template.getGridFreqX(), template.getGridFreqZ(), zone, config);
|
||||
}
|
||||
|
||||
public static boolean isTerraWorld(World w) {
|
||||
return w.getGenerator() instanceof BukkitChunkGenerator;
|
||||
}
|
||||
|
||||
public TerraBiomeGrid getGrid() {
|
||||
return grid;
|
||||
}
|
||||
|
||||
public ConfigPack getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public BiomeZone getZone() {
|
||||
return zone;
|
||||
}
|
||||
|
||||
public boolean isSafe() {
|
||||
return safe;
|
||||
}
|
||||
|
||||
public TerraProfiler getProfiler() {
|
||||
return profiler;
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.dfsek.terra.api;
|
||||
|
||||
import com.dfsek.tectonic.loading.TypeRegistry;
|
||||
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.biome.grid.master.TerraBiomeGrid;
|
||||
import com.dfsek.terra.biome.palette.PaletteHolder;
|
||||
import com.dfsek.terra.biome.palette.PaletteLayer;
|
||||
import com.dfsek.terra.carving.CarverPalette;
|
||||
import com.dfsek.terra.config.loaders.ImageLoaderLoader;
|
||||
import com.dfsek.terra.config.loaders.MaterialSetLoader;
|
||||
import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader;
|
||||
import com.dfsek.terra.config.loaders.RangeLoader;
|
||||
import com.dfsek.terra.config.loaders.config.FloraLayerLoader;
|
||||
import com.dfsek.terra.config.loaders.config.GridSpawnLoader;
|
||||
import com.dfsek.terra.config.loaders.config.NoiseBuilderLoader;
|
||||
import com.dfsek.terra.config.loaders.config.OreConfigLoader;
|
||||
import com.dfsek.terra.config.loaders.config.OreHolderLoader;
|
||||
import com.dfsek.terra.config.loaders.config.StructureFeatureLoader;
|
||||
import com.dfsek.terra.config.loaders.config.TreeLayerLoader;
|
||||
import com.dfsek.terra.config.loaders.palette.CarverPaletteLoader;
|
||||
import com.dfsek.terra.config.loaders.palette.PaletteHolderLoader;
|
||||
import com.dfsek.terra.config.loaders.palette.PaletteLayerLoader;
|
||||
import com.dfsek.terra.generation.config.NoiseBuilder;
|
||||
import com.dfsek.terra.generation.items.flora.FloraLayer;
|
||||
import com.dfsek.terra.generation.items.flora.TerraFlora;
|
||||
import com.dfsek.terra.generation.items.ores.Ore;
|
||||
import com.dfsek.terra.generation.items.ores.OreConfig;
|
||||
import com.dfsek.terra.generation.items.ores.OreHolder;
|
||||
import com.dfsek.terra.generation.items.tree.TreeLayer;
|
||||
import com.dfsek.terra.image.ImageLoader;
|
||||
import com.dfsek.terra.procgen.GridSpawn;
|
||||
import com.dfsek.terra.structure.features.Feature;
|
||||
import com.dfsek.terra.util.MaterialSet;
|
||||
import com.dfsek.terra.util.StructureTypeEnum;
|
||||
|
||||
public class GenericLoaders implements LoaderRegistrar {
|
||||
private final TerraPlugin main;
|
||||
|
||||
public GenericLoaders(TerraPlugin main) {
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(TypeRegistry registry) {
|
||||
registry.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader())
|
||||
.registerLoader(Range.class, new RangeLoader())
|
||||
.registerLoader(CarverPalette.class, new CarverPaletteLoader())
|
||||
.registerLoader(GridSpawn.class, new GridSpawnLoader())
|
||||
.registerLoader(PaletteHolder.class, new PaletteHolderLoader())
|
||||
.registerLoader(PaletteLayer.class, new PaletteLayerLoader())
|
||||
.registerLoader(FloraLayer.class, new FloraLayerLoader())
|
||||
.registerLoader(Ore.Type.class, (t, o, l) -> Ore.Type.valueOf((String) o))
|
||||
.registerLoader(OreConfig.class, new OreConfigLoader())
|
||||
.registerLoader(NoiseBuilder.class, new NoiseBuilderLoader())
|
||||
.registerLoader(TreeLayer.class, new TreeLayerLoader(main))
|
||||
.registerLoader(MaterialSet.class, new MaterialSetLoader())
|
||||
.registerLoader(OreHolder.class, new OreHolderLoader())
|
||||
.registerLoader(Feature.class, new StructureFeatureLoader())
|
||||
.registerLoader(ImageLoader.class, new ImageLoaderLoader())
|
||||
.registerLoader(TerraBiomeGrid.Type.class, (t, o, l) -> TerraBiomeGrid.Type.valueOf((String) o))
|
||||
.registerLoader(StructureTypeEnum.class, (t, o, l) -> StructureTypeEnum.valueOf((String) o))
|
||||
.registerLoader(ImageLoader.Channel.class, (t, o, l) -> ImageLoader.Channel.valueOf((String) o))
|
||||
.registerLoader(ImageLoader.Align.class, (t, o, l) -> ImageLoader.Align.valueOf((String) o))
|
||||
.registerLoader(TerraFlora.Search.class, (t, o, l) -> TerraFlora.Search.valueOf((String) o));
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.dfsek.terra.api;
|
||||
|
||||
import com.dfsek.tectonic.loading.TypeRegistry;
|
||||
|
||||
public interface LoaderRegistrar {
|
||||
void register(TypeRegistry registry);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea;
|
||||
|
||||
|
||||
import com.dfsek.terra.api.generic.world.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;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea;
|
||||
|
||||
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 Language getLanguage();
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
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.
|
||||
*/
|
||||
com.dfsek.terra.api.generic.world.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();
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.biome;
|
||||
|
||||
import com.dfsek.terra.api.gaea.generation.GenerationPhase;
|
||||
import com.dfsek.terra.api.gaea.math.FastNoiseLite;
|
||||
import com.dfsek.terra.api.generic.world.World;
|
||||
import com.dfsek.terra.api.generic.world.vector.Location;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
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();
|
||||
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.biome;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.Interpolator;
|
||||
import com.dfsek.terra.api.gaea.world.palette.Palette;
|
||||
import com.dfsek.terra.api.generic.world.World;
|
||||
import com.dfsek.terra.api.generic.world.block.BlockData;
|
||||
|
||||
public abstract class Generator {
|
||||
/**
|
||||
* Gets the 3D noise at a pair of coordinates using the provided FastNoiseLite instance.
|
||||
*
|
||||
* @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(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
@@ -1,111 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
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 {
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
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);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.command;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
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) {
|
||||
if(sender.getWorld().getGenerator() instanceof ChunkGenerator) { // TODO: implementation
|
||||
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);
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
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();
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
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("");
|
||||
}
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
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 com.dfsek.terra.api.generic.world.World;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
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 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.
|
||||
*/
|
||||
public ChunkInterpolator3(World w, int chunkX, int chunkZ, BiomeGrid grid) {
|
||||
this.xOrigin = chunkX << 4;
|
||||
this.zOrigin = chunkZ << 4;
|
||||
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(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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,61 +0,0 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.population;
|
||||
|
||||
|
||||
import com.dfsek.terra.api.generic.world.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;
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
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 com.dfsek.terra.api.generic.TerraPlugin;
|
||||
import com.dfsek.terra.api.generic.generator.TerraBlockPopulator;
|
||||
import com.dfsek.terra.api.generic.world.Chunk;
|
||||
import com.dfsek.terra.api.generic.world.World;
|
||||
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 implements TerraBlockPopulator {
|
||||
private final List<TerraBlockPopulator> attachedPopulators = new GlueList<>();
|
||||
private final HashSet<ChunkCoordinate> needsPop = new HashSet<>();
|
||||
private final TerraPlugin main;
|
||||
private WorldProfiler profiler;
|
||||
|
||||
public PopulationManager(TerraPlugin main) {
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
public void attach(TerraBlockPopulator populator) {
|
||||
this.attachedPopulators.add(populator);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("try")
|
||||
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(TerraBlockPopulator r : attachedPopulators) {
|
||||
r.populate(w, random, currentChunk);
|
||||
}
|
||||
needsPop.remove(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.profiler;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.World;
|
||||
import com.dfsek.terra.api.implementations.bukkit.generator.BukkitChunkGenerator;
|
||||
import com.dfsek.terra.api.implementations.bukkit.generator.BukkitChunkGeneratorWrapper;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
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 BukkitChunkGenerator))
|
||||
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;
|
||||
((BukkitChunkGeneratorWrapper) ((BukkitChunkGenerator) w.getGenerator()).getHandle()).getDelegate().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;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
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);
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
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 com.dfsek.terra.api.generic.world.vector.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.tree;
|
||||
|
||||
|
||||
import com.dfsek.terra.api.generic.world.block.MaterialData;
|
||||
import com.dfsek.terra.api.generic.world.vector.Location;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
public interface Tree {
|
||||
boolean plant(Location l, Random r);
|
||||
|
||||
Set<MaterialData> getSpawnable();
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.tree;
|
||||
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import com.dfsek.terra.api.generic.world.block.MaterialData;
|
||||
import com.dfsek.terra.api.generic.world.vector.Location;
|
||||
import com.dfsek.terra.api.implementations.bukkit.world.block.BukkitMaterialData;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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) {
|
||||
if(this.getVanillaTreeType() == null) {
|
||||
if(!spawnable.contains(l.subtract(0, 1, 0).getBlock().getType())) return false;
|
||||
FractalTree tree = getCustomTreeType().getTree(l, r);
|
||||
tree.grow();
|
||||
tree.plant();
|
||||
return true;
|
||||
}
|
||||
return l.getWorld().generateTree(l, this.getVanillaTreeType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MaterialData> getSpawnable() {
|
||||
return spawnable.stream().map(BukkitMaterialData::new).collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.vector.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;
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal;
|
||||
|
||||
import com.dfsek.terra.api.gaea.util.GlueList;
|
||||
import com.dfsek.terra.api.generic.world.block.BlockData;
|
||||
import com.dfsek.terra.api.generic.world.block.MaterialData;
|
||||
import com.dfsek.terra.api.generic.world.vector.Location;
|
||||
import com.dfsek.terra.api.implementations.bukkit.world.block.BukkitBlockData;
|
||||
import org.bukkit.Material;
|
||||
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, new BukkitBlockData(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 MaterialData getMaterial(Location l) {
|
||||
return treeAssembler.getOrDefault(l, new BukkitBlockData(Material.AIR.createBlockData())).getMaterial();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.generic.world.vector.Location;
|
||||
import com.dfsek.terra.api.generic.world.vector.Vector3;
|
||||
import org.bukkit.Material;
|
||||
|
||||
public class TreeGeometry {
|
||||
private final FractalTree tree;
|
||||
|
||||
public TreeGeometry(FractalTree tree) {
|
||||
this.tree = tree;
|
||||
}
|
||||
|
||||
public static Vector3 getPerpendicular(Vector3 v) {
|
||||
return v.getZ() < v.getX() ? new Vector3(v.getY(), - v.getX(), 0) : new Vector3(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++) {
|
||||
Vector3 position = l.toVector().clone().add(new Vector3(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++) {
|
||||
Vector3 position = l.toVector().clone().add(new Vector3(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++) {
|
||||
Vector3 position = l.toVector().clone().add(new Vector3(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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.vector.Location;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public interface TreeGetter {
|
||||
FractalTree getTree(Location l, Random r);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal.trees;
|
||||
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import com.dfsek.terra.api.generic.world.vector.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);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
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 com.dfsek.terra.api.generic.world.vector.Location;
|
||||
import com.dfsek.terra.api.generic.world.vector.Vector3;
|
||||
import org.bukkit.Material;
|
||||
|
||||
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() {
|
||||
Vector3 direction = new Vector3(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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
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 com.dfsek.terra.api.generic.world.vector.Location;
|
||||
import com.dfsek.terra.api.generic.world.vector.Vector3;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Material;
|
||||
|
||||
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 Vector3(super.getRandom().nextInt(5) - 2, super.getRandom().nextInt(4) + 6, super.getRandom().nextInt(5) - 2), 2, 0);
|
||||
}
|
||||
|
||||
private void growBranch(Location l1, Vector3 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;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal.trees;
|
||||
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import com.dfsek.terra.api.generic.world.vector.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));
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
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 com.dfsek.terra.api.generic.world.vector.Location;
|
||||
import com.dfsek.terra.api.generic.world.vector.Vector3;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Material;
|
||||
|
||||
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 Vector3(super.getRandom().nextInt(5) - 2, super.getRandom().nextInt(4) + 6, super.getRandom().nextInt(5) - 2), 1, 0);
|
||||
|
||||
}
|
||||
|
||||
private void growBranch(Location l1, Vector3 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;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.tree.fractal.trees;
|
||||
|
||||
import com.dfsek.terra.api.gaea.tree.fractal.FractalTree;
|
||||
import com.dfsek.terra.api.generic.world.vector.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);
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
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 com.dfsek.terra.api.generic.world.vector.Location;
|
||||
import com.dfsek.terra.api.generic.world.vector.Vector3;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Material;
|
||||
|
||||
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 Vector3(super.getRandom().nextInt(5) - 2, super.getRandom().nextInt(3) + 4, super.getRandom().nextInt(5) - 2), 1.5, 0);
|
||||
|
||||
}
|
||||
|
||||
private void growBranch(Location l1, Vector3 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;
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
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 com.dfsek.terra.api.generic.world.vector.Location;
|
||||
import com.dfsek.terra.api.generic.world.vector.Vector3;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Material;
|
||||
|
||||
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 Vector3(0, 16 + super.getRandom().nextInt(5), 0));
|
||||
}
|
||||
|
||||
private void growTrunk(Location l1, Vector3 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);
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,38 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
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), "org.polydev.gaea", "com.dfsek.terra.api.gaea"); // Backwards compat with old Gaea 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();
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.world;
|
||||
|
||||
import com.dfsek.terra.api.gaea.math.Range;
|
||||
import com.dfsek.terra.api.generic.world.Chunk;
|
||||
import com.dfsek.terra.api.generic.world.block.Block;
|
||||
import com.dfsek.terra.api.generic.world.vector.Location;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface Flora {
|
||||
List<Block> getValidSpawnsAt(Chunk chunk, int x, int z, Range check);
|
||||
|
||||
boolean plant(Location l);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
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 com.dfsek.terra.api.generic.world.World;
|
||||
import com.dfsek.terra.api.generic.world.vector.Vector3;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
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<Vector3, 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 Vector3((x << 4) + r.nextInt(16), r.nextInt(maxY - minY + 1) + minY, (z << 4) + r.nextInt(16)));
|
||||
Vector3 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, Vector3 l);
|
||||
|
||||
public abstract boolean isChunkCarved(World w, int chunkX, int chunkZ, Random r);
|
||||
|
||||
public enum CarvingType {
|
||||
CENTER, WALL, TOP, BOTTOM
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
package com.dfsek.terra.api.gaea.world.carving;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.vector.Vector3;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public abstract class Worm {
|
||||
private final Random r;
|
||||
private final Vector3 origin;
|
||||
private final Vector3 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, Vector3 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 Vector3 getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public Vector3 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 Vector3 origin;
|
||||
private final int topCut;
|
||||
private final int bottomCut;
|
||||
private final int[] rad;
|
||||
|
||||
public WormPoint(Vector3 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 Vector3 getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public int getRadius(int index) {
|
||||
return rad[index];
|
||||
}
|
||||
|
||||
public void carve(int chunkX, int chunkZ, BiConsumer<Vector3, 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++) {
|
||||
Vector3 position = origin.clone().add(new Vector3(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 Vector3(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 Vector3(position.getBlockX() - originX, position.getBlockY(), position.getBlockZ() - originZ), type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
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,8 +0,0 @@
|
||||
package com.dfsek.terra.api.generic;
|
||||
|
||||
/**
|
||||
* An interface that contains a platform delegate.
|
||||
*/
|
||||
public interface Handle {
|
||||
Object getHandle();
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.dfsek.terra.api.generic;
|
||||
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.api.LoaderRegistrar;
|
||||
import com.dfsek.terra.api.generic.world.World;
|
||||
import com.dfsek.terra.api.generic.world.WorldHandle;
|
||||
import com.dfsek.terra.config.base.PluginConfig;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public interface TerraPlugin extends LoaderRegistrar {
|
||||
WorldHandle getHandle();
|
||||
|
||||
boolean isEnabled();
|
||||
|
||||
TerraWorld getWorld(World world);
|
||||
|
||||
Logger getLogger();
|
||||
|
||||
PluginConfig getTerraConfig();
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.generator;
|
||||
|
||||
import com.dfsek.terra.api.generic.Handle;
|
||||
import com.dfsek.terra.api.generic.world.Chunk;
|
||||
import com.dfsek.terra.api.generic.world.World;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public interface BlockPopulator extends Handle {
|
||||
void populate(World world, Random random, Chunk chunk);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.generator;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.Chunk;
|
||||
import com.dfsek.terra.api.generic.world.World;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public interface TerraBlockPopulator {
|
||||
void populate(World world, Random random, Chunk chunk);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.generator;
|
||||
|
||||
import com.dfsek.terra.api.gaea.profiler.WorldProfiler;
|
||||
import com.dfsek.terra.api.generic.world.BiomeGrid;
|
||||
import com.dfsek.terra.api.generic.world.World;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public interface TerraChunkGenerator {
|
||||
ChunkGenerator.ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome, ChunkGenerator.ChunkData original);
|
||||
|
||||
void attachProfiler(WorldProfiler profiler);
|
||||
|
||||
boolean isParallelCapable();
|
||||
|
||||
boolean shouldGenerateCaves();
|
||||
|
||||
boolean shouldGenerateDecorations();
|
||||
|
||||
boolean shouldGenerateMobs();
|
||||
|
||||
boolean shouldGenerateStructures();
|
||||
|
||||
ConfigPack getConfigPack();
|
||||
|
||||
List<TerraBlockPopulator> getPopulators();
|
||||
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world;
|
||||
|
||||
import com.dfsek.terra.api.generic.Handle;
|
||||
|
||||
public interface Biome extends Handle {
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world;
|
||||
|
||||
import com.dfsek.terra.api.generic.Handle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface BiomeGrid extends Handle {
|
||||
/**
|
||||
* Get biome at x, z within chunk being generated
|
||||
*
|
||||
* @param x - 0-15
|
||||
* @param z - 0-15
|
||||
* @return Biome value
|
||||
*/
|
||||
@NotNull
|
||||
Biome getBiome(int x, int z);
|
||||
|
||||
/**
|
||||
* Get biome at x, z within chunk being generated
|
||||
*
|
||||
* @param x - 0-15
|
||||
* @param y - 0-255
|
||||
* @param z - 0-15
|
||||
* @return Biome value
|
||||
*/
|
||||
@NotNull
|
||||
Biome getBiome(int x, int y, int z);
|
||||
|
||||
/**
|
||||
* Set biome at x, z within chunk being generated
|
||||
*
|
||||
* @param x - 0-15
|
||||
* @param z - 0-15
|
||||
* @param bio - Biome value
|
||||
*/
|
||||
void setBiome(int x, int z, @NotNull Biome bio);
|
||||
|
||||
/**
|
||||
* Set biome at x, z within chunk being generated
|
||||
*
|
||||
* @param x - 0-15
|
||||
* @param y - 0-255
|
||||
* @param z - 0-15
|
||||
* @param bio - Biome value
|
||||
*/
|
||||
void setBiome(int x, int y, int z, @NotNull Biome bio);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world;
|
||||
|
||||
import com.dfsek.terra.api.generic.Handle;
|
||||
import com.dfsek.terra.api.generic.world.block.Block;
|
||||
|
||||
public interface Chunk extends Handle {
|
||||
int getX();
|
||||
|
||||
int getZ();
|
||||
|
||||
World getWorld();
|
||||
|
||||
Block getBlock(int x, int y, int z);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world;
|
||||
|
||||
import com.dfsek.terra.api.generic.Handle;
|
||||
import com.dfsek.terra.api.generic.generator.ChunkGenerator;
|
||||
import com.dfsek.terra.api.generic.world.block.Block;
|
||||
import com.dfsek.terra.api.generic.world.vector.Location;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.util.Consumer;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface World extends Handle {
|
||||
long getSeed();
|
||||
|
||||
int getMaxHeight();
|
||||
|
||||
ChunkGenerator getGenerator();
|
||||
|
||||
String getName();
|
||||
|
||||
UUID getUID();
|
||||
|
||||
boolean isChunkGenerated(int x, int z);
|
||||
|
||||
Chunk getChunkAt(int x, int z);
|
||||
|
||||
File getWorldFolder();
|
||||
|
||||
Block getBlockAt(int x, int y, int z);
|
||||
|
||||
Block getBlockAt(Location l);
|
||||
|
||||
boolean generateTree(Location l, TreeType vanillaTreeType); // TODO: Bukkit treetype is bad
|
||||
|
||||
void spawn(Location location, Class<Entity> entity, Consumer<Entity> consumer); // TODO: Bukkit Entity is bad
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.block.Block;
|
||||
import com.dfsek.terra.api.generic.world.block.BlockData;
|
||||
import com.dfsek.terra.api.generic.world.block.MaterialData;
|
||||
|
||||
/**
|
||||
* Interface to be implemented for world manipulation.
|
||||
*/
|
||||
public interface WorldHandle {
|
||||
void setBlockData(Block block, BlockData data, boolean physics);
|
||||
|
||||
BlockData getBlockData(Block block);
|
||||
|
||||
MaterialData getType(Block block);
|
||||
|
||||
BlockData createBlockData(String data);
|
||||
|
||||
MaterialData createMaterialData(String data);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world.block;
|
||||
|
||||
import com.dfsek.terra.api.generic.Handle;
|
||||
import com.dfsek.terra.api.generic.world.vector.Location;
|
||||
|
||||
public interface Block extends Handle {
|
||||
void setBlockData(BlockData data, boolean physics);
|
||||
|
||||
BlockData getBlockData();
|
||||
|
||||
Block getRelative(BlockFace face);
|
||||
|
||||
Block getRelative(BlockFace face, int len);
|
||||
|
||||
boolean isEmpty();
|
||||
|
||||
Location getLocation();
|
||||
|
||||
MaterialData getType();
|
||||
|
||||
int getX();
|
||||
|
||||
int getZ();
|
||||
|
||||
int getY();
|
||||
|
||||
boolean isPassable();
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world.block;
|
||||
|
||||
import com.dfsek.terra.api.generic.Handle;
|
||||
|
||||
public interface BlockData extends Cloneable, Handle {
|
||||
MaterialData getMaterial();
|
||||
|
||||
boolean matches(MaterialData materialData);
|
||||
|
||||
BlockData clone();
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world.block;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.vector.Vector3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public enum BlockFace {
|
||||
NORTH(0, 0, -1),
|
||||
EAST(1, 0, 0),
|
||||
SOUTH(0, 0, 1),
|
||||
WEST(-1, 0, 0),
|
||||
UP(0, 1, 0),
|
||||
DOWN(0, -1, 0),
|
||||
NORTH_EAST(NORTH, EAST),
|
||||
NORTH_WEST(NORTH, WEST),
|
||||
SOUTH_EAST(SOUTH, EAST),
|
||||
SOUTH_WEST(SOUTH, WEST),
|
||||
WEST_NORTH_WEST(WEST, NORTH_WEST),
|
||||
NORTH_NORTH_WEST(NORTH, NORTH_WEST),
|
||||
NORTH_NORTH_EAST(NORTH, NORTH_EAST),
|
||||
EAST_NORTH_EAST(EAST, NORTH_EAST),
|
||||
EAST_SOUTH_EAST(EAST, SOUTH_EAST),
|
||||
SOUTH_SOUTH_EAST(SOUTH, SOUTH_EAST),
|
||||
SOUTH_SOUTH_WEST(SOUTH, SOUTH_WEST),
|
||||
WEST_SOUTH_WEST(WEST, SOUTH_WEST),
|
||||
SELF(0, 0, 0);
|
||||
|
||||
private final int modX;
|
||||
private final int modY;
|
||||
private final int modZ;
|
||||
|
||||
BlockFace(final int modX, final int modY, final int modZ) {
|
||||
this.modX = modX;
|
||||
this.modY = modY;
|
||||
this.modZ = modZ;
|
||||
}
|
||||
|
||||
BlockFace(final BlockFace face1, final BlockFace face2) {
|
||||
this.modX = face1.getModX() + face2.getModX();
|
||||
this.modY = face1.getModY() + face2.getModY();
|
||||
this.modZ = face1.getModZ() + face2.getModZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of X-coordinates to modify to get the represented block
|
||||
*
|
||||
* @return Amount of X-coordinates to modify
|
||||
*/
|
||||
public int getModX() {
|
||||
return modX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of Y-coordinates to modify to get the represented block
|
||||
*
|
||||
* @return Amount of Y-coordinates to modify
|
||||
*/
|
||||
public int getModY() {
|
||||
return modY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of Z-coordinates to modify to get the represented block
|
||||
*
|
||||
* @return Amount of Z-coordinates to modify
|
||||
*/
|
||||
public int getModZ() {
|
||||
return modZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the normal vector corresponding to this block face.
|
||||
*
|
||||
* @return the normal vector
|
||||
*/
|
||||
@NotNull
|
||||
public Vector3 getDirection() {
|
||||
Vector3 direction = new Vector3(modX, modY, modZ);
|
||||
if(modX != 0 || modY != 0 || modZ != 0) {
|
||||
direction.normalize();
|
||||
}
|
||||
return direction;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public org.bukkit.block.BlockFace getOppositeFace() {
|
||||
switch(this) {
|
||||
case NORTH:
|
||||
return org.bukkit.block.BlockFace.SOUTH;
|
||||
|
||||
case SOUTH:
|
||||
return org.bukkit.block.BlockFace.NORTH;
|
||||
|
||||
case EAST:
|
||||
return org.bukkit.block.BlockFace.WEST;
|
||||
|
||||
case WEST:
|
||||
return org.bukkit.block.BlockFace.EAST;
|
||||
|
||||
case UP:
|
||||
return org.bukkit.block.BlockFace.DOWN;
|
||||
|
||||
case DOWN:
|
||||
return org.bukkit.block.BlockFace.UP;
|
||||
|
||||
case NORTH_EAST:
|
||||
return org.bukkit.block.BlockFace.SOUTH_WEST;
|
||||
|
||||
case NORTH_WEST:
|
||||
return org.bukkit.block.BlockFace.SOUTH_EAST;
|
||||
|
||||
case SOUTH_EAST:
|
||||
return org.bukkit.block.BlockFace.NORTH_WEST;
|
||||
|
||||
case SOUTH_WEST:
|
||||
return org.bukkit.block.BlockFace.NORTH_EAST;
|
||||
|
||||
case WEST_NORTH_WEST:
|
||||
return org.bukkit.block.BlockFace.EAST_SOUTH_EAST;
|
||||
|
||||
case NORTH_NORTH_WEST:
|
||||
return org.bukkit.block.BlockFace.SOUTH_SOUTH_EAST;
|
||||
|
||||
case NORTH_NORTH_EAST:
|
||||
return org.bukkit.block.BlockFace.SOUTH_SOUTH_WEST;
|
||||
|
||||
case EAST_NORTH_EAST:
|
||||
return org.bukkit.block.BlockFace.WEST_SOUTH_WEST;
|
||||
|
||||
case EAST_SOUTH_EAST:
|
||||
return org.bukkit.block.BlockFace.WEST_NORTH_WEST;
|
||||
|
||||
case SOUTH_SOUTH_EAST:
|
||||
return org.bukkit.block.BlockFace.NORTH_NORTH_WEST;
|
||||
|
||||
case SOUTH_SOUTH_WEST:
|
||||
return org.bukkit.block.BlockFace.NORTH_NORTH_EAST;
|
||||
|
||||
case WEST_SOUTH_WEST:
|
||||
return org.bukkit.block.BlockFace.EAST_NORTH_EAST;
|
||||
|
||||
case SELF:
|
||||
return org.bukkit.block.BlockFace.SELF;
|
||||
}
|
||||
|
||||
return org.bukkit.block.BlockFace.SELF;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world.block;
|
||||
|
||||
import com.dfsek.terra.api.generic.Handle;
|
||||
|
||||
public interface MaterialData extends Handle {
|
||||
boolean matches(MaterialData other);
|
||||
|
||||
boolean matches(BlockData other);
|
||||
|
||||
boolean isSolid();
|
||||
|
||||
boolean isAir();
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world.block.data;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.block.BlockData;
|
||||
|
||||
public interface Bisected extends BlockData {
|
||||
Half getHalf();
|
||||
|
||||
void setHalf(Half half);
|
||||
|
||||
enum Half {
|
||||
/**
|
||||
* The top half of the block, normally with the higher y coordinate.
|
||||
*/
|
||||
TOP,
|
||||
/**
|
||||
* The bottom half of the block, normally with the lower y coordinate.
|
||||
*/
|
||||
BOTTOM
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world.block.data;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.block.BlockData;
|
||||
import com.dfsek.terra.api.generic.world.block.BlockFace;
|
||||
|
||||
public interface Directional extends BlockData {
|
||||
BlockFace getFacing();
|
||||
|
||||
void setFacing(BlockFace facing);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world.block.data;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.block.BlockData;
|
||||
import com.dfsek.terra.api.generic.world.block.BlockFace;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface MultipleFacing extends BlockData {
|
||||
Set<BlockFace> getFaces();
|
||||
|
||||
void setFace(BlockFace face, boolean facing);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world.block.data;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.block.BlockData;
|
||||
import com.dfsek.terra.api.generic.world.block.BlockFace;
|
||||
|
||||
public interface Rotatable extends BlockData {
|
||||
BlockFace getRotation();
|
||||
|
||||
void setRotation(BlockFace face);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world.block.data;
|
||||
|
||||
public interface Slab extends Bisected, Waterlogged {
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world.block.data;
|
||||
|
||||
public interface Stairs extends Waterlogged, Directional, Bisected {
|
||||
Shape getShape();
|
||||
|
||||
void setShape(Shape shape);
|
||||
|
||||
enum Shape {
|
||||
/**
|
||||
* Regular stair block.
|
||||
*/
|
||||
STRAIGHT,
|
||||
/**
|
||||
* Inner corner stair block with higher left side.
|
||||
*/
|
||||
INNER_LEFT,
|
||||
/**
|
||||
* Inner corner stair block with higher right side.
|
||||
*/
|
||||
INNER_RIGHT,
|
||||
/**
|
||||
* Outer corner stair block with higher left side.
|
||||
*/
|
||||
OUTER_LEFT,
|
||||
/**
|
||||
* Outer corner stair block with higher right side.
|
||||
*/
|
||||
OUTER_RIGHT
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world.block.data;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.block.BlockData;
|
||||
|
||||
public interface Waterlogged extends BlockData {
|
||||
boolean isWaterlogged();
|
||||
|
||||
void setWaterlogged(boolean waterlogged);
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world.vector;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.World;
|
||||
import com.dfsek.terra.api.generic.world.block.Block;
|
||||
|
||||
public class Location implements Cloneable {
|
||||
private World world;
|
||||
private Vector3 vector;
|
||||
|
||||
public Location(World w, double x, double y, double z) {
|
||||
this.world = w;
|
||||
this.vector = new Vector3(x, y, z);
|
||||
}
|
||||
|
||||
public Location(World w, Vector3 vector) {
|
||||
this.world = w;
|
||||
this.vector = vector;
|
||||
}
|
||||
|
||||
public void setWorld(World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public Vector3 getVector() {
|
||||
return vector;
|
||||
}
|
||||
|
||||
public void setVector(Vector3 vector) {
|
||||
this.vector = vector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location clone() {
|
||||
try {
|
||||
Location other = (Location) super.clone();
|
||||
other.setVector(other.getVector().clone());
|
||||
return other;
|
||||
} catch(CloneNotSupportedException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getBlockX() {
|
||||
return vector.getBlockX();
|
||||
}
|
||||
|
||||
public int getBlockY() {
|
||||
return vector.getBlockY();
|
||||
}
|
||||
|
||||
public int getBlockZ() {
|
||||
return vector.getBlockZ();
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return vector.getY();
|
||||
}
|
||||
|
||||
public Location setY(double y) {
|
||||
vector.setY(y);
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return vector.getX();
|
||||
}
|
||||
|
||||
public Location setX(double x) {
|
||||
vector.setX(x);
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return vector.getZ();
|
||||
}
|
||||
|
||||
public Location setZ(double z) {
|
||||
vector.setZ(z);
|
||||
return this;
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public Location add(double x, double y, double z) {
|
||||
vector.add(x, y, z);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Block getBlock() {
|
||||
return world.getBlockAt(this);
|
||||
}
|
||||
|
||||
public Location subtract(int x, int y, int z) {
|
||||
vector.subtract(x, y, z);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Location add(Vector3 add) {
|
||||
vector.add(add);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vector3 toVector() {
|
||||
return vector.clone();
|
||||
}
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world.vector;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
|
||||
/**
|
||||
* oh yeah
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class Vector2 implements Cloneable {
|
||||
private double x;
|
||||
private double z;
|
||||
|
||||
/**
|
||||
* Create a vector with a given X and Z component
|
||||
*
|
||||
* @param x X component
|
||||
* @param z Z component
|
||||
*/
|
||||
public Vector2(double x, double z) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get X component
|
||||
*
|
||||
* @return X component
|
||||
*/
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public Vector2 setX(double x) {
|
||||
this.x = x;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Z component
|
||||
*
|
||||
* @return Z component
|
||||
*/
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public Vector2 setZ(double z) {
|
||||
this.z = z;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply X and Z components by a value.
|
||||
*
|
||||
* @param m Value to multiply
|
||||
* @return Mutated vector, for chaining.
|
||||
*/
|
||||
public Vector2 multiply(double m) {
|
||||
x *= m;
|
||||
z *= m;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add this vector to another.
|
||||
*
|
||||
* @param other Vector to add
|
||||
* @return Mutated vector, for chaining.
|
||||
*/
|
||||
public Vector2 add(Vector2 other) {
|
||||
x += other.x;
|
||||
z += other.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract a vector from this vector,
|
||||
*
|
||||
* @param other Vector to subtract
|
||||
* @return Mutated vector, for chaining.
|
||||
*/
|
||||
public Vector2 subtract(Vector2 other) {
|
||||
x -= other.x;
|
||||
z -= other.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize this vector to length 1
|
||||
*
|
||||
* @return Mutated vector, for chaining.
|
||||
*/
|
||||
public Vector2 normalize() {
|
||||
divide(length());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide X and Z components by a value.
|
||||
*
|
||||
* @param d Divisor
|
||||
* @return Mutated vector, for chaining.
|
||||
*/
|
||||
public Vector2 divide(double d) {
|
||||
x /= d;
|
||||
z /= d;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length of this Vector
|
||||
*
|
||||
* @return length
|
||||
*/
|
||||
public double length() {
|
||||
return FastMath.sqrt(lengthSquared());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the squared length of this Vector
|
||||
*
|
||||
* @return squared length
|
||||
*/
|
||||
public double lengthSquared() {
|
||||
return x * x + z * z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the distance from this vector to another.
|
||||
*
|
||||
* @param other Another vector
|
||||
* @return Distance between vectors
|
||||
*/
|
||||
public double distance(Vector2 other) {
|
||||
return FastMath.sqrt(distanceSquared(other));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the squared distance between 2 vectors.
|
||||
*
|
||||
* @param other Another vector
|
||||
* @return Squared distance
|
||||
*/
|
||||
public double distanceSquared(Vector2 other) {
|
||||
double dx = other.x - x;
|
||||
double dz = other.z - z;
|
||||
return dx * dx + dz * dz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 17;
|
||||
hash = 31 * hash + Double.hashCode(x);
|
||||
hash = 31 * hash + Double.hashCode(z);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(!(obj instanceof Vector2)) {
|
||||
return false;
|
||||
}
|
||||
Vector2 other = (Vector2) obj;
|
||||
return other.x == this.x && other.z == this.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2 clone() {
|
||||
try {
|
||||
return (Vector2) super.clone();
|
||||
} catch(CloneNotSupportedException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + x + ", " + z + ")";
|
||||
}
|
||||
}
|
||||
@@ -1,310 +0,0 @@
|
||||
package com.dfsek.terra.api.generic.world.vector;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.World;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Vector3 implements Cloneable {
|
||||
|
||||
/**
|
||||
* Threshold for fuzzy equals().
|
||||
*/
|
||||
private static final double epsilon = 0.000001;
|
||||
|
||||
private double x;
|
||||
private double y;
|
||||
private double z;
|
||||
|
||||
public Vector3(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the threshold used for equals().
|
||||
*
|
||||
* @return The epsilon.
|
||||
*/
|
||||
public static double getEpsilon() {
|
||||
return epsilon;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public Vector3 setZ(double z) {
|
||||
this.z = z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public Vector3 setX(double x) {
|
||||
this.x = x;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public Vector3 setY(double y) {
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getBlockX() {
|
||||
return FastMath.floorToInt(x);
|
||||
}
|
||||
|
||||
public int getBlockY() {
|
||||
return FastMath.floorToInt(y);
|
||||
}
|
||||
|
||||
public int getBlockZ() {
|
||||
return FastMath.floorToInt(z);
|
||||
}
|
||||
|
||||
public Vector3 multiply(double m) {
|
||||
x *= m;
|
||||
y *= m;
|
||||
z *= m;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vector3 add(double x, double y, double z) {
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
this.z += z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vector3 add(Vector3 other) {
|
||||
this.x += other.getX();
|
||||
this.y += other.getY();
|
||||
this.z += other.getZ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vector3 add(Vector2 other) {
|
||||
this.x += other.getX();
|
||||
this.z += other.getZ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public double lengthSquared() {
|
||||
return x * x + y * y + z * z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 clone() {
|
||||
try {
|
||||
return (Vector3) super.clone();
|
||||
} catch(CloneNotSupportedException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public double length() {
|
||||
return FastMath.sqrt(lengthSquared());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a vector is normalized
|
||||
*
|
||||
* @return whether the vector is normalised
|
||||
*/
|
||||
public boolean isNormalized() {
|
||||
return Math.abs(this.lengthSquared() - 1) < getEpsilon();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the vector around the x axis.
|
||||
* <p>
|
||||
* This piece of math is based on the standard rotation matrix for vectors
|
||||
* in three dimensional space. This matrix can be found here:
|
||||
* <a href="https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">Rotation
|
||||
* Matrix</a>.
|
||||
*
|
||||
* @param angle the angle to rotate the vector about. This angle is passed
|
||||
* in radians
|
||||
* @return the same vector
|
||||
*/
|
||||
@NotNull
|
||||
public Vector3 rotateAroundX(double angle) {
|
||||
double angleCos = Math.cos(angle);
|
||||
double angleSin = Math.sin(angle);
|
||||
|
||||
double y = angleCos * getY() - angleSin * getZ();
|
||||
double z = angleSin * getY() + angleCos * getZ();
|
||||
return setY(y).setZ(z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the vector around the y axis.
|
||||
* <p>
|
||||
* This piece of math is based on the standard rotation matrix for vectors
|
||||
* in three dimensional space. This matrix can be found here:
|
||||
* <a href="https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">Rotation
|
||||
* Matrix</a>.
|
||||
*
|
||||
* @param angle the angle to rotate the vector about. This angle is passed
|
||||
* in radians
|
||||
* @return the same vector
|
||||
*/
|
||||
@NotNull
|
||||
public Vector3 rotateAroundY(double angle) {
|
||||
double angleCos = Math.cos(angle);
|
||||
double angleSin = Math.sin(angle);
|
||||
|
||||
double x = angleCos * getX() + angleSin * getZ();
|
||||
double z = -angleSin * getX() + angleCos * getZ();
|
||||
return setX(x).setZ(z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the vector around the z axis
|
||||
* <p>
|
||||
* This piece of math is based on the standard rotation matrix for vectors
|
||||
* in three dimensional space. This matrix can be found here:
|
||||
* <a href="https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">Rotation
|
||||
* Matrix</a>.
|
||||
*
|
||||
* @param angle the angle to rotate the vector about. This angle is passed
|
||||
* in radians
|
||||
* @return the same vector
|
||||
*/
|
||||
@NotNull
|
||||
public Vector3 rotateAroundZ(double angle) {
|
||||
double angleCos = Math.cos(angle);
|
||||
double angleSin = Math.sin(angle);
|
||||
|
||||
double x = angleCos * getX() - angleSin * getY();
|
||||
double y = angleSin * getX() + angleCos * getY();
|
||||
return setX(x).setY(y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the distance between this vector and another. The value of this
|
||||
* method is not cached and uses a costly square-root function, so do not
|
||||
* repeatedly call this method to get the vector's magnitude. NaN will be
|
||||
* returned if the inner result of the sqrt() function overflows, which
|
||||
* will be caused if the distance is too long.
|
||||
*
|
||||
* @param o The other vector
|
||||
* @return the distance
|
||||
*/
|
||||
public double distance(@NotNull Vector3 o) {
|
||||
return FastMath.sqrt(NumberConversions.square(x - o.x) + NumberConversions.square(y - o.y) + NumberConversions.square(z - o.z));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the squared distance between this vector and another.
|
||||
*
|
||||
* @param o The other vector
|
||||
* @return the distance
|
||||
*/
|
||||
public double distanceSquared(@NotNull Vector3 o) {
|
||||
return NumberConversions.square(x - o.x) + NumberConversions.square(y - o.y) + NumberConversions.square(z - o.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the vector around a given arbitrary axis in 3 dimensional space.
|
||||
*
|
||||
* <p>
|
||||
* Rotation will follow the general Right-Hand-Rule, which means rotation
|
||||
* will be counterclockwise when the axis is pointing towards the observer.
|
||||
* <p>
|
||||
* This method will always make sure the provided axis is a unit vector, to
|
||||
* not modify the length of the vector when rotating. If you are experienced
|
||||
* with the scaling of a non-unit axis vector, you can use
|
||||
* {@link Vector#rotateAroundNonUnitAxis(Vector, double)}.
|
||||
*
|
||||
* @param axis the axis to rotate the vector around. If the passed vector is
|
||||
* not of length 1, it gets copied and normalized before using it for the
|
||||
* rotation. Please use {@link Vector#normalize()} on the instance before
|
||||
* passing it to this method
|
||||
* @param angle the angle to rotate the vector around the axis
|
||||
* @return the same vector
|
||||
* @throws IllegalArgumentException if the provided axis vector instance is
|
||||
* null
|
||||
*/
|
||||
@NotNull
|
||||
public Vector3 rotateAroundAxis(@NotNull Vector3 axis, double angle) throws IllegalArgumentException {
|
||||
return rotateAroundNonUnitAxis(axis.isNormalized() ? axis : axis.clone().normalize(), angle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the vector around a given arbitrary axis in 3 dimensional space.
|
||||
*
|
||||
* <p>
|
||||
* Rotation will follow the general Right-Hand-Rule, which means rotation
|
||||
* will be counterclockwise when the axis is pointing towards the observer.
|
||||
* <p>
|
||||
* Note that the vector length will change accordingly to the axis vector
|
||||
* length. If the provided axis is not a unit vector, the rotated vector
|
||||
* will not have its previous length. The scaled length of the resulting
|
||||
* vector will be related to the axis vector. If you are not perfectly sure
|
||||
* about the scaling of the vector, use
|
||||
* {@link Vector#rotateAroundAxis(Vector, double)}
|
||||
*
|
||||
* @param axis the axis to rotate the vector around.
|
||||
* @param angle the angle to rotate the vector around the axis
|
||||
* @return the same vector
|
||||
* @throws IllegalArgumentException if the provided axis vector instance is
|
||||
* null
|
||||
*/
|
||||
@NotNull
|
||||
public Vector3 rotateAroundNonUnitAxis(@NotNull Vector3 axis, double angle) throws IllegalArgumentException {
|
||||
double x = getX(), y = getY(), z = getZ();
|
||||
double x2 = axis.getX(), y2 = axis.getY(), z2 = axis.getZ();
|
||||
|
||||
double cosTheta = Math.cos(angle);
|
||||
double sinTheta = Math.sin(angle);
|
||||
double dotProduct = this.dot(axis);
|
||||
|
||||
double xPrime = x2 * dotProduct * (1d - cosTheta)
|
||||
+ x * cosTheta
|
||||
+ (-z2 * y + y2 * z) * sinTheta;
|
||||
double yPrime = y2 * dotProduct * (1d - cosTheta)
|
||||
+ y * cosTheta
|
||||
+ (z2 * x - x2 * z) * sinTheta;
|
||||
double zPrime = z2 * dotProduct * (1d - cosTheta)
|
||||
+ z * cosTheta
|
||||
+ (-y2 * x + x2 * y) * sinTheta;
|
||||
|
||||
return setX(xPrime).setY(yPrime).setZ(zPrime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the dot product of this vector with another. The dot product
|
||||
* is defined as x1*x2+y1*y2+z1*z2. The returned value is a scalar.
|
||||
*
|
||||
* @param other The other vector
|
||||
* @return dot product
|
||||
*/
|
||||
public double dot(@NotNull Vector3 other) {
|
||||
return x * other.x + y * other.y + z * other.z;
|
||||
}
|
||||
|
||||
public Location toLocation(World world) {
|
||||
return new Location(world, this.clone());
|
||||
}
|
||||
|
||||
public Vector3 normalize() {
|
||||
return this.multiply(1D / this.length());
|
||||
}
|
||||
|
||||
public Vector3 subtract(int x, int y, int z) {
|
||||
this.x -= x;
|
||||
this.y -= y;
|
||||
this.z = -z;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package com.dfsek.terra.api.implementations.bukkit;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.Biome;
|
||||
import com.dfsek.terra.api.generic.world.BiomeGrid;
|
||||
import com.dfsek.terra.api.implementations.bukkit.world.BukkitBiome;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class BukkitBiomeGrid implements BiomeGrid {
|
||||
private final ChunkGenerator.BiomeGrid delegate;
|
||||
|
||||
public BukkitBiomeGrid(ChunkGenerator.BiomeGrid biomeGrid) {
|
||||
this.delegate = biomeGrid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGenerator.BiomeGrid getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Biome getBiome(int x, int z) {
|
||||
return new BukkitBiome(delegate.getBiome(x, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Biome getBiome(int x, int y, int z) {
|
||||
return new BukkitBiome(delegate.getBiome(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int z, @NotNull Biome bio) {
|
||||
delegate.setBiome(x, z, ((BukkitBiome) bio).getHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int y, int z, @NotNull Biome bio) {
|
||||
delegate.setBiome(x, y, z, ((BukkitBiome) bio).getHandle());
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.dfsek.terra.api.implementations.bukkit;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.Chunk;
|
||||
import com.dfsek.terra.api.generic.world.World;
|
||||
import com.dfsek.terra.api.generic.world.block.Block;
|
||||
import com.dfsek.terra.api.implementations.bukkit.world.block.BukkitBlock;
|
||||
|
||||
public class BukkitChunk implements Chunk {
|
||||
private final org.bukkit.Chunk delegate;
|
||||
|
||||
public BukkitChunk(org.bukkit.Chunk delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getX() {
|
||||
return delegate.getX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ() {
|
||||
return delegate.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return new BukkitWorld(delegate.getWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getBlock(int x, int y, int z) {
|
||||
return new BukkitBlock(delegate.getBlock(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.Chunk getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
package com.dfsek.terra.api.implementations.bukkit;
|
||||
|
||||
import com.dfsek.terra.api.generic.generator.ChunkGenerator;
|
||||
import com.dfsek.terra.api.generic.world.Chunk;
|
||||
import com.dfsek.terra.api.generic.world.World;
|
||||
import com.dfsek.terra.api.generic.world.block.Block;
|
||||
import com.dfsek.terra.api.generic.world.vector.Location;
|
||||
import com.dfsek.terra.api.implementations.bukkit.generator.BukkitChunkGenerator;
|
||||
import com.dfsek.terra.api.implementations.bukkit.world.block.BukkitBlock;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.util.Consumer;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BukkitWorld implements World {
|
||||
private final org.bukkit.World delegate;
|
||||
|
||||
public BukkitWorld(org.bukkit.World delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSeed() {
|
||||
return delegate.getSeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return delegate.getMaxHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getGenerator() {
|
||||
return new BukkitChunkGenerator(delegate.getGenerator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return delegate.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUID() {
|
||||
return delegate.getUID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkGenerated(int x, int z) {
|
||||
return delegate.isChunkGenerated(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunkAt(int x, int z) {
|
||||
return new BukkitChunk(delegate.getChunkAt(x, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getWorldFolder() {
|
||||
return delegate.getWorldFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getBlockAt(int x, int y, int z) {
|
||||
return new BukkitBlock(delegate.getBlockAt(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getBlockAt(Location l) {
|
||||
return new BukkitBlock(delegate.getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generateTree(Location l, TreeType vanillaTreeType) {
|
||||
return delegate.generateTree(new org.bukkit.Location(((BukkitWorld) l.getWorld()).getHandle(), l.getX(), l.getY(), l.getZ()), vanillaTreeType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawn(Location l, Class<Entity> entity, Consumer<Entity> consumer) {
|
||||
delegate.spawn(new org.bukkit.Location(((BukkitWorld) l.getWorld()).getHandle(), l.getX(), l.getY(), l.getZ()), entity, consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.World getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(!(obj instanceof BukkitWorld)) return false;
|
||||
BukkitWorld other = (BukkitWorld) obj;
|
||||
return other.getHandle().equals(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return delegate.hashCode();
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.dfsek.terra.api.implementations.bukkit;
|
||||
|
||||
import com.dfsek.terra.api.generic.world.WorldHandle;
|
||||
import com.dfsek.terra.api.generic.world.block.Block;
|
||||
import com.dfsek.terra.api.generic.world.block.BlockData;
|
||||
import com.dfsek.terra.api.generic.world.block.MaterialData;
|
||||
import com.dfsek.terra.api.generic.world.block.data.Waterlogged;
|
||||
import com.dfsek.terra.api.implementations.bukkit.world.block.BukkitBlockData;
|
||||
import com.dfsek.terra.api.implementations.bukkit.world.block.BukkitMaterialData;
|
||||
import com.dfsek.terra.api.implementations.bukkit.world.block.data.BukkitStairs;
|
||||
import com.dfsek.terra.api.implementations.bukkit.world.block.data.BukkitWaterlogged;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.type.Stairs;
|
||||
|
||||
public class BukkitWorldHandle implements WorldHandle {
|
||||
|
||||
@Override
|
||||
public void setBlockData(Block block, BlockData data, boolean physics) {
|
||||
block.setBlockData(data, physics);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(Block block) {
|
||||
return block.getBlockData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaterialData getType(Block block) {
|
||||
return block.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData createBlockData(String data) {
|
||||
org.bukkit.block.data.BlockData bukkitData = Bukkit.createBlockData(data);
|
||||
if(bukkitData instanceof Stairs) return new BukkitStairs(bukkitData);
|
||||
if(bukkitData instanceof Waterlogged) return new BukkitWaterlogged(bukkitData);
|
||||
return new BukkitBlockData(Bukkit.createBlockData(data));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaterialData createMaterialData(String data) {
|
||||
return new BukkitMaterialData(Material.matchMaterial(data));
|
||||
}
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
package com.dfsek.terra.api.implementations.bukkit;
|
||||
|
||||
import com.dfsek.tectonic.loading.TypeRegistry;
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.api.GenericLoaders;
|
||||
import com.dfsek.terra.api.gaea.GaeaPlugin;
|
||||
import com.dfsek.terra.api.gaea.lang.Language;
|
||||
import com.dfsek.terra.api.generic.TerraPlugin;
|
||||
import com.dfsek.terra.api.generic.world.Biome;
|
||||
import com.dfsek.terra.api.generic.world.World;
|
||||
import com.dfsek.terra.api.generic.world.WorldHandle;
|
||||
import com.dfsek.terra.api.generic.world.block.BlockData;
|
||||
import com.dfsek.terra.api.generic.world.block.MaterialData;
|
||||
import com.dfsek.terra.api.implementations.bukkit.generator.BukkitChunkGenerator;
|
||||
import com.dfsek.terra.api.implementations.bukkit.generator.BukkitChunkGeneratorWrapper;
|
||||
import com.dfsek.terra.api.implementations.bukkit.world.BukkitBiome;
|
||||
import com.dfsek.terra.command.TerraCommand;
|
||||
import com.dfsek.terra.command.structure.LocateCommand;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.base.PluginConfig;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
import com.dfsek.terra.debug.Debug;
|
||||
import com.dfsek.terra.generation.TerraChunkGenerator;
|
||||
import com.dfsek.terra.listeners.EventListener;
|
||||
import com.dfsek.terra.listeners.SpigotListener;
|
||||
import com.dfsek.terra.registry.ConfigRegistry;
|
||||
import com.dfsek.terra.util.PaperUtil;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class TerraBukkitPlugin extends GaeaPlugin implements TerraPlugin {
|
||||
private final Map<String, TerraChunkGenerator> generatorMap = new HashMap<>();
|
||||
private final Map<World, TerraWorld> worldMap = new HashMap<>();
|
||||
private final Map<String, ConfigPack> worlds = new HashMap<>();
|
||||
private final ConfigRegistry registry = new ConfigRegistry();
|
||||
private final PluginConfig config = new PluginConfig();
|
||||
private WorldHandle handle = new BukkitWorldHandle();
|
||||
private final GenericLoaders genericLoaders = new GenericLoaders(this);
|
||||
|
||||
public void reload() {
|
||||
Map<World, TerraWorld> newMap = new HashMap<>();
|
||||
worldMap.forEach((world, tw) -> {
|
||||
String packID = tw.getConfig().getTemplate().getID();
|
||||
newMap.put(world, new TerraWorld(world, registry.get(packID), this));
|
||||
});
|
||||
worldMap.clear();
|
||||
worldMap.putAll(newMap);
|
||||
}
|
||||
|
||||
public void setHandle(WorldHandle handle) {
|
||||
getLogger().warning("|-------------------------------------------------------|");
|
||||
getLogger().warning("A third-party addon has injected a custom WorldHandle!");
|
||||
getLogger().warning("If you encounter issues, try *without* the addon before");
|
||||
getLogger().warning("reporting to Terra. Report issues with the addon to the");
|
||||
getLogger().warning("addon's maintainers!");
|
||||
getLogger().warning("|-------------------------------------------------------|");
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
TerraChunkGenerator.saveAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
Debug.setLogger(getLogger()); // Set debug logger.
|
||||
|
||||
saveDefaultConfig();
|
||||
|
||||
Metrics metrics = new Metrics(this, 9017); // Set up bStats.
|
||||
metrics.addCustomChart(new Metrics.SingleLineChart("worlds", worldMap::size)); // World number chart.
|
||||
|
||||
config.load(this); // Load master config.yml
|
||||
LangUtil.load(config.getLanguage(), this); // Load language.
|
||||
Debug.setDebug(isDebug());
|
||||
|
||||
registry.loadAll(this); // Load all config packs.
|
||||
|
||||
PluginCommand c = Objects.requireNonNull(getCommand("terra"));
|
||||
TerraCommand command = new TerraCommand(this); // Set up main Terra command.
|
||||
c.setExecutor(command);
|
||||
c.setTabCompleter(command);
|
||||
|
||||
LocateCommand locate = new LocateCommand(command, false);
|
||||
PluginCommand locatePl = Objects.requireNonNull(getCommand("locate"));
|
||||
locatePl.setExecutor(locate); // Override locate command. Once Paper accepts StructureLocateEvent this will be unneeded on Paper implementations.
|
||||
locatePl.setTabCompleter(locate);
|
||||
|
||||
|
||||
long save = config.getDataSaveInterval();
|
||||
Bukkit.getScheduler().runTaskTimerAsynchronously(this, TerraChunkGenerator::saveAll, save, save); // Schedule population data saving
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(new EventListener(this), this); // Register master event listener
|
||||
Bukkit.getPluginManager().registerEvents(new SpigotListener(this), this); // Register Spigot event listener, once Paper accepts StructureLocateEvent PR Spigot and Paper events will be separate.
|
||||
|
||||
PaperUtil.checkPaper(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ChunkGenerator getDefaultWorldGenerator(@NotNull String worldName, @Nullable String id) {
|
||||
return new BukkitChunkGeneratorWrapper(generatorMap.computeIfAbsent(worldName, name -> {
|
||||
if(!registry.contains(id)) throw new IllegalArgumentException("No such config pack \"" + id + "\"");
|
||||
worlds.put(worldName, registry.get(id));
|
||||
return new TerraChunkGenerator(registry.get(id), this);
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebug() {
|
||||
return config.isDebug();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Language getLanguage() {
|
||||
return LangUtil.getLanguage();
|
||||
}
|
||||
|
||||
public ConfigRegistry getRegistry() {
|
||||
return registry;
|
||||
}
|
||||
|
||||
public TerraWorld getWorld(World w) {
|
||||
if(!(w.getGenerator() instanceof BukkitChunkGenerator))
|
||||
throw new IllegalArgumentException("Not a Terra world! " + w.getGenerator());
|
||||
if(!worlds.containsKey(w.getName())) {
|
||||
getLogger().warning("Unexpected world load detected: \"" + w.getName() + "\"");
|
||||
return new TerraWorld(w, ((TerraChunkGenerator) w.getGenerator()).getConfigPack(), this);
|
||||
}
|
||||
return worldMap.computeIfAbsent(w, world -> new TerraWorld(w, worlds.get(w.getName()), this));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PluginConfig getTerraConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldHandle getHandle() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(TypeRegistry registry) {
|
||||
registry
|
||||
.registerLoader(BlockData.class, (t, o, l) -> handle.createBlockData((String) o))
|
||||
.registerLoader(MaterialData.class, (t, o, l) -> handle.createMaterialData((String) o))
|
||||
.registerLoader(Biome.class, (t, o, l) -> new BukkitBiome(org.bukkit.block.Biome.valueOf((String) o)))
|
||||
.registerLoader(EntityType.class, (t, o, l) -> EntityType.valueOf((String) o));
|
||||
genericLoaders.register(registry);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user