diff --git a/.gitignore b/.gitignore index be03ba1..d189ff3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ .classpath .settings/** .project +.idea/ +*.iml dependency-reduced-pom.xml \ No newline at end of file diff --git a/config.yml b/config.yml index 6c88e69..1c828f8 100644 --- a/config.yml +++ b/config.yml @@ -2,27 +2,27 @@ wormBehavior: wormType: Simplexworm - + #Amount of octaves in simplex function determining worm movement xMovementOctaveCount: 3 yMovementOctaveCount: 3 zMovementOctaveCount: 3 - + #Amplitudes for Simplex functions determining worm movement xSpreadAmplitude: 2.0 ySpreadAmpltitude: 2.0 zSpreadAmpltitude: 2.0 - + #Threshhold inside which the worm wont move xSpreadThreshHold: 0.0 ySpreadThreshHold: 0.05 zSpreadThreshHold: 0.0 - + #Frequency for Simplex functions determining worm movement xSpreadFrequency: 0.08 ySpreadFrequency: 0.16 zSpreadFrequency: 0.08 - + #Seed used for Simplex generator to calculate movement in each dimension, -1 for random seed xSeed: -1 ySeed: -1 @@ -30,56 +30,53 @@ wormBehavior: caveFormingBehavior: formingType: SimplexSphere - + #Lower bound of the range in which all blocks in the given direction are cleared around the center cave block xLowerRadiusBound: 2 yLowerRadiusBound: 2 zLowerRadiusBound: 2 - + #Lower bound of the range in which all blocks in the given direction are cleared around the center cave block xUpperRadiusBound: 6 yUpperRadiusBound: 6 zUpperRadiusBound: 6 - + #Frequency of the Simplex function determining the range in which all blocks in the given direction are cleared around the center cave block xFrequency: 0.1 yFrequency: 0.1 zFrequency: 0.1 - + #Amount of octaves of the Simplex function determining the range in which all blocks in the given direction are cleared around the center cave block xOctaves: 3 yOctaves: 3 zOctaves: 3 - + #Additional slices besides the main one which will be cleared out in each 2 dimensional level xzSlices: 0 xySlices: 0 yzSlices: 0 - + #What to do if a block, which is affected by gravity is above a block to remove: #0 Means the block will be cleared, ignoring the fact it will create a flying block #1 Means the block wont be cleared #2 Means the block will be moved upwards to replace the falling block fallingBlockBehavior: 2 - + fallingBlockReplacement: SANDSTONE - + #Materials that wont be replaced when generating caves, use spigot material identifiers here ignoreMaterials: - BEDROCK - + #Seed used for the generator determining spread for each dimension, -1 for random seed xSeed: -1 ySeed: -1 zSeed: -1 - + #Material with which the emptied out space is replaced, use identifiers as specified here: #https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html (Default: AIR) fillMaterial: AIR - - #Whether spoofed block breaks are sent to hidden ore when removing blocks - useHiddenOre: true - + distribution: area: type: ELLIPSE @@ -164,6 +161,6 @@ distribution: # xOffSet: 1 # yOffSet: 0 # zOffSet: -2 - + caveSystemSeed: -1 seed: -1 \ No newline at end of file diff --git a/plugin.yml b/plugin.yml index 93cc2ec..5d1f9c9 100644 --- a/plugin.yml +++ b/plugin.yml @@ -2,7 +2,7 @@ name: ${project.name} main: com.github.maxopoly.caveworm.Caveworm author: Maxopoly version: ${project.version} -depend: [CivModCore] +api-version: 1.13 commands: cwgen: permission: cw.op diff --git a/pom.xml b/pom.xml index a9f1569..c784df5 100644 --- a/pom.xml +++ b/pom.xml @@ -32,20 +32,8 @@ maven-compiler-plugin 2.3.2 - 1.8 - 1.8 - - - - org.apache.maven.plugins - maven-jar-plugin - - - - true - com.github.maxopoly.caveworm.executable.CavewormMain - - + 21 + 21 @@ -61,20 +49,8 @@ org.spigotmc - Spigot - 1.10 - provided - - - vg.civcraft.mc.civmodcore - CivModCore - 1.4.42 - provided - - - com.github.devotedmc - hiddenore - 1.2.1 + spigot + 1.21.5-R0.1-SNAPSHOT provided @@ -85,8 +61,8 @@ https://hub.spigotmc.org/nexus/content/repositories/snapshots/ - Jenkins-repo - http://build.civcraft.co:8080/plugin/repository/everything/ + jitpack.io + https://jitpack.io diff --git a/src/main/java/com/github/maxopoly/caveworm/CaveWormAPI.java b/src/main/java/com/github/maxopoly/caveworm/CaveWormAPI.java deleted file mode 100644 index 5d98d4f..0000000 --- a/src/main/java/com/github/maxopoly/caveworm/CaveWormAPI.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.github.maxopoly.caveworm; - -import org.bukkit.Location; - -import com.github.maxopoly.caveworm.caveFormers.CaveFormer; -import com.github.maxopoly.caveworm.caveFormers.SimplexSphereFormer; -import com.github.maxopoly.caveworm.distribution.GlobalDistributor; -import com.github.maxopoly.caveworm.worms.SimplexNoiseWorm; -import com.github.maxopoly.caveworm.worms.Worm; - -public class CaveWormAPI { - - public static Worm getWorm(Location loc, int length, WormConfig config) { - switch (config.getWormType()) { - case "Simplexworm": - return new SimplexNoiseWorm(loc, config.getXMovementOctaves(), - config.getYMovementOctaves(), config.getZMovementOctaves(), - config.getXSpreadFrequency(), config.getYSpreadFrequency(), - config.getZSpreadFrequency(), - config.getXSpreadThreshHold(), - config.getYSpreadThreshHold(), - config.getZSpreadThreshHold(), - config.getXSpreadAmplitude(), config.getYSpreadAmplitude(), - config.getYSpreadAmplitude(), length, - config.getXWormMovementSeed(), - config.getYWormMovementSeed(), - config.getZWormMovementSeed()); - default: - return null; - } - } - - public static SimplexSphereFormer getCaveFormer(WormConfig config, int id) { - switch (config.getFormingType()) { - case "SimplexSphere": - return new SimplexSphereFormer(id, config.getFormingFillMaterial(), - config.useHiddenOre(), config.getFillData(), - config.getXFormingOctaveCount(), - config.getYFormingOctaveCount(), - config.getZFormingOctaveCount(), - config.getXFormingFrequency(), - config.getYFormingFrequency(), - config.getZFormingFrequency(), - config.getXUpperFormingRadiusBound(), - config.getYUpperFormingRadiusBound(), - config.getZUpperFormingRadiusBound(), - config.getXLowerFormingRadiusBound(), - config.getYLowerFormingRadiusBound(), - config.getZLowerFormingRadiusBound(), config.getXZSlices(), - config.getXYSlices(), config.getYZSlices(), - config.getIgnoreMaterials(), - config.getFallingBlockBehavior(), - config.getFallingBlockReplacement(), - config.getXFillingSeed(), config.getYFillingSeed(), - config.getZFillingSeed()); - default: - return null; - } - } - - public static void spawnCaveAt(Location loc, int length, WormConfig config) { - Worm w = getWorm(loc, length, config); - CaveFormer former = getCaveFormer(config, 0); - while (w.hasNext()) { - former.extendLocation(w.next()); - } - } - - public static GlobalDistributor getDistributer(WormConfig config) { - if (config.getDistributionArea() == null) { - Caveworm.getInstance().warning( - "No area loaded, can't get distributor"); - return null; - } - GlobalDistributor dist = new GlobalDistributor(config, - config.getDistributionSeed(), 39); - return dist; - } -} diff --git a/src/main/java/com/github/maxopoly/caveworm/Caveworm.java b/src/main/java/com/github/maxopoly/caveworm/Caveworm.java index b0dc69b..1e4b737 100644 --- a/src/main/java/com/github/maxopoly/caveworm/Caveworm.java +++ b/src/main/java/com/github/maxopoly/caveworm/Caveworm.java @@ -1,58 +1,67 @@ package com.github.maxopoly.caveworm; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; - -import org.spigotmc.AsyncCatcher; - import com.github.maxopoly.caveworm.commands.CavewormCommandHandler; -import com.github.maxopoly.caveworm.distribution.GlobalDistributor; -import com.github.maxopoly.caveworm.external.HiddenOreManager; +import org.bukkit.plugin.java.JavaPlugin; -import vg.civcraft.mc.civmodcore.ACivMod; - -public class Caveworm extends ACivMod { +import java.util.logging.Level; +public class Caveworm extends JavaPlugin { private static WormConfig config; private static Caveworm instance; - private static HiddenOreManager hiddenOreManager; public void onEnable() { - instance = this; - handle = new CavewormCommandHandler(); - config = new WormConfig(); - refreshConfig(); - if (config.useHiddenOre()) { - if (Bukkit.getPluginManager().isPluginEnabled("HiddenOre")) { - hiddenOreManager = new HiddenOreManager(); - } else { - warning("Attempted to send block break events to HiddenOre according to config, but it seems like HiddenOre isn't loaded on this server"); - } - } - AsyncCatcher.enabled = false; + instance = this; + + new CavewormCommandHandler(this); + + config = new WormConfig(); + refreshConfig(); } - @Override - protected String getPluginName() { - return "Caveworm"; + /** + * Simple WARNING level logging. + */ + public void warning(String message) { + getLogger().log(Level.WARNING, message); } - public static WormConfig getWormConfig() { - return config; + /** + * Simple INFO level logging + */ + public void info(String message) { + getLogger().log(Level.INFO, message); } - public static Caveworm getInstance() { - return instance; + /** + * Live activatable debug message (using plugin's config.yml top level debug tag to decide) at + * INFO level. + *

+ * Skipped if DebugLog is false. + */ + public void debug(String message) { +// if (isDebugEnabled()) { TODO +// getLogger().log(Level.INFO, message); +// } } - public static HiddenOreManager getHiddenOreManager() { - return hiddenOreManager; + /** + * Simple SEVERE level logging. + */ + public void severe(String message) { + getLogger().log(Level.SEVERE, message); } - public void refreshConfig() { - saveDefaultConfig(); - reloadConfig(); - config.parse(this, getConfig()); + public static WormConfig getWormConfig() { + return config; } -} + public static Caveworm getInstance() { + return instance; + } + + public void refreshConfig() { + saveDefaultConfig(); + reloadConfig(); + config.parse(this, getConfig()); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/maxopoly/caveworm/CavewormAPI.java b/src/main/java/com/github/maxopoly/caveworm/CavewormAPI.java new file mode 100644 index 0000000..f99666e --- /dev/null +++ b/src/main/java/com/github/maxopoly/caveworm/CavewormAPI.java @@ -0,0 +1,78 @@ +package com.github.maxopoly.caveworm; + +import com.github.maxopoly.caveworm.caveformers.CaveFormer; +import com.github.maxopoly.caveworm.caveformers.SimplexSphereFormer; +import com.github.maxopoly.caveworm.distribution.GlobalDistributor; +import com.github.maxopoly.caveworm.events.CaveWormGenerationCompletionEvent; +import com.github.maxopoly.caveworm.worms.SimplexNoiseWorm; +import com.github.maxopoly.caveworm.worms.Worm; +import org.bukkit.Bukkit; +import org.bukkit.Location; + +public class CavewormAPI { + + public static Worm getWorm(Location loc, int length, WormConfig config) { + if (config.getWormType().equals("Simplexworm")) { + return new SimplexNoiseWorm(loc, config.getXMovementOctaves(), + config.getYMovementOctaves(), config.getZMovementOctaves(), + config.getXSpreadFrequency(), config.getYSpreadFrequency(), + config.getZSpreadFrequency(), + config.getXSpreadThreshHold(), + config.getYSpreadThreshHold(), + config.getZSpreadThreshHold(), + config.getXSpreadAmplitude(), config.getYSpreadAmplitude(), + config.getYSpreadAmplitude(), length, + config.getXWormMovementSeed(), + config.getYWormMovementSeed(), + config.getZWormMovementSeed()); + } + return null; + } + + public static SimplexSphereFormer getCaveFormer(WormConfig config, int id) { + if (config.getFormingType().equals("SimplexSphere")) { + return new SimplexSphereFormer(id, config.getFormingFillMaterial(), + config.getXFormingOctaveCount(), + config.getYFormingOctaveCount(), + config.getZFormingOctaveCount(), + config.getXFormingFrequency(), + config.getYFormingFrequency(), + config.getZFormingFrequency(), + config.getXUpperFormingRadiusBound(), + config.getYUpperFormingRadiusBound(), + config.getZUpperFormingRadiusBound(), + config.getXLowerFormingRadiusBound(), + config.getYLowerFormingRadiusBound(), + config.getZLowerFormingRadiusBound(), config.getXZSlices(), + config.getXYSlices(), config.getYZSlices(), + config.getIgnoreMaterials(), + config.getFallingBlockBehavior(), + config.getFallingBlockReplacement(), + config.getXFillingSeed(), config.getYFillingSeed(), + config.getZFillingSeed()); + } + return null; + } + + public static void spawnCaveAt(Location loc, int length, WormConfig config) { + Worm w = getWorm(loc, length, config); + CaveFormer former = getCaveFormer(config, 0); + + w.forEachRemaining(former::extendLocation); + + System.out.println("Firing event"); // TODO remove this + + Bukkit.getPluginManager().callEvent(new CaveWormGenerationCompletionEvent(config)); + } + + public static GlobalDistributor getDistributer(WormConfig config) { + if (config.getDistributionArea() == null) { + Caveworm.getInstance().warning( + "No area loaded, can't get distributor"); + return null; + } + + return new GlobalDistributor(config, + config.getDistributionSeed(), 39); + } +} diff --git a/src/main/java/com/github/maxopoly/caveworm/WormConfig.java b/src/main/java/com/github/maxopoly/caveworm/WormConfig.java index bd7182e..286c2cd 100644 --- a/src/main/java/com/github/maxopoly/caveworm/WormConfig.java +++ b/src/main/java/com/github/maxopoly/caveworm/WormConfig.java @@ -1,24 +1,15 @@ package com.github.maxopoly.caveworm; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Random; -import java.util.TreeMap; - +import com.github.maxopoly.caveworm.areas.IArea; +import com.github.maxopoly.caveworm.distribution.LocationOffset; +import com.github.maxopoly.caveworm.util.ConfigParsing; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; -import com.github.maxopoly.caveworm.distribution.LocationOffset; - -import vg.civcraft.mc.civmodcore.areas.IArea; -import vg.civcraft.mc.civmodcore.util.ConfigParsing; +import java.util.*; public class WormConfig { - private Random seedPicker; private String wormType; @@ -49,7 +40,6 @@ public class WormConfig { private String caveFormingType; private Material caveFillMaterial; - private byte caveFillData; private int fallingBlockFillingBehavior; private Material fallingBlockReplacement; @@ -77,8 +67,6 @@ public class WormConfig { private int xyFormingSlices; private int yzFormingSlices; - private boolean useHiddenOre; - private IArea distributionArea; private List exclusionAreas; private Collection yScanExclusionMaterials; @@ -94,480 +82,462 @@ public class WormConfig { private Collection fillingIgnoreMaterials; public void parse(Caveworm plugin, FileConfiguration config) { - seedPicker = new Random(); - ConfigurationSection behaviorSection = config - .getConfigurationSection("wormBehavior"); - if (behaviorSection == null) { - plugin.warning("No worm behavior section found, using defaults"); - // maybe user specified stuff wrong, so lets try this, if it doesnt - // work it will just load defaults - behaviorSection = config; - } - wormType = behaviorSection.getString("wormType", "Simplexworm"); - - if (wormType.equals("Simplexworm")) { - xMovementOctaves = behaviorSection - .getInt("xMovementOctaveCount", 3); - yMovementOctaves = behaviorSection - .getInt("yMovementOctaveCount", 3); - zMovementOctaves = behaviorSection - .getInt("zMovementOctaveCount", 3); - - xSpreadAmplitude = behaviorSection.getDouble("xSpreadAmplitude", - 2.0); - ySpreadAmplitude = behaviorSection.getDouble("ySpreadAmplitude", - 2.0); - zSpreadAmplitude = behaviorSection.getDouble("zSpreadAmplitude", - 2.0); - - xSpreadThreshHold = behaviorSection.getDouble("xSpreadThreshHold", - 0.05); - ySpreadThreshHold = behaviorSection.getDouble("ySpreadThreshHold", - 0.05); - zSpreadThreshHold = behaviorSection.getDouble("zSpreadThreshHold", - 0.05); - - xSpreadFrequency = behaviorSection.getDouble("xSpreadFrequency", - 0.1); - ySpreadFrequency = behaviorSection.getDouble("ySpreadFrequency", - 0.1); - zSpreadFrequency = behaviorSection.getDouble("zSpreadFrequency", - 0.1); - xMovementSeed = behaviorSection.getLong("xSeed", -1); - yMovementSeed = behaviorSection.getLong("ySeed", -1); - zMovementSeed = behaviorSection.getLong("zSeed", -1); - } - // parse more worm types here - - ConfigurationSection formingSection = config - .getConfigurationSection("caveFormingBehavior"); - if (formingSection == null) { - plugin.warning("No forming behavior section found, using defaults"); - // maybe user specified stuff wrong, so lets try this, if it doesnt - // work it will just load defaults - formingSection = config; - } - caveFormingType = formingSection.getString("formingType", - "SimplexSphere"); - if (caveFormingType.equals("SimplexSphere")) { - xLowerFormingRadiusBound = formingSection.getDouble( - "xLowerRadiusBound", 2); - yLowerFormingRadiusBound = formingSection.getDouble( - "yLowerRadiusBound", 2); - zLowerFormingRadiusBound = formingSection.getDouble( - "zLowerRadiusBound", 2); - xUpperFormingRadiusBound = formingSection.getDouble( - "xUpperRadiusBound", 6); - yUpperFormingRadiusBound = formingSection.getDouble( - "yUpperRadiusBound", 6); - zUpperFormingRadiusBound = formingSection.getDouble( - "zUpperRadiusBound", 6); - xFormingSimplexFrequency = formingSection.getDouble("xFrequency", - 0.1); - yFormingSimplexFrequency = formingSection.getDouble("yFrequency", - 0.1); - zFormingSimplexFrequency = formingSection.getDouble("zFrequency", - 0.1); - xFormingSimplexOctaves = formingSection.getInt("xOctaves", 3); - yFormingSimplexOctaves = formingSection.getInt("yOctaves", 3); - zFormingSimplexOctaves = formingSection.getInt("zOctaves", 3); - xzFormingSlices = Math.min(formingSection.getInt("xzSlices", 0), - (int) yUpperFormingRadiusBound); - xyFormingSlices = Math.min(formingSection.getInt("xySlices", 0), - (int) zUpperFormingRadiusBound); - yzFormingSlices = Math.min(formingSection.getInt("yzSlices", 0), - (int) xUpperFormingRadiusBound); - useHiddenOre = formingSection.getBoolean("useHiddenOre", false); - String fallingBlockReplacementString = formingSection.getString( - "fallingBlockReplacement", "STONE"); - try { - fallingBlockReplacement = Material - .valueOf(fallingBlockReplacementString); - } catch (IllegalArgumentException e) { - plugin.warning("Specified unknown material name " - + fallingBlockReplacementString + " at " - + formingSection.getCurrentPath() - + ". Defaulting it to stone"); - fallingBlockReplacement = Material.STONE; - } - xFormingSimplexSeed = formingSection.getLong("xSeed", -1); - yFormingSimplexSeed = formingSection.getLong("ySeed", -1); - zFormingSimplexSeed = formingSection.getLong("zSeed", -1); - fallingBlockFillingBehavior = formingSection.getInt( - "fallingBlockBehavior", 0); - if (fallingBlockFillingBehavior < 0 - || fallingBlockFillingBehavior > 2) { - plugin.warning("Falling block behavior was set to illegal value: " - + fallingBlockFillingBehavior + ". Defaulting it to 0"); - fallingBlockFillingBehavior = 0; - } - List ignoreMaterials = formingSection - .getStringList("ignoreMaterials"); - if (ignoreMaterials != null) { - fillingIgnoreMaterials = (ignoreMaterials.size() <= 5) ? new LinkedList() - : new HashSet(); - for (String matString : ignoreMaterials) { - try { - Material ignoreMat = Material.valueOf(matString); - fillingIgnoreMaterials.add(ignoreMat); - } catch (IllegalArgumentException e) { - plugin.warning("Specified ignore material " + matString - + " is not a valid material, skipped it"); - } - } - } - String mat = formingSection.getString("fillMaterial", "AIR"); - String[] matArgs = mat.split(":"); - try { - caveFillMaterial = Material.valueOf(matArgs[0]); - } catch (IllegalArgumentException e) { - plugin.warning("Specified fill material " - + matArgs[0] - + " is not a valid material. Fill material was defaulted to air"); - caveFillMaterial = Material.AIR; - } - if (matArgs.length > 1) { - try { - caveFillData = Byte.parseByte(matArgs[1]); - } catch (NumberFormatException e) { - plugin.warning("You specified " - + matArgs[1] - + " as data value, this is not a valid number. Defaulting to 0"); - caveFillData = 0; - } - } else { - caveFillData = 0; - } - } - - // parse more forming types here - - ConfigurationSection distriSection = config - .getConfigurationSection("distribution"); - if (distriSection != null) { - this.distributionArea = ConfigParsing.parseArea(distriSection - .getConfigurationSection("area")); - if (distributionArea == null) { - plugin.warning("Failed to parse distribution area, can't auto distribute"); - } - ConfigurationSection exclusionSection = distriSection - .getConfigurationSection("excludedAreas"); - exclusionAreas = new ArrayList(); - if (exclusionSection != null) { - for (String exclusionKey : exclusionSection.getKeys(false)) { - IArea exclu = ConfigParsing.parseArea(exclusionSection - .getConfigurationSection(exclusionKey)); - if (exclu != null) { - exclusionAreas.add(exclu); - } - } - - } - this.lowerDistributionYBound = distriSection.getInt("lowerYBound", - 0); - this.upperDistributionYBound = distriSection.getInt("upperYBound", - 255); - this.distributionMinimumSurfaceDistance = distriSection.getInt( - "minimumSurfaceDistance", 5); - this.distributionSeedChance = distriSection.getDouble("seedChance", - 0.05); - this.distributionLowerCaveLengthBound = distriSection.getInt( - "lowerCaveLengthBound", 50); - this.distributionUpperCaveLengthBound = distriSection.getInt( - "upperCaveLengthBound", 200); - this.distributionMinimumCaveLength = distriSection.getInt( - "minimumCaveLength", 30); - this.distributionSeed = distriSection.getLong("seed", -1); - - List yScanIgnoreStrings = distriSection - .getStringList("yScanIgnoreMaterials"); - if (yScanIgnoreStrings != null) { - yScanExclusionMaterials = (yScanIgnoreStrings.size() <= 5) ? new LinkedList() - : new HashSet(); - for (String matString : yScanIgnoreStrings) { - try { - Material ignoreMat = Material.valueOf(matString); - yScanExclusionMaterials.add(ignoreMat); - } catch (IllegalArgumentException e) { - plugin.warning("Specified ignore material " + matString - + " is not a valid material, skipped it"); - } - } - } - - offSetChances = new TreeMap>(); - ConfigurationSection systemConfig = distriSection - .getConfigurationSection("caveSystems"); - double sumChance = 0.0; - if (systemConfig != null) { - for (String key : systemConfig.getKeys(false)) { - ConfigurationSection current = systemConfig - .getConfigurationSection(key); - if (current == null) { - plugin.warning("Found invalid key " + key - + " in caveSystem mapping, could not parse it"); - continue; - } - double chance = current.getDouble("chance"); - ConfigurationSection offSetSection = current - .getConfigurationSection("offSets"); - if (offSetSection == null) { - plugin.warning("Found no offsets specified at " - + current.getCurrentPath() + " skipping it"); - continue; - } - List offsetList = new ArrayList(); - for (String offSetKey : offSetSection.getKeys(false)) { - ConfigurationSection currentOffSetSection = offSetSection - .getConfigurationSection(offSetKey); - if (currentOffSetSection == null) { - plugin.warning("Found invalid key " + key - + " in caveSystem mapping, at " - + offSetSection.toString() - + " could not parse it"); - continue; - } - int xOffset = currentOffSetSection.getInt("xOffSet", 0); - int yOffset = currentOffSetSection.getInt("yOffSet", 0); - int zOffset = currentOffSetSection.getInt("zOffSet", 0); - LocationOffset off = new LocationOffset(xOffset, - yOffset, zOffset); - offsetList.add(off); - } - sumChance += chance; - offSetChances.put(sumChance, offsetList); - } - } - offSetChances.put(1.0, null); - if (sumChance > 1.0) { - plugin.warning("Sum of all chances for cave systems is " - + sumChance + ", this might not work as intended"); - } - long caveSystemSeed = distriSection.getLong("caveSystemSeed", -1); - if (caveSystemSeed == -1) { - this.caveSystemTypePicker = new Random(); - } else { - this.caveSystemTypePicker = new Random(caveSystemSeed); - } - } else { - plugin.warning("Found no distribution parameters in config, automatic distribution is not possible"); - } + seedPicker = new Random(); + ConfigurationSection behaviorSection = config + .getConfigurationSection("wormBehavior"); + if (behaviorSection == null) { + plugin.warning("No worm behavior section found, using defaults"); + // maybe user specified stuff wrong, so lets try this, if it doesnt + // work it will just load defaults + behaviorSection = config; + } + wormType = behaviorSection.getString("wormType", "Simplexworm"); + + if (wormType.equals("Simplexworm")) { + xMovementOctaves = behaviorSection + .getInt("xMovementOctaveCount", 3); + yMovementOctaves = behaviorSection + .getInt("yMovementOctaveCount", 3); + zMovementOctaves = behaviorSection + .getInt("zMovementOctaveCount", 3); + + xSpreadAmplitude = behaviorSection.getDouble("xSpreadAmplitude", + 2.0); + ySpreadAmplitude = behaviorSection.getDouble("ySpreadAmplitude", + 2.0); + zSpreadAmplitude = behaviorSection.getDouble("zSpreadAmplitude", + 2.0); + + xSpreadThreshHold = behaviorSection.getDouble("xSpreadThreshHold", + 0.05); + ySpreadThreshHold = behaviorSection.getDouble("ySpreadThreshHold", + 0.05); + zSpreadThreshHold = behaviorSection.getDouble("zSpreadThreshHold", + 0.05); + + xSpreadFrequency = behaviorSection.getDouble("xSpreadFrequency", + 0.1); + ySpreadFrequency = behaviorSection.getDouble("ySpreadFrequency", + 0.1); + zSpreadFrequency = behaviorSection.getDouble("zSpreadFrequency", + 0.1); + xMovementSeed = behaviorSection.getLong("xSeed", -1); + yMovementSeed = behaviorSection.getLong("ySeed", -1); + zMovementSeed = behaviorSection.getLong("zSeed", -1); + } + // parse more worm types here + + ConfigurationSection formingSection = config + .getConfigurationSection("caveFormingBehavior"); + if (formingSection == null) { + plugin.warning("No forming behavior section found, using defaults"); + // maybe user specified stuff wrong, so lets try this, if it doesnt + // work it will just load defaults + formingSection = config; + } + caveFormingType = formingSection.getString("formingType", + "SimplexSphere"); + if (caveFormingType.equals("SimplexSphere")) { + xLowerFormingRadiusBound = formingSection.getDouble( + "xLowerRadiusBound", 2); + yLowerFormingRadiusBound = formingSection.getDouble( + "yLowerRadiusBound", 2); + zLowerFormingRadiusBound = formingSection.getDouble( + "zLowerRadiusBound", 2); + xUpperFormingRadiusBound = formingSection.getDouble( + "xUpperRadiusBound", 6); + yUpperFormingRadiusBound = formingSection.getDouble( + "yUpperRadiusBound", 6); + zUpperFormingRadiusBound = formingSection.getDouble( + "zUpperRadiusBound", 6); + xFormingSimplexFrequency = formingSection.getDouble("xFrequency", + 0.1); + yFormingSimplexFrequency = formingSection.getDouble("yFrequency", + 0.1); + zFormingSimplexFrequency = formingSection.getDouble("zFrequency", + 0.1); + xFormingSimplexOctaves = formingSection.getInt("xOctaves", 3); + yFormingSimplexOctaves = formingSection.getInt("yOctaves", 3); + zFormingSimplexOctaves = formingSection.getInt("zOctaves", 3); + xzFormingSlices = Math.min(formingSection.getInt("xzSlices", 0), + (int) yUpperFormingRadiusBound); + xyFormingSlices = Math.min(formingSection.getInt("xySlices", 0), + (int) zUpperFormingRadiusBound); + yzFormingSlices = Math.min(formingSection.getInt("yzSlices", 0), + (int) xUpperFormingRadiusBound); + String fallingBlockReplacementString = formingSection.getString( + "fallingBlockReplacement", "STONE"); + try { + fallingBlockReplacement = Material + .valueOf(fallingBlockReplacementString); + } catch (IllegalArgumentException e) { + plugin.warning("Specified unknown material name " + + fallingBlockReplacementString + " at " + + formingSection.getCurrentPath() + + ". Defaulting it to stone"); + fallingBlockReplacement = Material.STONE; + } + xFormingSimplexSeed = formingSection.getLong("xSeed", -1); + yFormingSimplexSeed = formingSection.getLong("ySeed", -1); + zFormingSimplexSeed = formingSection.getLong("zSeed", -1); + fallingBlockFillingBehavior = formingSection.getInt( + "fallingBlockBehavior", 0); + if (fallingBlockFillingBehavior < 0 + || fallingBlockFillingBehavior > 2) { + plugin.warning("Falling block behavior was set to illegal value: " + + fallingBlockFillingBehavior + ". Defaulting it to 0"); + fallingBlockFillingBehavior = 0; + } + List ignoreMaterials = formingSection + .getStringList("ignoreMaterials"); + fillingIgnoreMaterials = (ignoreMaterials.size() <= 5) ? new LinkedList<>() + : new HashSet<>(); + for (String matString : ignoreMaterials) { + try { + Material ignoreMat = Material.valueOf(matString); + fillingIgnoreMaterials.add(ignoreMat); + } catch (IllegalArgumentException e) { + plugin.warning("Specified ignore material " + matString + + " is not a valid material, skipped it"); + } + } + String mat = formingSection.getString("fillMaterial", "AIR"); + String[] matArgs = mat.split(":"); + try { + caveFillMaterial = Material.valueOf(matArgs[0]); + } catch (IllegalArgumentException e) { + plugin.warning("Specified fill material " + + matArgs[0] + + " is not a valid material. Fill material was defaulted to air"); + caveFillMaterial = Material.AIR; + } + if (matArgs.length > 1) { + plugin.warning("You specified " + + matArgs[1] + + " as data value, this format is no longer supported in 1.21.5!"); + } + } + + // parse more forming types here + + ConfigurationSection distriSection = config + .getConfigurationSection("distribution"); + if (distriSection != null) { + this.distributionArea = ConfigParsing.parseArea(distriSection + .getConfigurationSection("area")); + if (distributionArea == null) { + plugin.warning("Failed to parse distribution area, can't auto distribute"); + } + ConfigurationSection exclusionSection = distriSection + .getConfigurationSection("excludedAreas"); + exclusionAreas = new ArrayList(); + if (exclusionSection != null) { + for (String exclusionKey : exclusionSection.getKeys(false)) { + IArea exclu = ConfigParsing.parseArea(exclusionSection + .getConfigurationSection(exclusionKey)); + if (exclu != null) { + exclusionAreas.add(exclu); + } + } + + } + this.lowerDistributionYBound = distriSection.getInt("lowerYBound", + 0); + this.upperDistributionYBound = distriSection.getInt("upperYBound", + 255); + this.distributionMinimumSurfaceDistance = distriSection.getInt( + "minimumSurfaceDistance", 5); + this.distributionSeedChance = distriSection.getDouble("seedChance", + 0.05); + this.distributionLowerCaveLengthBound = distriSection.getInt( + "lowerCaveLengthBound", 50); + this.distributionUpperCaveLengthBound = distriSection.getInt( + "upperCaveLengthBound", 200); + this.distributionMinimumCaveLength = distriSection.getInt( + "minimumCaveLength", 30); + this.distributionSeed = distriSection.getLong("seed", -1); + + List yScanIgnoreStrings = distriSection + .getStringList("yScanIgnoreMaterials"); + if (yScanIgnoreStrings != null) { + yScanExclusionMaterials = (yScanIgnoreStrings.size() <= 5) ? new LinkedList() + : new HashSet(); + for (String matString : yScanIgnoreStrings) { + try { + Material ignoreMat = Material.valueOf(matString); + yScanExclusionMaterials.add(ignoreMat); + } catch (IllegalArgumentException e) { + plugin.warning("Specified ignore material " + matString + + " is not a valid material, skipped it"); + } + } + } + + offSetChances = new TreeMap<>(); + ConfigurationSection systemConfig = distriSection + .getConfigurationSection("caveSystems"); + double sumChance = 0.0; + if (systemConfig != null) { + for (String key : systemConfig.getKeys(false)) { + ConfigurationSection current = systemConfig + .getConfigurationSection(key); + if (current == null) { + plugin.warning("Found invalid key " + key + + " in caveSystem mapping, could not parse it"); + continue; + } + double chance = current.getDouble("chance"); + ConfigurationSection offSetSection = current + .getConfigurationSection("offSets"); + if (offSetSection == null) { + plugin.warning("Found no offsets specified at " + + current.getCurrentPath() + " skipping it"); + continue; + } + List offsetList = new ArrayList(); + for (String offSetKey : offSetSection.getKeys(false)) { + ConfigurationSection currentOffSetSection = offSetSection + .getConfigurationSection(offSetKey); + if (currentOffSetSection == null) { + plugin.warning("Found invalid key " + key + + " in caveSystem mapping, at " + + offSetSection + + " could not parse it"); + continue; + } + int xOffset = currentOffSetSection.getInt("xOffSet", 0); + int yOffset = currentOffSetSection.getInt("yOffSet", 0); + int zOffset = currentOffSetSection.getInt("zOffSet", 0); + LocationOffset off = new LocationOffset(xOffset, + yOffset, zOffset); + offsetList.add(off); + } + sumChance += chance; + offSetChances.put(sumChance, offsetList); + } + } + offSetChances.put(1.0, null); + if (sumChance > 1.0) { + plugin.warning("Sum of all chances for cave systems is " + + sumChance + ", this might not work as intended"); + } + long caveSystemSeed = distriSection.getLong("caveSystemSeed", -1); + if (caveSystemSeed == -1) { + this.caveSystemTypePicker = new Random(); + } else { + this.caveSystemTypePicker = new Random(caveSystemSeed); + } + } else { + plugin.warning("Found no distribution parameters in config, automatic distribution is not possible"); + } } public int getXMovementOctaves() { - return xMovementOctaves; + return xMovementOctaves; } public int getYMovementOctaves() { - return yMovementOctaves; + return yMovementOctaves; } public int getZMovementOctaves() { - return zMovementOctaves; + return zMovementOctaves; } public double getXSpreadFrequency() { - return xSpreadFrequency; + return xSpreadFrequency; } public double getYSpreadFrequency() { - return ySpreadFrequency; + return ySpreadFrequency; } public double getZSpreadFrequency() { - return zSpreadFrequency; + return zSpreadFrequency; } public double getXSpreadAmplitude() { - return xSpreadAmplitude; + return xSpreadAmplitude; } public double getYSpreadAmplitude() { - return ySpreadAmplitude; + return ySpreadAmplitude; } public double getZSpreadAmplitude() { - return zSpreadAmplitude; + return zSpreadAmplitude; } public double getXSpreadThreshHold() { - return xSpreadThreshHold; + return xSpreadThreshHold; } public double getYSpreadThreshHold() { - return ySpreadThreshHold; + return ySpreadThreshHold; } public double getZSpreadThreshHold() { - return zSpreadThreshHold; + return zSpreadThreshHold; } public String getWormType() { - return wormType; + return wormType; } public String getFormingType() { - return caveFormingType; + return caveFormingType; } public Material getFormingFillMaterial() { - return caveFillMaterial; + return caveFillMaterial; } public double getXFormingFrequency() { - return xFormingSimplexFrequency; + return xFormingSimplexFrequency; } public double getYFormingFrequency() { - return yFormingSimplexFrequency; + return yFormingSimplexFrequency; } public double getZFormingFrequency() { - return zFormingSimplexFrequency; + return zFormingSimplexFrequency; } public int getXFormingOctaveCount() { - return xFormingSimplexOctaves; + return xFormingSimplexOctaves; } public int getYFormingOctaveCount() { - return yFormingSimplexOctaves; + return yFormingSimplexOctaves; } public int getZFormingOctaveCount() { - return zFormingSimplexOctaves; + return zFormingSimplexOctaves; } public double getXLowerFormingRadiusBound() { - return xLowerFormingRadiusBound; + return xLowerFormingRadiusBound; } public double getYLowerFormingRadiusBound() { - return yLowerFormingRadiusBound; + return yLowerFormingRadiusBound; } public double getZLowerFormingRadiusBound() { - return zLowerFormingRadiusBound; + return zLowerFormingRadiusBound; } public double getXUpperFormingRadiusBound() { - return xUpperFormingRadiusBound; + return xUpperFormingRadiusBound; } public double getYUpperFormingRadiusBound() { - return yUpperFormingRadiusBound; + return yUpperFormingRadiusBound; } public double getZUpperFormingRadiusBound() { - return zUpperFormingRadiusBound; + return zUpperFormingRadiusBound; } public Collection getIgnoreMaterials() { - return fillingIgnoreMaterials; + return fillingIgnoreMaterials; } public int getXZSlices() { - return xzFormingSlices; + return xzFormingSlices; } public int getXYSlices() { - return xyFormingSlices; + return xyFormingSlices; } public int getYZSlices() { - return yzFormingSlices; + return yzFormingSlices; } public long getXWormMovementSeed() { - return (xMovementSeed == -1) ? seedPicker.nextLong() : xMovementSeed; + return (xMovementSeed == -1) ? seedPicker.nextLong() : xMovementSeed; } public long getYWormMovementSeed() { - return (yMovementSeed == -1) ? seedPicker.nextLong() : yMovementSeed; + return (yMovementSeed == -1) ? seedPicker.nextLong() : yMovementSeed; } public long getZWormMovementSeed() { - return (zMovementSeed == -1) ? seedPicker.nextLong() : zMovementSeed; + return (zMovementSeed == -1) ? seedPicker.nextLong() : zMovementSeed; } public long getXFillingSeed() { - return (xFormingSimplexSeed == -1) ? seedPicker.nextLong() - : xFormingSimplexSeed; + return (xFormingSimplexSeed == -1) ? seedPicker.nextLong() + : xFormingSimplexSeed; } public long getYFillingSeed() { - return (yFormingSimplexSeed == -1) ? seedPicker.nextLong() - : yFormingSimplexSeed; + return (yFormingSimplexSeed == -1) ? seedPicker.nextLong() + : yFormingSimplexSeed; } public long getZFillingSeed() { - return (zFormingSimplexSeed == -1) ? seedPicker.nextLong() - : zFormingSimplexSeed; + return (zFormingSimplexSeed == -1) ? seedPicker.nextLong() + : zFormingSimplexSeed; } public IArea getDistributionArea() { - return distributionArea; + return distributionArea; } public int getLowerDistributionYBound() { - return lowerDistributionYBound; + return lowerDistributionYBound; } public int getUpperDistributionYBound() { - return upperDistributionYBound; + return upperDistributionYBound; } public int getMinimumDistributionSurfaceDistance() { - return distributionMinimumSurfaceDistance; + return distributionMinimumSurfaceDistance; } public double getDistributionSeedChance() { - return distributionSeedChance; + return distributionSeedChance; } public int getLowerDistributionCaveLengthBound() { - return distributionLowerCaveLengthBound; + return distributionLowerCaveLengthBound; } public int getUpperDistributionCaveLengthBound() { - return distributionUpperCaveLengthBound; + return distributionUpperCaveLengthBound; } public int getMinimumDistributionCaveLength() { - return distributionMinimumCaveLength; + return distributionMinimumCaveLength; } public long getDistributionSeed() { - return distributionSeed == -1 ? new Random().nextLong() - : distributionSeed; - } - - public boolean useHiddenOre() { - return useHiddenOre; + return distributionSeed == -1 ? new Random().nextLong() + : distributionSeed; } public List getRandomLocationOffSet() { - return offSetChances.ceilingEntry(caveSystemTypePicker.nextDouble()) - .getValue(); - } - - public byte getFillData() { - return caveFillData; + return offSetChances.ceilingEntry(caveSystemTypePicker.nextDouble()) + .getValue(); } public Collection getDistributionYScanExclusionMaterials() { - return yScanExclusionMaterials; + return yScanExclusionMaterials; } public List getExclusionAreas() { - return exclusionAreas; + return exclusionAreas; } public int getFallingBlockBehavior() { - return fallingBlockFillingBehavior; + return fallingBlockFillingBehavior; } public Material getFallingBlockReplacement() { - return fallingBlockReplacement; + return fallingBlockReplacement; } } diff --git a/src/main/java/com/github/maxopoly/caveworm/areas/AbstractYLimitedArea.java b/src/main/java/com/github/maxopoly/caveworm/areas/AbstractYLimitedArea.java new file mode 100644 index 0000000..08dbba1 --- /dev/null +++ b/src/main/java/com/github/maxopoly/caveworm/areas/AbstractYLimitedArea.java @@ -0,0 +1,38 @@ +package com.github.maxopoly.caveworm.areas; + +import org.bukkit.Location; + +public abstract class AbstractYLimitedArea implements IArea { + + private final double lowerYBound; + + private final double upperYBound; + + public AbstractYLimitedArea(double lowerYBound, double upperYBound) { + if (lowerYBound > upperYBound) { + throw new IllegalArgumentException("Lower bound can't be bigger upper one"); + } + this.lowerYBound = lowerYBound; + this.upperYBound = upperYBound; + } + + @Override + public boolean isInArea(Location loc) { + return loc.getY() <= upperYBound && loc.getY() >= lowerYBound; + } + + /** + * @return The lowest y-level from which upwards locations can be included in this area (inclusive) + */ + public double getLowerYBound() { + return lowerYBound; + } + + /** + * @return The highest y-level from which downwards location can be included in this area (inclusive) + */ + public double getUpperYBound() { + return upperYBound; + } + +} \ No newline at end of file diff --git a/src/main/java/com/github/maxopoly/caveworm/areas/EllipseArea.java b/src/main/java/com/github/maxopoly/caveworm/areas/EllipseArea.java new file mode 100644 index 0000000..a043d9b --- /dev/null +++ b/src/main/java/com/github/maxopoly/caveworm/areas/EllipseArea.java @@ -0,0 +1,92 @@ +package com.github.maxopoly.caveworm.areas; + +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; + +import java.util.Collection; +import java.util.HashSet; + +public class EllipseArea extends AbstractYLimitedArea { + + private final Location center; + + private final double xSize; + + private final double zSize; + + public EllipseArea(double lowerYBound, double upperYBound, Location center, double xSize, double zSize) { + super(lowerYBound, upperYBound); + this.center = center; + this.xSize = xSize; + this.zSize = zSize; + } + + @Override + public Collection getChunks() { + Collection chunks = new HashSet<>(); + for (double x = center.getX() - xSize; x <= center.getX() + xSize; x += 16) { + for (double z = center.getZ() - zSize; z <= center.getZ() + zSize; z += 16) { + Chunk c = new Location(center.getWorld(), x, center.getY(), z).getChunk(); + // if one of the corners is in the area the chunk is inside + if (isInArea(new Location(c.getWorld(), c.getX() * 16, 0, (c.getZ() * 16) + 15)) + || isInArea(new Location(c.getWorld(), c.getX() * 16, 0, c.getZ() * 16)) + || isInArea(new Location(c.getWorld(), (c.getX() * 16) + 15, 0, c.getZ() * 16)) + || isInArea(new Location(c.getWorld(), (c.getX() * 16) + 15, 0, (c.getZ() * 16) + 15))) { + chunks.add(c); + } + } + } + return chunks; + } + + @Override + public Location getCenter() { + return center; + } + + @Override + public World getWorld() { + return center.getWorld(); + } + + @Override + public boolean isInArea(Location loc) { + double xDist = center.getX() - loc.getX(); + double zDist = center.getZ() - loc.getZ(); + return super.isInArea(loc) && ((xDist * xDist) / (xSize * xSize)) + ((zDist * zDist) / (zSize * zSize)) <= 1; + } + + /** + * @return Half of the diameter of this ellipse in x dimension + */ + public double getXSize() { + return xSize; + } + + /** + * @return Half of the diameter of this ellipse in z dimension + */ + public double getZSize() { + return zSize; + } + + @Override + public Collection getPseudoChunks() { + Collection chunks = new HashSet<>(); + for (int x = (int) (center.getX() - xSize); x <= center.getX() + xSize; x += 16) { + for (int z = (int) (center.getZ() - zSize); z <= center.getZ() + zSize; z += 16) { + PseudoChunk c = new PseudoChunk(center.getWorld(), x / 16, z / 16); + // if one of the corners is in the area the chunk is inside + if (isInArea(new Location(c.getWorld(), c.getX() * 16, 0, (c.getZ() * 16) + 15)) + || isInArea(new Location(c.getWorld(), c.getX() * 16, 0, c.getZ() * 16)) + || isInArea(new Location(c.getWorld(), (c.getX() * 16) + 15, 0, c.getZ() * 16)) + || isInArea(new Location(c.getWorld(), (c.getX() * 16) + 15, 0, (c.getZ() * 16) + 15))) { + chunks.add(c); + } + } + } + return chunks; + } + +} \ No newline at end of file diff --git a/src/main/java/com/github/maxopoly/caveworm/areas/GlobalYLimitedArea.java b/src/main/java/com/github/maxopoly/caveworm/areas/GlobalYLimitedArea.java new file mode 100644 index 0000000..fe32308 --- /dev/null +++ b/src/main/java/com/github/maxopoly/caveworm/areas/GlobalYLimitedArea.java @@ -0,0 +1,46 @@ +package com.github.maxopoly.caveworm.areas; + +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; + +import java.util.Collection; + +public class GlobalYLimitedArea extends AbstractYLimitedArea { + + private final World world; + + public GlobalYLimitedArea(double lowerYBound, double upperYBound, World world) { + super(lowerYBound, upperYBound); + this.world = world; + } + + /** + * @return Null, because this area includes an infinite amount of chunks + */ + @Override + public Collection getChunks() { + return null; + } + + @Override + public Location getCenter() { + return new Location(world, 0, 0, 0); + } + + @Override + public World getWorld() { + return world; + } + + @Override + public boolean isInArea(Location loc) { + return super.isInArea(loc) && loc.getWorld().getUID().equals(world.getUID()); + } + + @Override + public Collection getPseudoChunks() { + return null; + } + +} \ No newline at end of file diff --git a/src/main/java/com/github/maxopoly/caveworm/areas/IArea.java b/src/main/java/com/github/maxopoly/caveworm/areas/IArea.java new file mode 100644 index 0000000..dfbac7d --- /dev/null +++ b/src/main/java/com/github/maxopoly/caveworm/areas/IArea.java @@ -0,0 +1,46 @@ +package com.github.maxopoly.caveworm.areas; + +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; + +import java.util.Collection; + +public interface IArea { + + /** + * Checks whether a given location is inside the defined area + * + * @param loc Location to check + * @return True if the given location is inside the area, false if not + */ + boolean isInArea(Location loc); + + /** + * Collects all chunks which are (partially) inside the defined area. If the area contains an infinite amount of + * chunks, this will return null + * + * @return All chunks in the area or null in case of an infinite size + */ + Collection getChunks(); + + /** + * Collects all chunks which are (partially) inside the defined area. Instead of actual chunk objects, which require + * the chunk behind it to be loaded, this will only return pseudo chunks, which contain the right chunk coordinates + * for it to be loaded later on + * + * @return All chunks in the area represented through pseudo chunks or null in case of an infinite size + */ + Collection getPseudoChunks(); + + /** + * @return Center of this area + */ + Location getCenter(); + + /** + * @return World in which this area is + */ + World getWorld(); + +} \ No newline at end of file diff --git a/src/main/java/com/github/maxopoly/caveworm/areas/PseudoChunk.java b/src/main/java/com/github/maxopoly/caveworm/areas/PseudoChunk.java new file mode 100644 index 0000000..a2083ed --- /dev/null +++ b/src/main/java/com/github/maxopoly/caveworm/areas/PseudoChunk.java @@ -0,0 +1,44 @@ +package com.github.maxopoly.caveworm.areas; + +import org.bukkit.Chunk; +import org.bukkit.World; + +public class PseudoChunk { + + private final World world; + + private final int x; + + private final int z; + + public PseudoChunk(World w, int x, int z) { + this.world = w; + this.x = x; + this.z = z; + } + + public int getX() { + return x; + } + + public int getZ() { + return z; + } + + public World getWorld() { + return world; + } + + public int getActualX() { + return x * 16; + } + + public int getActualZ() { + return z * 16; + } + + public Chunk getActualChunk() { + return world.getChunkAt(x, z); + } + +} \ No newline at end of file diff --git a/src/main/java/com/github/maxopoly/caveworm/areas/RectangleArea.java b/src/main/java/com/github/maxopoly/caveworm/areas/RectangleArea.java new file mode 100644 index 0000000..3d02cbc --- /dev/null +++ b/src/main/java/com/github/maxopoly/caveworm/areas/RectangleArea.java @@ -0,0 +1,84 @@ +package com.github.maxopoly.caveworm.areas; + +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; + +import java.util.Collection; +import java.util.HashSet; + +public class RectangleArea extends AbstractYLimitedArea { + + private final Location center; + + private final double xSize; + + private final double zSize; + + public RectangleArea(double lowerYBound, double upperYBound, Location center, double xSize, double zSize) { + super(lowerYBound, upperYBound); + this.center = center; + this.xSize = xSize; + this.zSize = zSize; + } + + @Override + public Collection getChunks() { + Collection chunks = new HashSet<>(); + for (double x = center.getX() - xSize; x <= center.getX() + xSize; x += 16) { + for (double z = center.getZ() - zSize; z <= center.getZ() + zSize; z += 16) { + chunks.add(new Location(center.getWorld(), x, center.getY(), z).getChunk()); + } + // last one might have been skipped + chunks.add(new Location(center.getWorld(), x, center.getY(), center.getZ() + zSize).getChunk()); + } + return chunks; + } + + @Override + public boolean isInArea(Location loc) { + double x = loc.getX(); + double z = loc.getZ(); + return loc.getWorld().getUID().equals(getWorld().getUID()) && (center.getX() - xSize) <= x + && (center.getX() + xSize) >= x && (center.getZ() - zSize) <= z && (center.getZ() + zSize) >= z + && super.isInArea(loc); + } + + @Override + public Location getCenter() { + return center; + } + + @Override + public World getWorld() { + return center.getWorld(); + } + + /** + * @return Half of the diameter of this rectangle in x dimension + */ + public double getXSize() { + return xSize; + } + + /** + * @return Half of the diameter of this rectangle in z dimension + */ + public double getZSize() { + return zSize; + } + + @Override + public Collection getPseudoChunks() { + Collection chunks = new HashSet<>(); + for (int x = (int) (center.getX() - xSize); x <= center.getX() + xSize; x += 16) { + for (int z = (int) (center.getZ() - zSize); z <= center.getZ() + zSize; z += 16) { + chunks.add(new PseudoChunk(center.getWorld(), x / 16, z / 16)); + } + // last one might have been skipped + chunks.add(new PseudoChunk(center.getWorld(), x / 16, ((int) (center.getZ() + zSize)) / 16)); + } + return chunks; + } + +} \ No newline at end of file diff --git a/src/main/java/com/github/maxopoly/caveworm/blockModifications/FormingQueue.java b/src/main/java/com/github/maxopoly/caveworm/blockModifications/FormingQueue.java deleted file mode 100644 index 6b58deb..0000000 --- a/src/main/java/com/github/maxopoly/caveworm/blockModifications/FormingQueue.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.github.maxopoly.caveworm.blockModifications; - -import java.util.Collection; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; - -import org.bukkit.Bukkit; -import org.bukkit.Location; - -import com.github.maxopoly.caveworm.CaveWormAPI; -import com.github.maxopoly.caveworm.Caveworm; -import com.github.maxopoly.caveworm.WormConfig; -import com.github.maxopoly.caveworm.caveFormers.SimplexSphereFormer; -import com.github.maxopoly.caveworm.distribution.JobQueue; - -public class FormingQueue implements Runnable { - - private Queue pending; - private int modificationsPerTick; - private WormConfig config; - private SimplexSphereFormer former; - private JobQueue jobs; - - // private to avoid explicit instanciating - public FormingQueue(WormConfig config, int modificationsPerTick) { - this.pending = new ConcurrentLinkedQueue(); - Bukkit.getScheduler().scheduleSyncRepeatingTask(Caveworm.getInstance(), - this, 1L, 1L); - this.modificationsPerTick = modificationsPerTick; - this.config = config; - former = CaveWormAPI.getCaveFormer(config, 0); - this.jobs = JobQueue.getInstance(); - } - - public void add(Location modification) { - pending.add(modification); - } - - public void addAll(Collection locations) { - pending.addAll(locations); - } - - @Override - public void run() { - if (pending.size() == 0) { - return; - } - int i = 0; - while (!pending.isEmpty() && i < modificationsPerTick) { - former.extendLocation(pending.remove()); - i++; - } - Caveworm.getInstance().info( - "Finished expanding locations for this tick, currently left in queue: " - + pending.size() + "; Additional job not started yet: " - + jobs.getWaitingJobCount()); - } -} diff --git a/src/main/java/com/github/maxopoly/caveworm/blockmodifications/FormingQueue.java b/src/main/java/com/github/maxopoly/caveworm/blockmodifications/FormingQueue.java new file mode 100644 index 0000000..0f2da70 --- /dev/null +++ b/src/main/java/com/github/maxopoly/caveworm/blockmodifications/FormingQueue.java @@ -0,0 +1,57 @@ +package com.github.maxopoly.caveworm.blockmodifications; + +import com.github.maxopoly.caveworm.Caveworm; +import com.github.maxopoly.caveworm.CavewormAPI; +import com.github.maxopoly.caveworm.WormConfig; +import com.github.maxopoly.caveworm.caveformers.SimplexSphereFormer; +import com.github.maxopoly.caveworm.distribution.JobQueue; +import org.bukkit.Bukkit; +import org.bukkit.Location; + +import java.util.Collection; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +public class FormingQueue implements Runnable { + + private final Queue pending; + private final int modificationsPerTick; + private final WormConfig config; + private final SimplexSphereFormer former; + private final JobQueue jobs; + + // private to avoid explicit instanciating + public FormingQueue(WormConfig config, int modificationsPerTick) { + this.pending = new ConcurrentLinkedQueue(); + Bukkit.getScheduler().scheduleSyncRepeatingTask(Caveworm.getInstance(), + this, 1L, 1L); + this.modificationsPerTick = modificationsPerTick; + this.config = config; + former = CavewormAPI.getCaveFormer(config, 0); + this.jobs = JobQueue.getInstance(); + } + + public void add(Location modification) { + pending.add(modification); + } + + public void addAll(Collection locations) { + pending.addAll(locations); + } + + @Override + public void run() { + if (pending.size() == 0) { + return; + } + int i = 0; + while (!pending.isEmpty() && i < modificationsPerTick) { + former.extendLocation(pending.remove()); + i++; + } + Caveworm.getInstance().info( + "Finished expanding locations for this tick, currently left in queue: " + + pending.size() + "; Additional job not started yet: " + + jobs.getWaitingJobCount()); + } +} diff --git a/src/main/java/com/github/maxopoly/caveworm/caveFormers/CaveFormer.java b/src/main/java/com/github/maxopoly/caveworm/caveFormers/CaveFormer.java deleted file mode 100644 index 48cfd9c..0000000 --- a/src/main/java/com/github/maxopoly/caveworm/caveFormers/CaveFormer.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.github.maxopoly.caveworm.caveFormers; - -import org.bukkit.Location; - -public interface CaveFormer { - - public void extendLocation(Location loc); - -} diff --git a/src/main/java/com/github/maxopoly/caveworm/caveFormers/SimplexSphereFormer.java b/src/main/java/com/github/maxopoly/caveworm/caveFormers/SimplexSphereFormer.java deleted file mode 100644 index 8a9969b..0000000 --- a/src/main/java/com/github/maxopoly/caveworm/caveFormers/SimplexSphereFormer.java +++ /dev/null @@ -1,304 +0,0 @@ -package com.github.maxopoly.caveworm.caveFormers; - -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; -import java.util.Random; - -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.util.noise.SimplexNoiseGenerator; - -import com.github.maxopoly.caveworm.Caveworm; -import com.github.maxopoly.caveworm.external.HiddenOreManager; - -public class SimplexSphereFormer implements CaveFormer { - - private SimplexNoiseGenerator xGenerator; - private SimplexNoiseGenerator yGenerator; - private SimplexNoiseGenerator zGenerator; - - private Material replacementMaterial; - private byte replacementData; - private double amplitude; - private Collection ignoreMaterials; - private HiddenOreManager hiddenOreManager; - - private int xOctaves; - private int yOctaves; - private int zOctaves; - - private double xSpreadFrequency; - private double ySpreadFrequency; - private double zSpreadFrequency; - - private double xUpperRadiusBound; - private double yUpperRadiusBound; - private double zUpperRadiusBound; - - private double xLowerRadiusBound; - private double yLowerRadiusBound; - private double zLowerRadiusBound; - - private int xzSlices; - private int xySlices; - private int yzSlices; - - private FallingBlockHandler fallingBlockHandler; - - private List doLater; - private List doLaterCenters; - - private int id; - - public SimplexSphereFormer(int id, Material replacementMaterial, - boolean useHiddenOre, byte replacementData, int xOctaves, - int yOctaves, int zOctaves, double xSpreadFrequency, - double ySpreadFrequency, double zSpreadFrequency, - double xUpperRadiusBound, double yUpperRadiusBound, - double zUpperRadiusBound, double xLowerRadiusBound, - double yLowerRadiusBound, double zLowerRadiusBound, int xzSlices, - int xySlices, int yzSlices, Collection materialsToIgnore, - int fallingBlockBehavior, Material fallingBlockReplacement, - long xSeed, long ySeed, long zSeed) { - this.replacementMaterial = replacementMaterial; - this.amplitude = 2.0; // hardcoded to ensure it properly scales with the - // bounds - this.id = id; - this.xGenerator = new SimplexNoiseGenerator(xSeed); - this.yGenerator = new SimplexNoiseGenerator(ySeed); - this.zGenerator = new SimplexNoiseGenerator(zSeed); - this.xOctaves = xOctaves; - this.yOctaves = yOctaves; - this.zOctaves = zOctaves; - this.xSpreadFrequency = xSpreadFrequency; - this.ySpreadFrequency = ySpreadFrequency; - this.zSpreadFrequency = zSpreadFrequency; - this.xUpperRadiusBound = xUpperRadiusBound; - this.yUpperRadiusBound = yUpperRadiusBound; - this.zUpperRadiusBound = zUpperRadiusBound; - this.xLowerRadiusBound = xLowerRadiusBound; - this.yLowerRadiusBound = yLowerRadiusBound; - this.zLowerRadiusBound = zLowerRadiusBound; - this.xySlices = xySlices; - this.xzSlices = xzSlices; - this.yzSlices = yzSlices; - this.doLater = new LinkedList(); - this.ignoreMaterials = materialsToIgnore; - this.replacementData = replacementData; - if (useHiddenOre) { - if (Bukkit.getPluginManager().isPluginEnabled("HiddenOre")) { - hiddenOreManager = new HiddenOreManager(); - } else { - Caveworm.getInstance() - .warning( - "Attempted to send block break events to HiddenOre according to config, but it seems like HiddenOre isn't loaded on this server"); - hiddenOreManager = null; - } - } - switch (fallingBlockBehavior) { - case 0: - // ignore the fact that there's a falling block and clear the block - // below anyway - fallingBlockHandler = (b) -> { - executeBlockModification(b); - }; - break; - case 1: - // dont clear the block - fallingBlockHandler = (b) -> { - }; - break; - case 2: - // move the block one upwards instead of clearing it and if the - // block moved is gravity affected as well, instead another block is - // put in place - fallingBlockHandler = (b) -> { - Block above = b.getRelative(BlockFace.UP); - if (b.getType().hasGravity()) { - above.setType(fallingBlockReplacement); - executeBlockModification(b); - } else { - above.setTypeIdAndData(b.getType().getId(), b.getData(), - false); - executeBlockModification(b); - } - }; - break; - default: - throw new IllegalArgumentException(); - } - } - - public SimplexSphereFormer(int id, Material replacementMaterial, - boolean useHiddenOre, byte replacementData, int xOctaves, - int yOctaves, int zOctaves, double xSpreadFrequency, - double ySpreadFrequency, double zSpreadFrequency, - double xUpperRadiusBound, double yUpperRadiusBound, - double zUpperRadiusBound, double xLowerRadiusBound, - double yLowerRadiusBound, double zLowerRadiusBound, int xzSlices, - int xySlices, int yzSlices, Collection materialsToIgnore, - int fallingBlockBehavior, Material fallingBlockReplacement) { - this(id, replacementMaterial, useHiddenOre, replacementData, xOctaves, - yOctaves, zOctaves, xSpreadFrequency, ySpreadFrequency, - zSpreadFrequency, xUpperRadiusBound, yUpperRadiusBound, - zUpperRadiusBound, xLowerRadiusBound, yLowerRadiusBound, - zLowerRadiusBound, xzSlices, xySlices, yzSlices, - materialsToIgnore, fallingBlockBehavior, - fallingBlockReplacement, new Random().nextLong(), new Random() - .nextLong(), new Random().nextLong()); - } - - public void clearRemaining() { - int failCounter = 0; - while (doLater.size() != 0) { - int startSize = doLater.size(); - // copy in new array to avoid concurrent problems when forming fails - // while doing this - Location[] locsToDoNow = doLater.toArray(new Location[startSize]); - doLater.clear(); - for (Location loc : locsToDoNow) { - clearBlock(loc); - } - System.out.println("Cleanupqueue for thread " + id + " processed " - + (startSize - doLater.size()) + " locations, " - + doLater.size() + " left "); - if (startSize == doLater.size()) { - failCounter++; - try { - Thread.sleep(5); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } else { - failCounter = 0; - } - if (failCounter >= 1000) { - return; - } - } - } - - public void extendLocation(Location loc) { - // always clear center block - clearBlock(loc); - // calculate x distance blocks must be within - double currentXRange = xGenerator.noise(loc.getX(), loc.getY(), - loc.getZ(), xOctaves, xSpreadFrequency, amplitude, true); - currentXRange = (Math.abs(currentXRange - * (double) (xUpperRadiusBound - xLowerRadiusBound))) - + (double) xLowerRadiusBound; - // calculate y distance blocks must be within - double currentYRange = yGenerator.noise(loc.getX(), loc.getY(), - loc.getZ(), yOctaves, ySpreadFrequency, amplitude, true); - currentYRange = (Math.abs(currentYRange - * (double) (yUpperRadiusBound - yLowerRadiusBound))) - + (double) yLowerRadiusBound; - // calculate z distance blocks must be within - double currentZRange = zGenerator.noise(loc.getX(), loc.getY(), - loc.getZ(), zOctaves, zSpreadFrequency, amplitude, true); - currentZRange = (Math.abs(currentZRange - * (double) (zUpperRadiusBound - zLowerRadiusBound))) - + (double) zLowerRadiusBound; - // clear circle in X-Z direction - for (int yOffSet = 0; yOffSet <= xzSlices; yOffSet++) { - for (double relX = loc.getX() - xUpperRadiusBound; relX <= loc - .getX() + xUpperRadiusBound; relX++) { - for (double relZ = loc.getZ() - zUpperRadiusBound; relZ <= loc - .getZ() + zUpperRadiusBound; relZ++) { - Location temp = new Location(loc.getWorld(), relX, - loc.getY() + yOffSet, relZ); - double xDistance = loc.getX() - temp.getX(); - double zDistance = loc.getZ() - temp.getZ(); - // check whether point is inside ellipse - if (((xDistance * xDistance) / (currentXRange * currentXRange)) - + ((yOffSet * yOffSet) / (currentYRange * currentYRange)) - + ((zDistance * zDistance) / (currentZRange * currentZRange)) <= 1) { - clearBlock(temp); - clearBlock(new Location(loc.getWorld(), relX, - loc.getY() - yOffSet, relZ)); - } - } - } - } - // clear circle in Y-Z direction - for (int xOffSet = 0; xOffSet <= yzSlices; xOffSet++) { - for (double relY = loc.getY() - yUpperRadiusBound; relY <= loc - .getY() + yUpperRadiusBound; relY++) { - for (double relZ = loc.getZ() - zUpperRadiusBound; relZ <= loc - .getZ() + zUpperRadiusBound; relZ++) { - Location temp = new Location(loc.getWorld(), loc.getX() - + xOffSet, relY, relZ); - double yDistance = loc.getY() - temp.getY(); - double zDistance = loc.getZ() - temp.getZ(); - // check whether point is inside ellipse - if (((xOffSet * xOffSet) / (currentXRange * currentXRange)) - + ((yDistance * yDistance) / (currentYRange * currentYRange)) - + ((zDistance * zDistance) / (currentZRange * currentZRange)) <= 1) { - clearBlock(temp); - clearBlock(new Location(loc.getWorld(), loc.getX() - - xOffSet, relY, relZ)); - } - } - } - } - // clear circle in X-Y direction - for (int zOffSet = 0; zOffSet <= xySlices; zOffSet++) { - for (double relX = loc.getX() - xUpperRadiusBound; relX <= loc - .getX() + xUpperRadiusBound; relX++) { - for (double relY = loc.getY() - yUpperRadiusBound; relY <= loc - .getY() + yUpperRadiusBound; relY++) { - Location temp = new Location(loc.getWorld(), relX, relY, - loc.getZ() + zOffSet); - double yDistance = loc.getY() - temp.getY(); - double xDistance = loc.getX() - temp.getX(); - // check whether point is inside ellipse - if (((xDistance * xDistance) / (currentXRange * currentXRange)) - + ((yDistance * yDistance) / (currentYRange * currentYRange)) - + ((zOffSet * zOffSet) / (currentZRange * currentZRange)) <= 1) { - clearBlock(temp); - clearBlock(new Location(loc.getWorld(), relX, relY, - loc.getZ() - zOffSet)); - } - } - } - - } - } - - private void executeBlockModification(Block b) { - if (hiddenOreManager != null) { - hiddenOreManager.callBreak(b); - } - b.setTypeIdAndData(replacementMaterial.getId(), replacementData, false); - Block comp = b.getWorld().getBlockAt(b.getX(), b.getY(), b.getZ()); - if (!comp.getType().equals(replacementMaterial) - || comp.getData() != replacementData) { - doLater.add(b.getLocation()); - } - } - - private void clearBlock(Location loc) { - if (loc.getBlockY() <= 0 || loc.getBlockY() > 255) { - return; - } - Block b = loc.getBlock(); - if ((!ignoreMaterials.contains(b.getType())) - && (b.getType() != replacementMaterial || b.getData() != replacementData)) { - if (b.getRelative(BlockFace.UP).getType().hasGravity()) { - fallingBlockHandler.handle(b); - } else { - executeBlockModification(b); - } - } - } - - private interface FallingBlockHandler { - void handle(Block b); - } -} diff --git a/src/main/java/com/github/maxopoly/caveworm/caveformers/CaveFormer.java b/src/main/java/com/github/maxopoly/caveworm/caveformers/CaveFormer.java new file mode 100644 index 0000000..77a6fd5 --- /dev/null +++ b/src/main/java/com/github/maxopoly/caveworm/caveformers/CaveFormer.java @@ -0,0 +1,9 @@ +package com.github.maxopoly.caveworm.caveformers; + +import org.bukkit.Location; + +public interface CaveFormer { + + void extendLocation(Location loc); + +} diff --git a/src/main/java/com/github/maxopoly/caveworm/caveformers/SimplexSphereFormer.java b/src/main/java/com/github/maxopoly/caveworm/caveformers/SimplexSphereFormer.java new file mode 100644 index 0000000..d86c7fb --- /dev/null +++ b/src/main/java/com/github/maxopoly/caveworm/caveformers/SimplexSphereFormer.java @@ -0,0 +1,279 @@ +package com.github.maxopoly.caveworm.caveformers; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.util.noise.SimplexNoiseGenerator; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; + +public class SimplexSphereFormer implements CaveFormer { + + private final SimplexNoiseGenerator xGenerator; + private final SimplexNoiseGenerator yGenerator; + private final SimplexNoiseGenerator zGenerator; + + private final Material replacementMaterial; + private final double amplitude; + private final Collection ignoreMaterials; + + private final int xOctaves; + private final int yOctaves; + private final int zOctaves; + + private final double xSpreadFrequency; + private final double ySpreadFrequency; + private final double zSpreadFrequency; + + private final double xUpperRadiusBound; + private final double yUpperRadiusBound; + private final double zUpperRadiusBound; + + private final double xLowerRadiusBound; + private final double yLowerRadiusBound; + private final double zLowerRadiusBound; + + private final int xzSlices; + private final int xySlices; + private final int yzSlices; + + private final FallingBlockHandler fallingBlockHandler; + + private final List doLater; + private List doLaterCenters; + + private final int id; + + public SimplexSphereFormer(int id, Material replacementMaterial, int xOctaves, + int yOctaves, int zOctaves, double xSpreadFrequency, + double ySpreadFrequency, double zSpreadFrequency, + double xUpperRadiusBound, double yUpperRadiusBound, + double zUpperRadiusBound, double xLowerRadiusBound, + double yLowerRadiusBound, double zLowerRadiusBound, int xzSlices, + int xySlices, int yzSlices, Collection materialsToIgnore, + int fallingBlockBehavior, Material fallingBlockReplacement, + long xSeed, long ySeed, long zSeed) { + this.replacementMaterial = replacementMaterial; + this.amplitude = 2.0; // hardcoded to ensure it properly scales with the + // bounds + this.id = id; + this.xGenerator = new SimplexNoiseGenerator(xSeed); + this.yGenerator = new SimplexNoiseGenerator(ySeed); + this.zGenerator = new SimplexNoiseGenerator(zSeed); + this.xOctaves = xOctaves; + this.yOctaves = yOctaves; + this.zOctaves = zOctaves; + this.xSpreadFrequency = xSpreadFrequency; + this.ySpreadFrequency = ySpreadFrequency; + this.zSpreadFrequency = zSpreadFrequency; + this.xUpperRadiusBound = xUpperRadiusBound; + this.yUpperRadiusBound = yUpperRadiusBound; + this.zUpperRadiusBound = zUpperRadiusBound; + this.xLowerRadiusBound = xLowerRadiusBound; + this.yLowerRadiusBound = yLowerRadiusBound; + this.zLowerRadiusBound = zLowerRadiusBound; + this.xySlices = xySlices; + this.xzSlices = xzSlices; + this.yzSlices = yzSlices; + this.doLater = new LinkedList<>(); + this.ignoreMaterials = materialsToIgnore; + switch (fallingBlockBehavior) { + case 0: + // ignore the fact that there's a falling block and clear the block + // below anyway + fallingBlockHandler = (b) -> { + executeBlockModification(b); + }; + break; + case 1: + // dont clear the block + fallingBlockHandler = (b) -> { + }; + break; + case 2: + // move the block one upwards instead of clearing it and if the + // block moved is gravity affected as well, instead another block is + // put in place + fallingBlockHandler = (b) -> { + Block above = b.getRelative(BlockFace.UP); + if (b.getType().hasGravity()) { + above.setType(fallingBlockReplacement); + executeBlockModification(b); + } else { + above.setType(b.getType(), false); + above.setBlockData(b.getBlockData(), false); + executeBlockModification(b); + } + }; + break; + default: + throw new IllegalArgumentException(); + } + } + + public SimplexSphereFormer(int id, Material replacementMaterial, int xOctaves, + int yOctaves, int zOctaves, double xSpreadFrequency, + double ySpreadFrequency, double zSpreadFrequency, + double xUpperRadiusBound, double yUpperRadiusBound, + double zUpperRadiusBound, double xLowerRadiusBound, + double yLowerRadiusBound, double zLowerRadiusBound, int xzSlices, + int xySlices, int yzSlices, Collection materialsToIgnore, + int fallingBlockBehavior, Material fallingBlockReplacement) { + this(id, replacementMaterial, xOctaves, + yOctaves, zOctaves, xSpreadFrequency, ySpreadFrequency, + zSpreadFrequency, xUpperRadiusBound, yUpperRadiusBound, + zUpperRadiusBound, xLowerRadiusBound, yLowerRadiusBound, + zLowerRadiusBound, xzSlices, xySlices, yzSlices, + materialsToIgnore, fallingBlockBehavior, + fallingBlockReplacement, new Random().nextLong(), new Random() + .nextLong(), new Random().nextLong()); + } + + public void clearRemaining() { + int failCounter = 0; + while (doLater.size() != 0) { + int startSize = doLater.size(); + // copy in new array to avoid concurrent problems when forming fails + // while doing this + Location[] locsToDoNow = doLater.toArray(new Location[startSize]); + doLater.clear(); + for (Location loc : locsToDoNow) { + clearBlock(loc); + } + System.out.println("Cleanupqueue for thread " + id + " processed " + + (startSize - doLater.size()) + " locations, " + + doLater.size() + " left "); + if (startSize == doLater.size()) { + failCounter++; + try { + Thread.sleep(5); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } else { + failCounter = 0; + } + if (failCounter >= 1000) { + return; + } + } + } + + public void extendLocation(Location loc) { + // always clear center block + clearBlock(loc); + // calculate x distance blocks must be within + double currentXRange = xGenerator.noise(loc.getX(), loc.getY(), + loc.getZ(), xOctaves, xSpreadFrequency, amplitude, true); + currentXRange = (Math.abs(currentXRange + * (xUpperRadiusBound - xLowerRadiusBound))) + + xLowerRadiusBound; + // calculate y distance blocks must be within + double currentYRange = yGenerator.noise(loc.getX(), loc.getY(), + loc.getZ(), yOctaves, ySpreadFrequency, amplitude, true); + currentYRange = (Math.abs(currentYRange + * (yUpperRadiusBound - yLowerRadiusBound))) + + yLowerRadiusBound; + // calculate z distance blocks must be within + double currentZRange = zGenerator.noise(loc.getX(), loc.getY(), + loc.getZ(), zOctaves, zSpreadFrequency, amplitude, true); + currentZRange = (Math.abs(currentZRange + * (zUpperRadiusBound - zLowerRadiusBound))) + + zLowerRadiusBound; + // clear circle in X-Z direction + for (int yOffSet = 0; yOffSet <= xzSlices; yOffSet++) { + for (double relX = loc.getX() - xUpperRadiusBound; relX <= loc + .getX() + xUpperRadiusBound; relX++) { + for (double relZ = loc.getZ() - zUpperRadiusBound; relZ <= loc + .getZ() + zUpperRadiusBound; relZ++) { + Location temp = new Location(loc.getWorld(), relX, + loc.getY() + yOffSet, relZ); + double xDistance = loc.getX() - temp.getX(); + double zDistance = loc.getZ() - temp.getZ(); + // check whether point is inside ellipse + if (((xDistance * xDistance) / (currentXRange * currentXRange)) + + ((yOffSet * yOffSet) / (currentYRange * currentYRange)) + + ((zDistance * zDistance) / (currentZRange * currentZRange)) <= 1) { + clearBlock(temp); + clearBlock(new Location(loc.getWorld(), relX, + loc.getY() - yOffSet, relZ)); + } + } + } + } + // clear circle in Y-Z direction + for (int xOffSet = 0; xOffSet <= yzSlices; xOffSet++) { + for (double relY = loc.getY() - yUpperRadiusBound; relY <= loc + .getY() + yUpperRadiusBound; relY++) { + for (double relZ = loc.getZ() - zUpperRadiusBound; relZ <= loc + .getZ() + zUpperRadiusBound; relZ++) { + Location temp = new Location(loc.getWorld(), loc.getX() + + xOffSet, relY, relZ); + double yDistance = loc.getY() - temp.getY(); + double zDistance = loc.getZ() - temp.getZ(); + // check whether point is inside ellipse + if (((xOffSet * xOffSet) / (currentXRange * currentXRange)) + + ((yDistance * yDistance) / (currentYRange * currentYRange)) + + ((zDistance * zDistance) / (currentZRange * currentZRange)) <= 1) { + clearBlock(temp); + clearBlock(new Location(loc.getWorld(), loc.getX() + - xOffSet, relY, relZ)); + } + } + } + } + // clear circle in X-Y direction + for (int zOffSet = 0; zOffSet <= xySlices; zOffSet++) { + for (double relX = loc.getX() - xUpperRadiusBound; relX <= loc + .getX() + xUpperRadiusBound; relX++) { + for (double relY = loc.getY() - yUpperRadiusBound; relY <= loc + .getY() + yUpperRadiusBound; relY++) { + Location temp = new Location(loc.getWorld(), relX, relY, + loc.getZ() + zOffSet); + double yDistance = loc.getY() - temp.getY(); + double xDistance = loc.getX() - temp.getX(); + // check whether point is inside ellipse + if (((xDistance * xDistance) / (currentXRange * currentXRange)) + + ((yDistance * yDistance) / (currentYRange * currentYRange)) + + ((zOffSet * zOffSet) / (currentZRange * currentZRange)) <= 1) { + clearBlock(temp); + clearBlock(new Location(loc.getWorld(), relX, relY, + loc.getZ() - zOffSet)); + } + } + } + + } + } + + private void executeBlockModification(Block b) { + b.setType(replacementMaterial, false); + Block comp = b.getWorld().getBlockAt(b.getX(), b.getY(), b.getZ()); + if (!comp.getType().equals(replacementMaterial)) { + doLater.add(b.getLocation()); + } + } + + private void clearBlock(Location loc) { + if (loc.getBlockY() <= 0 || loc.getBlockY() > 255) { + return; + } + Block b = loc.getBlock(); + if ((!ignoreMaterials.contains(b.getType())) + && (b.getType() != replacementMaterial)) { + if (b.getRelative(BlockFace.UP).getType().hasGravity()) { + fallingBlockHandler.handle(b); + } else { + executeBlockModification(b); + } + } + } + + private interface FallingBlockHandler { + void handle(Block b); + } +} diff --git a/src/main/java/com/github/maxopoly/caveworm/commands/CavewormCommandHandler.java b/src/main/java/com/github/maxopoly/caveworm/commands/CavewormCommandHandler.java index 310448f..b97ba2c 100644 --- a/src/main/java/com/github/maxopoly/caveworm/commands/CavewormCommandHandler.java +++ b/src/main/java/com/github/maxopoly/caveworm/commands/CavewormCommandHandler.java @@ -1,18 +1,32 @@ package com.github.maxopoly.caveworm.commands; -import vg.civcraft.mc.civmodcore.command.CommandHandler; +import org.bukkit.command.PluginCommand; +import org.bukkit.plugin.java.JavaPlugin; -public class CavewormCommandHandler extends CommandHandler { +public class CavewormCommandHandler { + public CavewormCommandHandler(JavaPlugin plugin) { + registerCommands(plugin); + } - public CavewormCommandHandler() { - registerCommands(); - } - - @Override - public void registerCommands() { - addCommands(new GenerateCave("cwgen")); - addCommands(new ReloadConfig("cwreload")); - addCommands(new SeedArea("cwseed")); - addCommands(new MultiSeedMap("cwmultiseed")); - } + public void registerCommands(JavaPlugin plugin) { + PluginCommand cwgen = plugin.getCommand("cwgen"); + cwgen.setExecutor(new GenerateCave()); + cwgen.setDescription("Spawns a cave at your current location"); + cwgen.setUsage("/cwgen "); + + PluginCommand cwreload = plugin.getCommand("cwreload"); + cwreload.setExecutor(new ReloadConfig()); + cwreload.setDescription("Reloads the config"); + cwreload.setUsage("/cwreload"); + + PluginCommand cwseed = plugin.getCommand("cwseed"); + cwseed.setExecutor(new SeedArea()); + cwseed.setDescription("Begins distributing caves around the map as specified in the config"); + cwseed.setUsage("/cwseed"); + + PluginCommand cwmultiseed = plugin.getCommand("cwmultiseed"); + cwmultiseed.setExecutor(new MultiSeedMap()); + cwmultiseed.setDescription("Begins distributing caves around the map as specified in any yml files in the config folder"); + cwmultiseed.setUsage("/cwmultiseed"); + } } diff --git a/src/main/java/com/github/maxopoly/caveworm/commands/GenerateCave.java b/src/main/java/com/github/maxopoly/caveworm/commands/GenerateCave.java index 857e671..a6e9510 100644 --- a/src/main/java/com/github/maxopoly/caveworm/commands/GenerateCave.java +++ b/src/main/java/com/github/maxopoly/caveworm/commands/GenerateCave.java @@ -1,49 +1,34 @@ package com.github.maxopoly.caveworm.commands; -import java.util.List; - +import com.github.maxopoly.caveworm.Caveworm; +import com.github.maxopoly.caveworm.CavewormAPI; import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import com.github.maxopoly.caveworm.CaveWormAPI; -import com.github.maxopoly.caveworm.Caveworm; - -import vg.civcraft.mc.civmodcore.command.PlayerCommand; - -public class GenerateCave extends PlayerCommand { - - public GenerateCave(String name) { - super(name); - setIdentifier("cwgen"); - setDescription("Spawns a cave at your current location"); - setUsage("/cwgen "); - setArguments(1, 1); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED - + "Generating caves inside the console seems like a bad idea, let's not do that"); - return true; - } - int length; - try { - length = Integer.parseInt(args [0]); - } - catch (NumberFormatException e) { - sender.sendMessage(ChatColor.RED + args [0] + " is not a valid integer"); - return true; - } - CaveWormAPI.spawnCaveAt(((Player) sender).getLocation(), length, Caveworm.getWormConfig()); - sender.sendMessage(ChatColor.GREEN + "Done"); - return true; - } - - @Override - public List tabComplete(CommandSender sender, String[] args) { - return null; - } - +public class GenerateCave implements CommandExecutor { + @Override + public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(ChatColor.RED + + "Generating caves inside the console seems like a bad idea, let's not do that"); + return true; + } + if (args.length == 0) { + sender.sendMessage(ChatColor.RED + "Usage: /cwgen "); + return true; + } + int length; + try { + length = Integer.parseInt(args[0]); + } catch (NumberFormatException e) { + sender.sendMessage(ChatColor.RED + args[0] + " is not a valid integer"); + return true; + } + CavewormAPI.spawnCaveAt(((Player) sender).getLocation(), length, Caveworm.getWormConfig()); + sender.sendMessage(ChatColor.GREEN + "Done"); + return true; + } } diff --git a/src/main/java/com/github/maxopoly/caveworm/commands/MultiSeedMap.java b/src/main/java/com/github/maxopoly/caveworm/commands/MultiSeedMap.java index 42d6221..dab8573 100644 --- a/src/main/java/com/github/maxopoly/caveworm/commands/MultiSeedMap.java +++ b/src/main/java/com/github/maxopoly/caveworm/commands/MultiSeedMap.java @@ -1,84 +1,67 @@ package com.github.maxopoly.caveworm.commands; -import java.io.File; -import java.util.List; -import java.util.Set; - -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.YamlConfiguration; - -import vg.civcraft.mc.civmodcore.command.PlayerCommand; - -import com.github.maxopoly.caveworm.CaveWormAPI; import com.github.maxopoly.caveworm.Caveworm; +import com.github.maxopoly.caveworm.CavewormAPI; import com.github.maxopoly.caveworm.WormConfig; import com.github.maxopoly.caveworm.distribution.GlobalDistributor; import com.github.maxopoly.caveworm.distribution.JobQueue; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.YamlConfiguration; -public class MultiSeedMap extends PlayerCommand { - - private Set distributorsWaiting; - - public MultiSeedMap(String name) { - super(name); - setIdentifier("cwmultiseed"); - setDescription("Begins distributing caves around the map as specified in any yml files in the config folder"); - setUsage("/cwmultiseed"); - setArguments(0, 0); - } +import java.io.File; +import java.util.Set; - @Override - public boolean execute(CommandSender sender, String[] args) { - Caveworm plugin = Caveworm.getInstance(); - File folder = plugin.getDataFolder(); - if (!folder.isDirectory()) { - sender.sendMessage(ChatColor.RED - + "The plugin directory for this plugin doesn't exist"); - return true; - } +public class MultiSeedMap implements CommandExecutor { + private Set distributorsWaiting; - for (File possibleConfig : folder.listFiles()) { - sender.sendMessage("Attempting to parse " + possibleConfig.getName()); - if (possibleConfig.isDirectory()) { - sender.sendMessage(ChatColor.RED + "Found directory " - + possibleConfig.getName() - + " in plugin folder, ignoring it"); - continue; - } - if (!possibleConfig.getName().endsWith(".yml")) { - sender.sendMessage(ChatColor.RED + "Found non yaml file " - + possibleConfig.getName() - + " in plugin folder, ignoring it"); - continue; - } - YamlConfiguration yamlConfig = YamlConfiguration - .loadConfiguration(possibleConfig); - if (yamlConfig == null) { - sender.sendMessage(ChatColor.RED + "Failed to load file " - + possibleConfig.getName() - + " in plugin folder, ignoring it"); - continue; - } - WormConfig config = new WormConfig(); - config.parse(plugin, yamlConfig); + @Override + public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { + Caveworm plugin = Caveworm.getInstance(); + File folder = plugin.getDataFolder(); + if (!folder.isDirectory()) { + sender.sendMessage(ChatColor.RED + + "The plugin directory for this plugin doesn't exist"); + return true; + } - GlobalDistributor dist = CaveWormAPI.getDistributer(config); - if (dist == null) { - sender.sendMessage(ChatColor.RED - + "Could not initiate seeding, check console log for more information"); - continue; - } - JobQueue jobs = JobQueue.getInstance(); - plugin.info(ChatColor.GOLD + "Adding job based on config " + possibleConfig.getName() + " to queue "); - jobs.addJob(dist); - } - return true; - } + for (File possibleConfig : folder.listFiles()) { + sender.sendMessage("Attempting to parse " + possibleConfig.getName()); + if (possibleConfig.isDirectory()) { + sender.sendMessage(ChatColor.RED + "Found directory " + + possibleConfig.getName() + + " in plugin folder, ignoring it"); + continue; + } + if (!possibleConfig.getName().endsWith(".yml")) { + sender.sendMessage(ChatColor.RED + "Found non yaml file " + + possibleConfig.getName() + + " in plugin folder, ignoring it"); + continue; + } + YamlConfiguration yamlConfig = YamlConfiguration + .loadConfiguration(possibleConfig); + if (yamlConfig == null) { + sender.sendMessage(ChatColor.RED + "Failed to load file " + + possibleConfig.getName() + + " in plugin folder, ignoring it"); + continue; + } + WormConfig config = new WormConfig(); + config.parse(plugin, yamlConfig); - @Override - public List tabComplete(CommandSender sender, String[] args) { - // TODO Auto-generated method stub - return null; + GlobalDistributor dist = CavewormAPI.getDistributer(config); + if (dist == null) { + sender.sendMessage(ChatColor.RED + + "Could not initiate seeding, check console log for more information"); + continue; + } + JobQueue jobs = JobQueue.getInstance(); + plugin.info(ChatColor.GOLD + "Adding job based on config " + possibleConfig.getName() + " to queue "); + jobs.addJob(dist); + } + return true; } } \ No newline at end of file diff --git a/src/main/java/com/github/maxopoly/caveworm/commands/ReloadConfig.java b/src/main/java/com/github/maxopoly/caveworm/commands/ReloadConfig.java index 1b2c729..a063053 100644 --- a/src/main/java/com/github/maxopoly/caveworm/commands/ReloadConfig.java +++ b/src/main/java/com/github/maxopoly/caveworm/commands/ReloadConfig.java @@ -1,35 +1,16 @@ package com.github.maxopoly.caveworm.commands; -import java.util.List; - +import com.github.maxopoly.caveworm.Caveworm; import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -import vg.civcraft.mc.civmodcore.command.PlayerCommand; - -import com.github.maxopoly.caveworm.Caveworm; - -public class ReloadConfig extends PlayerCommand { - - public ReloadConfig(String name) { - super(name); - setIdentifier("cwreload"); - setDescription("Reloads the config"); - setUsage("/cwreload"); - setArguments(0, 0); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - Caveworm.getInstance().refreshConfig(); - sender.sendMessage(ChatColor.GREEN + "Reloaded config"); - return true; - } - - @Override - public List tabComplete(CommandSender sender, String[] args) { - // TODO Auto-generated method stub - return null; - } - +public class ReloadConfig implements CommandExecutor { + @Override + public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { + Caveworm.getInstance().refreshConfig(); + sender.sendMessage(ChatColor.GREEN + "Reloaded config"); + return true; + } } diff --git a/src/main/java/com/github/maxopoly/caveworm/commands/SeedArea.java b/src/main/java/com/github/maxopoly/caveworm/commands/SeedArea.java index 079a4db..01997c8 100644 --- a/src/main/java/com/github/maxopoly/caveworm/commands/SeedArea.java +++ b/src/main/java/com/github/maxopoly/caveworm/commands/SeedArea.java @@ -1,40 +1,23 @@ package com.github.maxopoly.caveworm.commands; -import java.util.List; - -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; - -import com.github.maxopoly.caveworm.CaveWormAPI; import com.github.maxopoly.caveworm.Caveworm; +import com.github.maxopoly.caveworm.CavewormAPI; import com.github.maxopoly.caveworm.distribution.GlobalDistributor; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; -import vg.civcraft.mc.civmodcore.command.PlayerCommand; - -public class SeedArea extends PlayerCommand { - public SeedArea(String name) { - super(name); - setIdentifier("cwseed"); - setDescription("Begins distributing caves around the map as specified in the config"); - setUsage("/cwseed"); - setArguments(0, 0); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - GlobalDistributor dist = CaveWormAPI.getDistributer(Caveworm.getWormConfig()); - if (dist == null) { - sender.sendMessage(ChatColor.RED + "Could not initiate seeding, check console log for more information"); - return true; - } - sender.sendMessage(ChatColor.GOLD + "Beginning to seed. This may take a while"); - dist.distribute(); - return true; - } - - @Override - public List tabComplete(CommandSender sender, String[] args) { - // TODO Auto-generated method stub - return null; - } +public class SeedArea implements CommandExecutor { + @Override + public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { + GlobalDistributor dist = CavewormAPI.getDistributer(Caveworm.getWormConfig()); + if (dist == null) { + sender.sendMessage(ChatColor.RED + "Could not initiate seeding, check console log for more information"); + return true; + } + sender.sendMessage(ChatColor.GOLD + "Beginning to seed. This may take a while"); + dist.distribute(); + return true; + } } diff --git a/src/main/java/com/github/maxopoly/caveworm/distribution/DistributionRunnable.java b/src/main/java/com/github/maxopoly/caveworm/distribution/DistributionRunnable.java index f224de1..5343617 100644 --- a/src/main/java/com/github/maxopoly/caveworm/distribution/DistributionRunnable.java +++ b/src/main/java/com/github/maxopoly/caveworm/distribution/DistributionRunnable.java @@ -1,137 +1,131 @@ package com.github.maxopoly.caveworm.distribution; +import com.github.maxopoly.caveworm.Caveworm; +import com.github.maxopoly.caveworm.CavewormAPI; +import com.github.maxopoly.caveworm.WormConfig; +import com.github.maxopoly.caveworm.areas.IArea; +import com.github.maxopoly.caveworm.areas.PseudoChunk; +import com.github.maxopoly.caveworm.caveformers.SimplexSphereFormer; +import com.github.maxopoly.caveworm.worms.Worm; +import org.bukkit.Location; + import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Random; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.Location; - -import vg.civcraft.mc.civmodcore.areas.IArea; -import vg.civcraft.mc.civmodcore.areas.PseudoChunk; - -import com.github.maxopoly.caveworm.CaveWormAPI; -import com.github.maxopoly.caveworm.Caveworm; -import com.github.maxopoly.caveworm.WormConfig; -import com.github.maxopoly.caveworm.blockModifications.FormingQueue; -import com.github.maxopoly.caveworm.caveFormers.CaveFormer; -import com.github.maxopoly.caveworm.caveFormers.SimplexSphereFormer; -import com.github.maxopoly.caveworm.worms.Worm; - public class DistributionRunnable implements Runnable { - private Random rng; - private PseudoChunk[] chunks; - private double seedChance; - private Collection exclusionAreas; - private int id; - private double upperYBound; - private double lowerYBound; - private int upperCaveLengthBound; - private int lowerCaveLengthBound; - private int minimumCaveLength; - private Caveworm plugin; - private WormConfig config; - private GlobalDistributor distributor; - private SimplexSphereFormer former; + private final Random rng; + private final PseudoChunk[] chunks; + private final double seedChance; + private final Collection exclusionAreas; + private final int id; + private final double upperYBound; + private final double lowerYBound; + private final int upperCaveLengthBound; + private final int lowerCaveLengthBound; + private final int minimumCaveLength; + private final Caveworm plugin; + private final WormConfig config; + private final GlobalDistributor distributor; + private final SimplexSphereFormer former; public DistributionRunnable(WormConfig config, int id, int seed, - PseudoChunk[] chunks, GlobalDistributor distributor) { - this.seedChance = config.getDistributionSeedChance(); - this.config = config; - this.rng = new Random(seed); - this.chunks = chunks; - this.exclusionAreas = config.getExclusionAreas(); - this.upperYBound = config.getUpperDistributionYBound(); - this.lowerYBound = config.getLowerDistributionYBound(); - this.plugin = Caveworm.getInstance(); - this.lowerCaveLengthBound = config - .getLowerDistributionCaveLengthBound(); - this.upperCaveLengthBound = config - .getUpperDistributionCaveLengthBound(); - this.minimumCaveLength = config.getMinimumDistributionCaveLength(); - this.distributor = distributor; - this.former = CaveWormAPI.getCaveFormer(config, id); - this.id = id; + PseudoChunk[] chunks, GlobalDistributor distributor) { + this.seedChance = config.getDistributionSeedChance(); + this.config = config; + this.rng = new Random(seed); + this.chunks = chunks; + this.exclusionAreas = config.getExclusionAreas(); + this.upperYBound = config.getUpperDistributionYBound(); + this.lowerYBound = config.getLowerDistributionYBound(); + this.plugin = Caveworm.getInstance(); + this.lowerCaveLengthBound = config + .getLowerDistributionCaveLengthBound(); + this.upperCaveLengthBound = config + .getUpperDistributionCaveLengthBound(); + this.minimumCaveLength = config.getMinimumDistributionCaveLength(); + this.distributor = distributor; + this.former = CavewormAPI.getCaveFormer(config, id); + this.id = id; } @Override public void run() { - for (int currentIndex = 0; currentIndex < chunks.length; currentIndex++) { - PseudoChunk c = chunks[currentIndex]; - if (c == null) { - continue; - } - chunks[currentIndex] = null; - for (IArea excluArea : exclusionAreas) { - if (excluArea.isInArea(new Location(c.getWorld(), - c.getX() * 16, 0, (c.getZ() * 16) + 15)) - || excluArea.isInArea(new Location(c.getWorld(), c - .getX() * 16, 0, c.getZ() * 16)) - || excluArea.isInArea(new Location(c.getWorld(), (c - .getX() * 16) + 15, 0, c.getZ() * 16)) - || excluArea.isInArea(new Location(c.getWorld(), (c - .getX() * 16) + 15, 0, (c.getZ() * 16) + 15))) { - return; - } - } - double seedCopy = seedChance; - while (seedCopy > 0) { - if (rng.nextDouble() <= seedCopy) { - seedCopy--; - int x = rng.nextInt(16); - int z = rng.nextInt(16); - double yScaleFactor = rng.nextDouble(); - double y = (int) (((upperYBound - lowerYBound) * yScaleFactor) + lowerYBound); - Location spawnLocation = new Location(c.getWorld(), - c.getX() * 16 + x, y, c.getZ() * 16 + z); - List spawnLocations = new LinkedList(); - spawnLocations.add(spawnLocation); - List offSets = Caveworm.getWormConfig() - .getRandomLocationOffSet(); - if (offSets != null) { - plugin.debug("Attempting to seed cave system " - + offSets.toString() + " around " - + spawnLocation.toString()); - for (LocationOffset offset : offSets) { - spawnLocations.add(offset - .getOffSetLocation(spawnLocation)); - } - } - for (Location loc : spawnLocations) { - double caveLengthFactor = rng.nextDouble(); - int length = (int) (((upperCaveLengthBound - lowerCaveLengthBound) * caveLengthFactor) + lowerCaveLengthBound); - Worm w = CaveWormAPI.getWorm(loc, length, config); - List path = w.getAllLocations(); - if (path.size() < minimumCaveLength) { - plugin.debug("Attempted to spawn cave starting at " - + loc.toString() - + " but generated cave was only " - + path.size() - + " long, so it was not generated"); - // not long enough; - continue; - } - plugin.debug("Seeding cave at " + loc.toString() - + " with a total length of " + path.size()); - for(Location loca : path) { - former.extendLocation(loca); - } - } - } - } - if ((currentIndex % 250) == 0) { - Caveworm.getInstance().info( - currentIndex + " out of " + chunks.length - + " processed by thread " + id); - } - } - former.clearRemaining(); - Caveworm.getInstance().info( - "Thread " + id + " finished calculation"); - distributor.notifyCompletion(id); + for (int currentIndex = 0; currentIndex < chunks.length; currentIndex++) { + PseudoChunk c = chunks[currentIndex]; + if (c == null) { + continue; + } + chunks[currentIndex] = null; + for (IArea excluArea : exclusionAreas) { + if (excluArea.isInArea(new Location(c.getWorld(), + c.getX() * 16, 0, (c.getZ() * 16) + 15)) + || excluArea.isInArea(new Location(c.getWorld(), c + .getX() * 16, 0, c.getZ() * 16)) + || excluArea.isInArea(new Location(c.getWorld(), (c + .getX() * 16) + 15, 0, c.getZ() * 16)) + || excluArea.isInArea(new Location(c.getWorld(), (c + .getX() * 16) + 15, 0, (c.getZ() * 16) + 15))) { + return; + } + } + double seedCopy = seedChance; + while (seedCopy > 0) { + if (rng.nextDouble() <= seedCopy) { + seedCopy--; + int x = rng.nextInt(16); + int z = rng.nextInt(16); + double yScaleFactor = rng.nextDouble(); + double y = (int) (((upperYBound - lowerYBound) * yScaleFactor) + lowerYBound); + Location spawnLocation = new Location(c.getWorld(), + c.getX() * 16 + x, y, c.getZ() * 16 + z); + List spawnLocations = new LinkedList(); + spawnLocations.add(spawnLocation); + List offSets = Caveworm.getWormConfig() + .getRandomLocationOffSet(); + if (offSets != null) { + plugin.debug("Attempting to seed cave system " + + offSets + " around " + + spawnLocation); + for (LocationOffset offset : offSets) { + spawnLocations.add(offset + .getOffSetLocation(spawnLocation)); + } + } + for (Location loc : spawnLocations) { + double caveLengthFactor = rng.nextDouble(); + int length = (int) (((upperCaveLengthBound - lowerCaveLengthBound) * caveLengthFactor) + lowerCaveLengthBound); + Worm w = CavewormAPI.getWorm(loc, length, config); + List path = w.getAllLocations(); + if (path.size() < minimumCaveLength) { + plugin.debug("Attempted to spawn cave starting at " + + loc.toString() + + " but generated cave was only " + + path.size() + + " long, so it was not generated"); + // not long enough; + continue; + } + plugin.debug("Seeding cave at " + loc.toString() + + " with a total length of " + path.size()); + for (Location loca : path) { + former.extendLocation(loca); + } + } + } + } + if ((currentIndex % 250) == 0) { + Caveworm.getInstance().info( + currentIndex + " out of " + chunks.length + + " processed by thread " + id); + } + } + former.clearRemaining(); + Caveworm.getInstance().info( + "Thread " + id + " finished calculation"); + distributor.notifyCompletion(id); } } diff --git a/src/main/java/com/github/maxopoly/caveworm/distribution/GlobalDistributor.java b/src/main/java/com/github/maxopoly/caveworm/distribution/GlobalDistributor.java index 1c86592..9ca50c1 100644 --- a/src/main/java/com/github/maxopoly/caveworm/distribution/GlobalDistributor.java +++ b/src/main/java/com/github/maxopoly/caveworm/distribution/GlobalDistributor.java @@ -1,70 +1,62 @@ package com.github.maxopoly.caveworm.distribution; -import java.util.Collection; -import java.util.Random; - - - - -import org.bukkit.Chunk; - import com.github.maxopoly.caveworm.Caveworm; import com.github.maxopoly.caveworm.WormConfig; -import com.github.maxopoly.caveworm.blockModifications.FormingQueue; +import com.github.maxopoly.caveworm.areas.IArea; +import com.github.maxopoly.caveworm.areas.PseudoChunk; -import vg.civcraft.mc.civmodcore.areas.IArea; -import vg.civcraft.mc.civmodcore.areas.PseudoChunk; +import java.util.Collection; +import java.util.Random; public class GlobalDistributor { - - private IArea area; - private Random rng; - private int threads; - private Caveworm plugin; - private WormConfig config; - private boolean [] threadTracking; + private final IArea area; + private final Random rng; + private final int threads; + private final Caveworm plugin; + private final WormConfig config; + private final boolean[] threadTracking; public GlobalDistributor(WormConfig config, long seed, int threads) { - this.config = config; - this.rng = new Random(seed); - this.plugin = Caveworm.getInstance(); - this.threads = threads; - threadTracking = new boolean [threads]; - for(int i = 0; i < threadTracking.length; i++) { - threadTracking[i] = false; - } - this.area = config.getDistributionArea(); + this.config = config; + this.rng = new Random(seed); + this.plugin = Caveworm.getInstance(); + this.threads = threads; + threadTracking = new boolean[threads]; + for (int i = 0; i < threadTracking.length; i++) { + threadTracking[i] = false; + } + this.area = config.getDistributionArea(); } public void distribute() { - Collection chunkCollection = area.getPseudoChunks(); - if (chunkCollection == null) { - Caveworm.getInstance().warning( - "Couldnt distribute caves, chunk collection was null"); - return; - } - PseudoChunk [] allChunks = chunkCollection.toArray(new PseudoChunk[chunkCollection.size()]); - plugin.info("Loaded " + allChunks.length + " chunks for generation"); - int chunksPerThread = (int) Math.ceil(((double)allChunks.length) /((double) threads)); - for(int i = 0; i < threads; i++) { - PseudoChunk [] chunkRun = new PseudoChunk [chunksPerThread]; - for(int x = 0; x < chunksPerThread && (i * chunksPerThread + x) < allChunks.length; x++) { - chunkRun [x] = allChunks [i * chunksPerThread + x]; - } - Thread t = new Thread(new DistributionRunnable(config, i, rng.nextInt(), chunkRun, this)); - t.start(); - } + Collection chunkCollection = area.getPseudoChunks(); + if (chunkCollection == null) { + Caveworm.getInstance().warning( + "Couldnt distribute caves, chunk collection was null"); + return; + } + PseudoChunk[] allChunks = chunkCollection.toArray(new PseudoChunk[chunkCollection.size()]); + plugin.info("Loaded " + allChunks.length + " chunks for generation"); + int chunksPerThread = (int) Math.ceil(((double) allChunks.length) / ((double) threads)); + for (int i = 0; i < threads; i++) { + PseudoChunk[] chunkRun = new PseudoChunk[chunksPerThread]; + for (int x = 0; x < chunksPerThread && (i * chunksPerThread + x) < allChunks.length; x++) { + chunkRun[x] = allChunks[i * chunksPerThread + x]; + } + Thread t = new Thread(new DistributionRunnable(config, i, rng.nextInt(), chunkRun, this)); + t.start(); + } } - + synchronized void notifyCompletion(int id) { - threadTracking [id] = true; - for(int i = 0; i < threadTracking.length; i++) { - if (threadTracking [i] == false) { - return; - } - } - //all threads are done, so report completion to the job queue - JobQueue jobs = JobQueue.getInstance(); - jobs.notifyCompletion(this); + threadTracking[id] = true; + for (int i = 0; i < threadTracking.length; i++) { + if (!threadTracking[i]) { + return; + } + } + //all threads are done, so report completion to the job queue + JobQueue jobs = JobQueue.getInstance(); + jobs.notifyCompletion(this); } } diff --git a/src/main/java/com/github/maxopoly/caveworm/distribution/JobQueue.java b/src/main/java/com/github/maxopoly/caveworm/distribution/JobQueue.java index dbc82fa..a7580a0 100644 --- a/src/main/java/com/github/maxopoly/caveworm/distribution/JobQueue.java +++ b/src/main/java/com/github/maxopoly/caveworm/distribution/JobQueue.java @@ -1,83 +1,70 @@ package com.github.maxopoly.caveworm.distribution; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; - -import net.minecraft.server.v1_10_R1.ExceptionWorldConflict; - +import com.github.maxopoly.caveworm.Caveworm; import org.bukkit.Bukkit; import org.bukkit.World; -import org.bukkit.craftbukkit.v1_10_R1.CraftWorld; -import com.github.maxopoly.caveworm.Caveworm; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; public class JobQueue { - - private Queue distributionsPending; + private final Queue distributionsPending; private GlobalDistributor currentJob; - + private static JobQueue instance; // private to avoid explicit instanciating private JobQueue() { - this.distributionsPending = new ConcurrentLinkedQueue(); + this.distributionsPending = new ConcurrentLinkedQueue<>(); } public static JobQueue getInstance() { - if (instance == null) { - instance = new JobQueue(); - } - return instance; + if (instance == null) { + instance = new JobQueue(); + } + return instance; } public synchronized void addJob(GlobalDistributor dist) { - distributionsPending.add(dist); - checkForNextQueue(); + distributionsPending.add(dist); + checkForNextQueue(); } public synchronized boolean hasActiveJob() { - return currentJob != null; + return currentJob != null; } - + public synchronized void notifyCompletion(GlobalDistributor dist) { - if (dist != currentJob) { - Caveworm.getInstance().severe("Sync failure in job queue"); - return; - } - Caveworm.getInstance().info("Completed distribution, currently " + distributionsPending.size() + " more in queue"); - currentJob = null; - checkForNextQueue(); + if (dist != currentJob) { + Caveworm.getInstance().severe("Sync failure in job queue"); + return; + } + Caveworm.getInstance().info("Completed distribution, currently " + distributionsPending.size() + " more in queue"); + currentJob = null; + checkForNextQueue(); } - + private synchronized void checkForNextQueue() { - if (currentJob != null) { - return; - } - if (!distributionsPending.isEmpty()) { - currentJob = distributionsPending.remove(); - currentJob.distribute(); - } - else { - //no more jobs, shutdown - for(World w : Bukkit.getServer().getWorlds()) { - Caveworm.getInstance().info("Attempting to save " + w.getName()); - net.minecraft.server.v1_10_R1.WorldServer handle = ((CraftWorld) w).getHandle(); - try { - handle.save(true, null); - handle.saveLevel(); - Caveworm.getInstance().info("Queued " + handle.getChunkProviderServer().unloadQueue.size() + " chunks for unloading"); - handle.getChunkProviderServer().unloadChunks(); - } catch (ExceptionWorldConflict ex) { - Caveworm.getInstance().severe("Failed to save chunks"); - ex.printStackTrace(); - } - Caveworm.getInstance().info("Successfully saved " + w.getName()); - } - } + if (currentJob != null) { + return; + } + if (!distributionsPending.isEmpty()) { + currentJob = distributionsPending.remove(); + currentJob.distribute(); + } else { + //no more jobs, shutdown + for (World w : Bukkit.getServer().getWorlds()) { + Caveworm.getInstance().info("Attempting to save " + w.getName()); + + Bukkit.getServer().unloadWorld(w, true); + + Caveworm.getInstance().info("Successfully saved " + w.getName()); + } + } } - + public int getWaitingJobCount() { - return distributionsPending.size(); + return distributionsPending.size(); } } diff --git a/src/main/java/com/github/maxopoly/caveworm/distribution/LocationOffset.java b/src/main/java/com/github/maxopoly/caveworm/distribution/LocationOffset.java index bec92e3..85e3930 100644 --- a/src/main/java/com/github/maxopoly/caveworm/distribution/LocationOffset.java +++ b/src/main/java/com/github/maxopoly/caveworm/distribution/LocationOffset.java @@ -4,36 +4,36 @@ public class LocationOffset { - private int xOffSet; - private int yOffSet; - private int zOffSet; - - public LocationOffset(int xOffSet, int yOffSet, int zOffSet) { - this.xOffSet = xOffSet; - this.yOffSet = yOffSet; - this.zOffSet = zOffSet; - } - - public Location getOffSetLocation(Location loc) { - return new Location(loc.getWorld(), loc.getX() + xOffSet, loc.getY() - + yOffSet, loc.getZ() + yOffSet); - } - - public int getXOffSet() { - return xOffSet; - } - - public int getYOffSet() { - return yOffSet; - } - - public int getZOffSet() { - return zOffSet; - } - - public String toString() { - return "LocationOffset(x=" + xOffSet + ",y=" + yOffSet + ",z=" - + zOffSet + ")"; - } + private final int xOffSet; + private final int yOffSet; + private final int zOffSet; + + public LocationOffset(int xOffSet, int yOffSet, int zOffSet) { + this.xOffSet = xOffSet; + this.yOffSet = yOffSet; + this.zOffSet = zOffSet; + } + + public Location getOffSetLocation(Location loc) { + return new Location(loc.getWorld(), loc.getX() + xOffSet, loc.getY() + + yOffSet, loc.getZ() + yOffSet); + } + + public int getXOffSet() { + return xOffSet; + } + + public int getYOffSet() { + return yOffSet; + } + + public int getZOffSet() { + return zOffSet; + } + + public String toString() { + return "LocationOffset(x=" + xOffSet + ",y=" + yOffSet + ",z=" + + zOffSet + ")"; + } } diff --git a/src/main/java/com/github/maxopoly/caveworm/events/CaveWormGenerationCompletionEvent.java b/src/main/java/com/github/maxopoly/caveworm/events/CaveWormGenerationCompletionEvent.java index a09d46b..825a688 100644 --- a/src/main/java/com/github/maxopoly/caveworm/events/CaveWormGenerationCompletionEvent.java +++ b/src/main/java/com/github/maxopoly/caveworm/events/CaveWormGenerationCompletionEvent.java @@ -1,19 +1,28 @@ package com.github.maxopoly.caveworm.events; import com.github.maxopoly.caveworm.WormConfig; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; -import vg.civcraft.mc.civmodcore.interfaces.CustomEvent; +public class CaveWormGenerationCompletionEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + + private final WormConfig configUsed; -public class CaveWormGenerationCompletionEvent extends CustomEvent { - - private WormConfig configUsed; - public CaveWormGenerationCompletionEvent(WormConfig config) { - this.configUsed = config; + this.configUsed = config; } - + public WormConfig getConfig() { - return configUsed; + return configUsed; } + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } } diff --git a/src/main/java/com/github/maxopoly/caveworm/executable/CavewormMain.java b/src/main/java/com/github/maxopoly/caveworm/executable/CavewormMain.java deleted file mode 100644 index 20b86a0..0000000 --- a/src/main/java/com/github/maxopoly/caveworm/executable/CavewormMain.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.github.maxopoly.caveworm.executable; - -public class CavewormMain { - - - public static void main(String [] args) { - - } - -} diff --git a/src/main/java/com/github/maxopoly/caveworm/external/HiddenOreManager.java b/src/main/java/com/github/maxopoly/caveworm/external/HiddenOreManager.java deleted file mode 100644 index a220ae0..0000000 --- a/src/main/java/com/github/maxopoly/caveworm/external/HiddenOreManager.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.github.maxopoly.caveworm.external; - -import org.bukkit.block.Block; -import org.bukkit.inventory.ItemStack; - -import com.github.devotedmc.hiddenore.listeners.BlockBreakListener; - -public class HiddenOreManager { - - private ItemStack dummyItem; - - public void callBreak(Block b) { - BlockBreakListener.spoofBlockBreak(b.getLocation(), b, null); - } - -} diff --git a/src/main/java/com/github/maxopoly/caveworm/util/ConfigParsing.java b/src/main/java/com/github/maxopoly/caveworm/util/ConfigParsing.java new file mode 100644 index 0000000..4e87f89 --- /dev/null +++ b/src/main/java/com/github/maxopoly/caveworm/util/ConfigParsing.java @@ -0,0 +1,91 @@ +package com.github.maxopoly.caveworm.util; + +import com.github.maxopoly.caveworm.areas.EllipseArea; +import com.github.maxopoly.caveworm.areas.GlobalYLimitedArea; +import com.github.maxopoly.caveworm.areas.IArea; +import com.github.maxopoly.caveworm.areas.RectangleArea; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.configuration.ConfigurationSection; + +import java.util.logging.Logger; + +public class ConfigParsing { + private static final Logger log = Bukkit.getLogger(); + + public static IArea parseArea(ConfigurationSection config) { + if (config == null) { + log.warning("Tried to parse area on null section"); + return null; + } + String type = config.getString("type"); + if (type == null) { + log.warning("Found no area type at " + config.getCurrentPath()); + return null; + } + int lowerYBound = config.getInt("lowerYBound", 0); + int upperYBound = config.getInt("upperYBound", 255); + String worldName = config.getString("world"); + if (worldName == null) { + log.warning("Found no world specified for area at " + config.getCurrentPath()); + return null; + } + World world = Bukkit.getWorld(worldName); + if (world == null) { + log.warning("Found no world with name " + worldName + " as specified at " + config.getCurrentPath()); + return null; + } + Location center = null; + if (config.isConfigurationSection("center")) { + ConfigurationSection centerSection = config.getConfigurationSection("center"); + int x = centerSection.getInt("x", 0); + int y = centerSection.getInt("y", 0); + int z = centerSection.getInt("z", 0); + if (world != null) { + center = new Location(world, x, y, z); + } + } + int xSize = config.getInt("xSize", -1); + int zSize = config.getInt("zSize", -1); + IArea area = null; + switch (type) { + case "GLOBAL": + area = new GlobalYLimitedArea(lowerYBound, upperYBound, world); + break; + case "ELLIPSE": + if (center == null) { + log.warning("Found no center for area at " + config.getCurrentPath()); + return null; + } + if (xSize == -1) { + log.warning("Found no xSize for area at " + config.getCurrentPath()); + return null; + } + if (zSize == -1) { + log.warning("Found no zSize for area at " + config.getCurrentPath()); + return null; + } + area = new EllipseArea(lowerYBound, upperYBound, center, xSize, zSize); + break; + case "RECTANGLE": + if (center == null) { + log.warning("Found no center for area at " + config.getCurrentPath()); + return null; + } + if (xSize == -1) { + log.warning("Found no xSize for area at " + config.getCurrentPath()); + return null; + } + if (zSize == -1) { + log.warning("Found no zSize for area at " + config.getCurrentPath()); + return null; + } + area = new RectangleArea(lowerYBound, upperYBound, center, xSize, zSize); + break; + default: + log.warning("Invalid area type " + type + " at " + config.getCurrentPath()); + } + return area; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/maxopoly/caveworm/worms/SimplexNoiseWorm.java b/src/main/java/com/github/maxopoly/caveworm/worms/SimplexNoiseWorm.java index f99d3b1..f818214 100644 --- a/src/main/java/com/github/maxopoly/caveworm/worms/SimplexNoiseWorm.java +++ b/src/main/java/com/github/maxopoly/caveworm/worms/SimplexNoiseWorm.java @@ -1,167 +1,162 @@ package com.github.maxopoly.caveworm.worms; -import java.util.ArrayList; -import java.util.ConcurrentModificationException; -import java.util.HashSet; -import java.util.List; -import java.util.Random; -import java.util.Set; - import org.bukkit.Location; import org.bukkit.util.noise.SimplexNoiseGenerator; +import java.util.*; + public class SimplexNoiseWorm extends Worm { - private Set currentPath; - - private SimplexNoiseGenerator xNoiseGenerator; - private SimplexNoiseGenerator yNoiseGenerator; - private SimplexNoiseGenerator zNoiseGenerator; - - private int currentX; - private int currentY; - private int currentZ; - private int currentLength; - private boolean finished; - - private int xMovementOctaves; - private int yMovementOctaves; - private int zMovementOctaves; - - private double xSpreadFrequency; - private double ySpreadFrequency; - private double zSpreadFrequency; - - private double xSpreadAmplitude; - private double ySpreadAmplitude; - private double zSpreadAmplitude; - - private double xSpreadThreshHold; - private double ySpreadThreshHold; - private double zSpreadThreshHold; - - public SimplexNoiseWorm(Location startingLocation, int xMovementOctaves, - int yMovementOctaves, int zMovementOctaves, - double xSpreadFrequency, double ySpreadFrequency, - double zSpreadFrequency, double xSpreadThreshHold, - double ySpreadThreshHold, double zSpreadThreshHold, - double xSpreadAmplitude, double ySpreadAmplitude, - double zSpreadAmplitude, int maximumLength, long seedX, long seedY, - long seedZ) { - super(startingLocation, maximumLength); - this.xNoiseGenerator = new SimplexNoiseGenerator(seedX); - this.yNoiseGenerator = new SimplexNoiseGenerator(seedY); - this.zNoiseGenerator = new SimplexNoiseGenerator(seedZ); - this.xMovementOctaves = xMovementOctaves; - this.yMovementOctaves = yMovementOctaves; - this.zMovementOctaves = zMovementOctaves; - this.xSpreadFrequency = xSpreadFrequency; - this.ySpreadFrequency = ySpreadFrequency; - this.zSpreadFrequency = zSpreadFrequency; - this.xSpreadThreshHold = xSpreadThreshHold; - this.ySpreadThreshHold = ySpreadThreshHold; - this.zSpreadThreshHold = zSpreadThreshHold; - this.xSpreadAmplitude = xSpreadAmplitude; - this.ySpreadAmplitude = ySpreadAmplitude; - this.zSpreadAmplitude = zSpreadAmplitude; - this.currentX = startingLocation.getBlockX(); - this.currentY = startingLocation.getBlockY(); - this.currentZ = startingLocation.getBlockZ(); - currentPath = new HashSet(); - this.currentLength = 0; - finished = false; - } - - public SimplexNoiseWorm(Location startingLocation, int xMovementOctaves, - int yMovementOctaves, int zMovementOctaves, - double xSpreadFrequency, double ySpreadFrequency, - double zSpreadFrequency, double xSpreadThreshHold, - double ySpreadThreshHold, double zSpreadThreshHold, - double xSpreadAmplitude, double ySpreadAmplitude, - double zSpreadAmplitude, int maximumLength) { - this(startingLocation, xMovementOctaves, yMovementOctaves, - zMovementOctaves, xSpreadFrequency, ySpreadFrequency, - zSpreadFrequency, xSpreadThreshHold, ySpreadThreshHold, - zSpreadThreshHold, xSpreadAmplitude, ySpreadAmplitude, - zSpreadAmplitude, maximumLength, new Random().nextLong(), - new Random().nextLong(), new Random().nextLong()); - } - - public boolean hasNext() { - return !finished; - } - - public Location next() { - if (finished) { - return null; - } - Location result = new Location(startingLocation.getWorld(), currentX, - currentY, currentZ); - // precalculate next result - - // move in x direction - double x = xNoiseGenerator.noise(currentX, currentY, currentZ, - xMovementOctaves, xSpreadFrequency, xSpreadAmplitude, true); - if (x >= xSpreadThreshHold) { - currentX++; - } - if (x <= (-1 * xSpreadThreshHold)) { - currentX--; - } - - // move in y direction - double y = yNoiseGenerator.noise(currentX, currentY, currentZ, - yMovementOctaves, ySpreadFrequency, ySpreadAmplitude, true); - if (y >= ySpreadThreshHold) { - currentY++; - } - if (y <= (-1 * ySpreadThreshHold)) { - currentY--; - } - - // move in z direction - double z = zNoiseGenerator.noise(currentX, currentY, currentZ, - zMovementOctaves, zSpreadFrequency, zSpreadAmplitude, true); - if (z >= zSpreadThreshHold) { - currentZ++; - } - if (z <= (-1 * zSpreadThreshHold)) { - currentZ--; - } - // increment length counter - currentLength++; - //if maximum length was reached, stop - if (currentLength >= maximumLength) { - finished = true; - } - // if this point was already reached, we are inside a cycle and can stop - // earlier - Location nextOne = new Location(startingLocation.getWorld(), currentX, - currentY, currentZ); - if (currentPath.contains(nextOne)) { - finished = true; - } else { - currentPath.add(nextOne); - } - return result; - } - - public List getAllLocations() - throws ConcurrentModificationException { - if (currentX != startingLocation.getBlockX() - || currentY != startingLocation.getBlockY() - || currentZ != startingLocation.getBlockZ()) { - throw new ConcurrentModificationException(); - } - List result = new ArrayList(); - while (hasNext()) { - result.add(next()); - } - return result; - } - - public int getCurrentLength() { - return currentLength; - } + private final Set currentPath; + + private final SimplexNoiseGenerator xNoiseGenerator; + private final SimplexNoiseGenerator yNoiseGenerator; + private final SimplexNoiseGenerator zNoiseGenerator; + + private int currentX; + private int currentY; + private int currentZ; + private int currentLength; + private boolean finished; + + private final int xMovementOctaves; + private final int yMovementOctaves; + private final int zMovementOctaves; + + private final double xSpreadFrequency; + private final double ySpreadFrequency; + private final double zSpreadFrequency; + + private final double xSpreadAmplitude; + private final double ySpreadAmplitude; + private final double zSpreadAmplitude; + + private final double xSpreadThreshHold; + private final double ySpreadThreshHold; + private final double zSpreadThreshHold; + + public SimplexNoiseWorm(Location startingLocation, int xMovementOctaves, + int yMovementOctaves, int zMovementOctaves, + double xSpreadFrequency, double ySpreadFrequency, + double zSpreadFrequency, double xSpreadThreshHold, + double ySpreadThreshHold, double zSpreadThreshHold, + double xSpreadAmplitude, double ySpreadAmplitude, + double zSpreadAmplitude, int maximumLength, long seedX, long seedY, + long seedZ) { + super(startingLocation, maximumLength); + this.xNoiseGenerator = new SimplexNoiseGenerator(seedX); + this.yNoiseGenerator = new SimplexNoiseGenerator(seedY); + this.zNoiseGenerator = new SimplexNoiseGenerator(seedZ); + this.xMovementOctaves = xMovementOctaves; + this.yMovementOctaves = yMovementOctaves; + this.zMovementOctaves = zMovementOctaves; + this.xSpreadFrequency = xSpreadFrequency; + this.ySpreadFrequency = ySpreadFrequency; + this.zSpreadFrequency = zSpreadFrequency; + this.xSpreadThreshHold = xSpreadThreshHold; + this.ySpreadThreshHold = ySpreadThreshHold; + this.zSpreadThreshHold = zSpreadThreshHold; + this.xSpreadAmplitude = xSpreadAmplitude; + this.ySpreadAmplitude = ySpreadAmplitude; + this.zSpreadAmplitude = zSpreadAmplitude; + this.currentX = startingLocation.getBlockX(); + this.currentY = startingLocation.getBlockY(); + this.currentZ = startingLocation.getBlockZ(); + currentPath = new HashSet(); + this.currentLength = 0; + finished = false; + } + + public SimplexNoiseWorm(Location startingLocation, int xMovementOctaves, + int yMovementOctaves, int zMovementOctaves, + double xSpreadFrequency, double ySpreadFrequency, + double zSpreadFrequency, double xSpreadThreshHold, + double ySpreadThreshHold, double zSpreadThreshHold, + double xSpreadAmplitude, double ySpreadAmplitude, + double zSpreadAmplitude, int maximumLength) { + this(startingLocation, xMovementOctaves, yMovementOctaves, + zMovementOctaves, xSpreadFrequency, ySpreadFrequency, + zSpreadFrequency, xSpreadThreshHold, ySpreadThreshHold, + zSpreadThreshHold, xSpreadAmplitude, ySpreadAmplitude, + zSpreadAmplitude, maximumLength, new Random().nextLong(), + new Random().nextLong(), new Random().nextLong()); + } + + public boolean hasNext() { + return !finished; + } + + public Location next() { + if (finished) { + return null; + } + Location result = new Location(startingLocation.getWorld(), currentX, + currentY, currentZ); + // precalculate next result + + // move in x direction + double x = xNoiseGenerator.noise(currentX, currentY, currentZ, + xMovementOctaves, xSpreadFrequency, xSpreadAmplitude, true); + if (x >= xSpreadThreshHold) { + currentX++; + } + if (x <= (-1 * xSpreadThreshHold)) { + currentX--; + } + + // move in y direction + double y = yNoiseGenerator.noise(currentX, currentY, currentZ, + yMovementOctaves, ySpreadFrequency, ySpreadAmplitude, true); + if (y >= ySpreadThreshHold) { + currentY++; + } + if (y <= (-1 * ySpreadThreshHold)) { + currentY--; + } + + // move in z direction + double z = zNoiseGenerator.noise(currentX, currentY, currentZ, + zMovementOctaves, zSpreadFrequency, zSpreadAmplitude, true); + if (z >= zSpreadThreshHold) { + currentZ++; + } + if (z <= (-1 * zSpreadThreshHold)) { + currentZ--; + } + // increment length counter + currentLength++; + //if maximum length was reached, stop + if (currentLength >= maximumLength) { + finished = true; + } + // if this point was already reached, we are inside a cycle and can stop + // earlier + Location nextOne = new Location(startingLocation.getWorld(), currentX, + currentY, currentZ); + if (currentPath.contains(nextOne)) { + finished = true; + } else { + currentPath.add(nextOne); + } + return result; + } + + public List getAllLocations() + throws ConcurrentModificationException { + if (currentX != startingLocation.getBlockX() + || currentY != startingLocation.getBlockY() + || currentZ != startingLocation.getBlockZ()) { + throw new ConcurrentModificationException(); + } + List result = new ArrayList(); + while (hasNext()) { + result.add(next()); + } + return result; + } + + public int getCurrentLength() { + return currentLength; + } } diff --git a/src/main/java/com/github/maxopoly/caveworm/worms/Worm.java b/src/main/java/com/github/maxopoly/caveworm/worms/Worm.java index 25daa84..7749120 100644 --- a/src/main/java/com/github/maxopoly/caveworm/worms/Worm.java +++ b/src/main/java/com/github/maxopoly/caveworm/worms/Worm.java @@ -1,19 +1,19 @@ package com.github.maxopoly.caveworm.worms; +import org.bukkit.Location; + import java.util.Iterator; import java.util.List; -import org.bukkit.Location; +public abstract class Worm implements Iterator { + + protected Location startingLocation; + protected int maximumLength; + + public Worm(Location startingLocation, int maximumLength) { + this.startingLocation = startingLocation; + this.maximumLength = maximumLength; + } -public abstract class Worm implements Iterator { - - protected Location startingLocation; - protected int maximumLength; - - public Worm(Location startingLocation, int maximumLength) { - this.startingLocation = startingLocation; - this.maximumLength = maximumLength; - } - - public abstract List getAllLocations(); + public abstract List getAllLocations(); }