mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-18 18:42:30 +00:00
Begin work on structure /locate, fix voxel geometry and add test commands, begin work on simplex caves
This commit is contained in:
parent
188cf612fb
commit
c80e65cce9
@ -6,7 +6,6 @@ import com.dfsek.terra.generation.TerraChunkGenerator;
|
|||||||
import org.bstats.bukkit.Metrics;
|
import org.bstats.bukkit.Metrics;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.PluginCommand;
|
import org.bukkit.command.PluginCommand;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -1,7 +1,15 @@
|
|||||||
package com.dfsek.terra;
|
package com.dfsek.terra;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.IncompleteRegionException;
|
||||||
|
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||||
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
import com.sk89q.worldedit.regions.RegionSelector;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
public class WorldEditUtil {
|
public class WorldEditUtil {
|
||||||
@ -11,4 +19,50 @@ public class WorldEditUtil {
|
|||||||
Bukkit.getLogger().severe("[Terra] a command requiring WorldEdit was executed, but WorldEdit was not detected!");
|
Bukkit.getLogger().severe("[Terra] a command requiring WorldEdit was executed, but WorldEdit was not detected!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
public static Location[] getSelectionLocations(Player sender) {
|
||||||
|
WorldEditPlugin we = WorldEditUtil.getWorldEdit();
|
||||||
|
if(we == null) {
|
||||||
|
sender.sendMessage("WorldEdit is not installed! Please install WorldEdit before attempting to export structures.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Region selection;
|
||||||
|
try {
|
||||||
|
selection = we.getSession(sender).getSelection(BukkitAdapter.adapt(sender.getWorld()));
|
||||||
|
} catch(IncompleteRegionException |ClassCastException e) {
|
||||||
|
sender.sendMessage("Invalid/incomplete selection!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if(selection == null) {
|
||||||
|
sender.sendMessage("Please make a selection before attempting to export!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BlockVector3 min = selection.getMinimumPoint();
|
||||||
|
BlockVector3 max = selection.getMaximumPoint();
|
||||||
|
Location l1 = new Location(sender.getWorld(), min.getBlockX(), min.getBlockY(), min.getBlockZ());
|
||||||
|
Location l2 = new Location(sender.getWorld(), max.getBlockX(), max.getBlockY(), max.getBlockZ());
|
||||||
|
return new Location[] {l1, l2};
|
||||||
|
}
|
||||||
|
public static Location[] getSelectionPositions(Player sender) {
|
||||||
|
WorldEditPlugin we = WorldEditUtil.getWorldEdit();
|
||||||
|
if(we == null) {
|
||||||
|
sender.sendMessage("WorldEdit is not installed! Please install WorldEdit before attempting to export structures.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
CuboidRegion selection;
|
||||||
|
try {
|
||||||
|
selection = (CuboidRegion) we.getSession(sender).getSelection(BukkitAdapter.adapt(sender.getWorld()));
|
||||||
|
} catch(IncompleteRegionException |ClassCastException e) {
|
||||||
|
sender.sendMessage("Invalid/incomplete selection!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if(selection == null) {
|
||||||
|
sender.sendMessage("Please make a selection before attempting to export!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BlockVector3 min = selection.getPos1();
|
||||||
|
BlockVector3 max = selection.getPos2();
|
||||||
|
Location l1 = new Location(sender.getWorld(), min.getBlockX(), min.getBlockY(), min.getBlockZ());
|
||||||
|
Location l2 = new Location(sender.getWorld(), max.getBlockX(), max.getBlockY(), max.getBlockZ());
|
||||||
|
return new Location[] {l1, l2};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
103
src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java
Normal file
103
src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package com.dfsek.terra.async;
|
||||||
|
|
||||||
|
import com.dfsek.terra.Terra;
|
||||||
|
import com.dfsek.terra.TerraProfiler;
|
||||||
|
import com.dfsek.terra.biome.TerraBiomeGrid;
|
||||||
|
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||||
|
import com.dfsek.terra.config.genconfig.StructureConfig;
|
||||||
|
import com.dfsek.terra.structure.GaeaStructure;
|
||||||
|
import com.dfsek.terra.structure.StructureSpawnRequirement;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.polydev.gaea.generation.GenerationPhase;
|
||||||
|
import org.polydev.gaea.profiler.ProfileFuture;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class AsyncStructureFinder implements Runnable {
|
||||||
|
private final TerraBiomeGrid grid;
|
||||||
|
private final StructureConfig target;
|
||||||
|
private final Player p;
|
||||||
|
private final int startRadius;
|
||||||
|
private final int maxRadius;
|
||||||
|
private final boolean tp;
|
||||||
|
private final int centerX;
|
||||||
|
private final int centerZ;
|
||||||
|
private final long seed;
|
||||||
|
private final World world;
|
||||||
|
|
||||||
|
public AsyncStructureFinder(TerraBiomeGrid grid, StructureConfig target, Player p, int startRadius, int maxRadius, boolean tp) {
|
||||||
|
this.grid = grid;
|
||||||
|
this.target = target;
|
||||||
|
this.p = p;
|
||||||
|
this.startRadius = startRadius;
|
||||||
|
this.maxRadius = maxRadius;
|
||||||
|
this.tp = tp;
|
||||||
|
this.centerX = p.getLocation().getBlockX();
|
||||||
|
this.centerZ = p.getLocation().getBlockZ();
|
||||||
|
this.seed = p.getWorld().getSeed();
|
||||||
|
this.world = p.getWorld();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
int x = centerX;
|
||||||
|
int z = centerZ;
|
||||||
|
|
||||||
|
int wid = target.getSpawn().getWidth() + 2*target.getSpawn().getSeparation();
|
||||||
|
|
||||||
|
int run = 1;
|
||||||
|
boolean toggle = true;
|
||||||
|
boolean found = false;
|
||||||
|
main: for(int i = startRadius; i < maxRadius; i++) {
|
||||||
|
for(int j = 0; j < run; j++) {
|
||||||
|
if(toggle) x += 16;
|
||||||
|
else x -= 16;
|
||||||
|
if(hasValidSpawn(x, z)) {
|
||||||
|
found = true;
|
||||||
|
break main;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int j = 0; j < run; j++) {
|
||||||
|
if(toggle) z += 16;
|
||||||
|
else z -= 16;
|
||||||
|
if(hasValidSpawn(x, z)) {
|
||||||
|
found = true;
|
||||||
|
break main;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run++;
|
||||||
|
toggle = !toggle;
|
||||||
|
}
|
||||||
|
if(found) {
|
||||||
|
Vector v = target.getSpawn().getNearestSpawn(x, z, seed);
|
||||||
|
x = v.getBlockX();
|
||||||
|
z = v.getBlockZ();
|
||||||
|
p.sendMessage("Located structure at (" + x + ", " + z + ").");
|
||||||
|
if(tp) {
|
||||||
|
int finalX = x;
|
||||||
|
int finalZ = z;
|
||||||
|
Bukkit.getScheduler().runTask(Terra.getInstance(), () -> p.teleport(new Location(p.getWorld(), finalX, p.getLocation().getY(), finalZ)));
|
||||||
|
}
|
||||||
|
} else if(p.isOnline()) p.sendMessage("Unable to locate structure.");
|
||||||
|
}
|
||||||
|
private boolean hasValidSpawn(int x, int z) {
|
||||||
|
UserDefinedBiome b = (UserDefinedBiome) grid.getBiome(x, z, GenerationPhase.POPULATE);
|
||||||
|
Location spawn = target.getSpawn().getNearestSpawn(x, z, seed).toLocation(world); // Probably(tm) async safe
|
||||||
|
Random r2 = new Random(spawn.hashCode());
|
||||||
|
GaeaStructure struc = target.getStructure(r2);
|
||||||
|
main: for(int y = target.getSearchStart().get(r2); y > 0; y--) {
|
||||||
|
if(y > target.getBound().getMax() || y < target.getBound().getMin()) return false;
|
||||||
|
spawn.setY(y);
|
||||||
|
for(StructureSpawnRequirement s : struc.getSpawns()) {
|
||||||
|
if(! s.isValidSpawn(spawn)) continue main; // Probably(tm) async safe
|
||||||
|
if(!b.equals(grid.getBiome(spawn.clone().add(s.getX(), s.getY(), s.getZ()), GenerationPhase.POPULATE))) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
72
src/main/java/com/dfsek/terra/carving/SimplexCarver.java
Normal file
72
src/main/java/com/dfsek/terra/carving/SimplexCarver.java
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package com.dfsek.terra.carving;
|
||||||
|
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.polydev.gaea.math.FastNoise;
|
||||||
|
import org.polydev.gaea.world.carving.Carver;
|
||||||
|
import org.polydev.gaea.world.carving.CarvingData;
|
||||||
|
import org.polydev.gaea.world.carving.Worm;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class SimplexCarver extends Carver {
|
||||||
|
private final FastNoise noise;
|
||||||
|
private final FastNoise height;
|
||||||
|
private final FastNoise column;
|
||||||
|
private final FastNoise hasCaves;
|
||||||
|
private final double root2inverse = 1D/Math.sqrt(2);
|
||||||
|
public SimplexCarver(int minY, int maxY) {
|
||||||
|
super(minY, maxY);
|
||||||
|
noise = new FastNoise(2403);
|
||||||
|
noise.setNoiseType(FastNoise.NoiseType.SimplexFractal);
|
||||||
|
noise.setFractalOctaves(3);
|
||||||
|
noise.setFrequency(0.02f);
|
||||||
|
|
||||||
|
height = new FastNoise(2404);
|
||||||
|
height.setNoiseType(FastNoise.NoiseType.Simplex);
|
||||||
|
height.setFrequency(0.01f);
|
||||||
|
|
||||||
|
column = new FastNoise(2404);
|
||||||
|
column.setNoiseType(FastNoise.NoiseType.SimplexFractal);
|
||||||
|
column.setFractalOctaves(5);
|
||||||
|
column.setFrequency(0.05f);
|
||||||
|
|
||||||
|
hasCaves = new FastNoise(2405);
|
||||||
|
hasCaves.setNoiseType(FastNoise.NoiseType.Simplex);
|
||||||
|
hasCaves.setFrequency(0.005f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Worm getWorm(long l, Vector vector) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChunkCarved(World world, int i, int i1, Random random) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CarvingData carve(int chunkX, int chunkZ, World w) {
|
||||||
|
CarvingData c = new CarvingData(chunkX, chunkZ);
|
||||||
|
int ox = chunkX << 4;
|
||||||
|
int oz = chunkZ << 4;
|
||||||
|
for(int x = ox; x < ox+16; x++) {
|
||||||
|
for(int z = oz; z < oz+16; z++) {
|
||||||
|
double heightNoise = height.getNoise(x, z);
|
||||||
|
double mainNoise = noise.getNoise(x, z)*2;
|
||||||
|
double columnNoise = Math.pow(Math.max(column.getNoise(x, z), 0)*2, 3);
|
||||||
|
double hc = (acot(16*(hasCaves.getNoise(x, z)-0.2))/Math.PI)-0.1;
|
||||||
|
for(int y = 0; y < 64; y++) {
|
||||||
|
double finalNoise = (-0.05*Math.abs(y-(heightNoise*16 + 24))+1 - (Math.pow(mainNoise + root2inverse, 3)/2 + columnNoise)) * hc;
|
||||||
|
if(finalNoise > 0.5) c.carve(x-ox, y, z-oz, CarvingData.CarvingType.CENTER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double acot(double x) {
|
||||||
|
return Math.PI / 2 - Math.atan(x);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package com.dfsek.terra.command;
|
package com.dfsek.terra.command;
|
||||||
|
|
||||||
import com.dfsek.terra.command.biome.BiomeCommand;
|
import com.dfsek.terra.command.biome.BiomeCommand;
|
||||||
|
import com.dfsek.terra.command.geometry.GeometryCommand;
|
||||||
import com.dfsek.terra.command.image.ImageCommand;
|
import com.dfsek.terra.command.image.ImageCommand;
|
||||||
import com.dfsek.terra.command.profile.ProfileCommand;
|
import com.dfsek.terra.command.profile.ProfileCommand;
|
||||||
import com.dfsek.terra.command.structure.StructureCommand;
|
import com.dfsek.terra.command.structure.StructureCommand;
|
||||||
@ -19,7 +20,8 @@ public class TerraCommand extends Command {
|
|||||||
new ProfileCommand(),
|
new ProfileCommand(),
|
||||||
new SaveDataCommand(),
|
new SaveDataCommand(),
|
||||||
new StructureCommand(),
|
new StructureCommand(),
|
||||||
new ImageCommand());
|
new ImageCommand(),
|
||||||
|
new GeometryCommand());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@ -33,13 +35,6 @@ public class TerraCommand extends Command {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
public boolean execute(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
if(args.length > 0) {
|
|
||||||
for(com.dfsek.terra.command.type.Command c : commands) {
|
|
||||||
if(c.getName().equals(args[0])) return c.execute(sender, command, label, Arrays.stream(args, 1, args.length).toArray(String[]::new));
|
|
||||||
}
|
|
||||||
sender.sendMessage("Invalid command.");
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
sender.sendMessage("--------------------Terra--------------------");
|
sender.sendMessage("--------------------Terra--------------------");
|
||||||
sender.sendMessage("reload - Reload configuration data");
|
sender.sendMessage("reload - Reload configuration data");
|
||||||
sender.sendMessage("biome - Get current biome");
|
sender.sendMessage("biome - Get current biome");
|
||||||
@ -47,7 +42,6 @@ public class TerraCommand extends Command {
|
|||||||
sender.sendMessage("save-data - Save population data");
|
sender.sendMessage("save-data - Save population data");
|
||||||
sender.sendMessage("structure - Load and export structures");
|
sender.sendMessage("structure - Load and export structures");
|
||||||
sender.sendMessage("profile - Profiler options");
|
sender.sendMessage("profile - Profiler options");
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
package com.dfsek.terra.command.geometry;
|
||||||
|
|
||||||
|
import com.dfsek.terra.command.type.PlayerCommand;
|
||||||
|
import com.dfsek.terra.procgen.voxel.DeformedSphere;
|
||||||
|
import com.dfsek.terra.procgen.voxel.Sphere;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.polydev.gaea.math.FastNoise;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DeformedSphereCommand extends PlayerCommand {
|
||||||
|
@Override
|
||||||
|
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
|
int radius;
|
||||||
|
try {
|
||||||
|
radius = Integer.parseInt(args[0]);
|
||||||
|
} catch(NumberFormatException e) {
|
||||||
|
sender.sendMessage("Invalid radius: " + args[0]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
double deform;
|
||||||
|
try {
|
||||||
|
deform = Double.parseDouble(args[1]);
|
||||||
|
} catch(NumberFormatException e) {
|
||||||
|
sender.sendMessage("Invalid deform: " + args[1]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float freq;
|
||||||
|
try {
|
||||||
|
freq = Float.parseFloat(args[2]);
|
||||||
|
} catch(NumberFormatException e) {
|
||||||
|
sender.sendMessage("Invalid frequency: " + args[2]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
FastNoise n = new FastNoise((int) sender.getWorld().getSeed());
|
||||||
|
n.setNoiseType(FastNoise.NoiseType.Simplex);
|
||||||
|
n.setFrequency(freq);
|
||||||
|
DeformedSphere sphere = new DeformedSphere(sender.getLocation().toVector(), radius, deform, n);
|
||||||
|
for(Vector v : sphere.getGeometry()) {
|
||||||
|
v.toLocation(sender.getWorld()).getBlock().setType(Material.STONE);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "deformedsphere";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<com.dfsek.terra.command.type.Command> getSubCommands() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int arguments() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.dfsek.terra.command.geometry;
|
||||||
|
|
||||||
|
import com.dfsek.terra.command.type.PlayerCommand;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GeometryCommand extends PlayerCommand {
|
||||||
|
@Override
|
||||||
|
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
|
sender.sendMessage("---------------Terra/geometry----------------");
|
||||||
|
sender.sendMessage("Various voxel geometry debugging commands");
|
||||||
|
sender.sendMessage("sphere - Generate a sphere");
|
||||||
|
sender.sendMessage("deformsphere - Generate a deformed sphere");
|
||||||
|
sender.sendMessage("tube - Generate a tube");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "geometry";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<com.dfsek.terra.command.type.Command> getSubCommands() {
|
||||||
|
return Arrays.asList(new SphereCommand(), new TubeCommand(), new DeformedSphereCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int arguments() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package com.dfsek.terra.command.geometry;
|
||||||
|
|
||||||
|
import com.dfsek.terra.command.type.PlayerCommand;
|
||||||
|
import com.dfsek.terra.procgen.voxel.Sphere;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SphereCommand extends PlayerCommand {
|
||||||
|
@Override
|
||||||
|
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
|
int radius;
|
||||||
|
try {
|
||||||
|
radius = Integer.parseInt(args[0]);
|
||||||
|
} catch(NumberFormatException e) {
|
||||||
|
sender.sendMessage("Invalid radius: " + args[0]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Sphere sphere = new Sphere(sender.getLocation().toVector(), radius);
|
||||||
|
for(Vector v : sphere.getGeometry()) {
|
||||||
|
v.toLocation(sender.getWorld()).getBlock().setType(Material.STONE);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "sphere";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<com.dfsek.terra.command.type.Command> getSubCommands() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int arguments() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package com.dfsek.terra.command.geometry;
|
||||||
|
|
||||||
|
import com.dfsek.terra.WorldEditUtil;
|
||||||
|
import com.dfsek.terra.command.type.PlayerCommand;
|
||||||
|
import com.dfsek.terra.procgen.voxel.Tube;
|
||||||
|
import com.sk89q.worldedit.IncompleteRegionException;
|
||||||
|
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||||
|
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||||
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TubeCommand extends PlayerCommand {
|
||||||
|
@Override
|
||||||
|
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
|
Location[] l = WorldEditUtil.getSelectionPositions(sender);
|
||||||
|
if(l == null) return true;
|
||||||
|
int radius;
|
||||||
|
try {
|
||||||
|
radius = Integer.parseInt(args[0]);
|
||||||
|
} catch(NumberFormatException e) {
|
||||||
|
sender.sendMessage("Invalid radius: " + args[0]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Tube tube = new Tube(l[0].toVector(), l[1].toVector(), radius);
|
||||||
|
for(Vector v : tube.getGeometry()) {
|
||||||
|
v.toLocation(sender.getWorld()).getBlock().setType(Material.STONE);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "tube";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<com.dfsek.terra.command.type.Command> getSubCommands() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int arguments() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
@ -24,28 +24,11 @@ import java.util.List;
|
|||||||
public class ExportCommand extends PlayerCommand {
|
public class ExportCommand extends PlayerCommand {
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
WorldEditPlugin we = WorldEditUtil.getWorldEdit();
|
Location[] l = WorldEditUtil.getSelectionLocations(sender);
|
||||||
if(we == null) {
|
if(l == null) return true;
|
||||||
sender.sendMessage("WorldEdit is not installed! Please install WorldEdit before attempting to export structures.");
|
Location l1 = l[0];
|
||||||
return true;
|
Location l2 = l[1];
|
||||||
}
|
GaeaStructure structure;
|
||||||
Region selection;
|
|
||||||
try {
|
|
||||||
selection = we.getSession(sender).getSelection(BukkitAdapter.adapt(sender.getWorld()));
|
|
||||||
} catch(IncompleteRegionException e) {
|
|
||||||
sender.sendMessage("Invalid/incomplete selection!");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
BukkitAdapter.adapt(sender);
|
|
||||||
if(selection == null) {
|
|
||||||
sender.sendMessage("Please make a selection before attempting to export!");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
BlockVector3 min = selection.getMinimumPoint();
|
|
||||||
BlockVector3 max = selection.getMaximumPoint();
|
|
||||||
Location l1 = new Location(sender.getWorld(), min.getBlockX(), min.getBlockY(), min.getBlockZ());
|
|
||||||
Location l2 = new Location(sender.getWorld(), max.getBlockX(), max.getBlockY(), max.getBlockZ());
|
|
||||||
GaeaStructure structure = null;
|
|
||||||
try {
|
try {
|
||||||
structure = new GaeaStructure(l1, l2, args[0]);
|
structure = new GaeaStructure(l1, l2, args[0]);
|
||||||
} catch(InitializationException e) {
|
} catch(InitializationException e) {
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
package com.dfsek.terra.command.structure;
|
||||||
|
|
||||||
|
import com.dfsek.terra.Terra;
|
||||||
|
import com.dfsek.terra.TerraWorld;
|
||||||
|
import com.dfsek.terra.async.AsyncStructureFinder;
|
||||||
|
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||||
|
import com.dfsek.terra.command.type.WorldCommand;
|
||||||
|
import com.dfsek.terra.config.genconfig.StructureConfig;
|
||||||
|
import com.dfsek.terra.generation.TerraChunkGenerator;
|
||||||
|
import com.dfsek.terra.procgen.GridSpawn;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.polydev.gaea.structures.UserDefinedStructure;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class LocateCommand extends WorldCommand {
|
||||||
|
private final boolean tp;
|
||||||
|
public LocateCommand(boolean tp) {
|
||||||
|
this.tp = tp;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) {
|
||||||
|
String id = args[0];
|
||||||
|
int maxRadius;
|
||||||
|
try {
|
||||||
|
maxRadius = Integer.parseInt(args[1]);
|
||||||
|
} catch(NumberFormatException e) {
|
||||||
|
sender.sendMessage("Invalid radius: " + args[1]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
StructureConfig s;
|
||||||
|
try {
|
||||||
|
s = Objects.requireNonNull(TerraWorld.getWorld(world).getConfig().getStructure(id));
|
||||||
|
} catch(IllegalArgumentException | NullPointerException e) {
|
||||||
|
sender.sendMessage("Invalid biome ID: " + id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(Terra.getInstance(), new AsyncStructureFinder(TerraWorld.getWorld(world).getGrid(), s, sender, 0, maxRadius, tp));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return tp ? "tp" : "locate";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<com.dfsek.terra.command.type.Command> getSubCommands() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int arguments() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
|
||||||
|
if(!(sender instanceof Player) || !(((Player) sender).getWorld().getGenerator() instanceof TerraChunkGenerator)) return Collections.emptyList();
|
||||||
|
List<String> ids = TerraWorld.getWorld(((Player) sender).getWorld()).getConfig().getStructureIDs();
|
||||||
|
if(args.length == 1) return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList());
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
@ -21,7 +21,7 @@ public class StructureCommand extends PlayerCommand {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<com.dfsek.terra.command.type.Command> getSubCommands() {
|
public List<com.dfsek.terra.command.type.Command> getSubCommands() {
|
||||||
return Arrays.asList(new ExportCommand(), new LoadCommand());
|
return Arrays.asList(new ExportCommand(), new LoadCommand(), new LocateCommand(false), new LocateCommand(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -31,7 +31,7 @@ public class StructureCommand extends PlayerCommand {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int arguments() {
|
public int arguments() {
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -181,6 +181,14 @@ public class ConfigPack extends YamlConfiguration {
|
|||||||
return fill;
|
return fill;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getStructureIDs() {
|
||||||
|
List<String> fill = new ArrayList<>();
|
||||||
|
for(StructureConfig s : structures.values()) {
|
||||||
|
fill.add(s.getID());
|
||||||
|
}
|
||||||
|
return fill;
|
||||||
|
}
|
||||||
|
|
||||||
public FloraConfig getFlora(String id) {
|
public FloraConfig getFlora(String id) {
|
||||||
return flora.get(id);
|
return flora.get(id);
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
|
|||||||
for(Map.Entry<World, PopulationManager> e : popMap.entrySet()) {
|
for(Map.Entry<World, PopulationManager> e : popMap.entrySet()) {
|
||||||
try {
|
try {
|
||||||
e.getValue().saveBlocks(e.getKey());
|
e.getValue().saveBlocks(e.getKey());
|
||||||
Debug.info("[Terra] Saved data for world " + e.getKey().getName());
|
Debug.info("Saved data for world " + e.getKey().getName());
|
||||||
} catch(IOException ioException) {
|
} catch(IOException ioException) {
|
||||||
ioException.printStackTrace();
|
ioException.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.dfsek.terra.population;
|
|||||||
|
|
||||||
import com.dfsek.terra.TerraProfiler;
|
import com.dfsek.terra.TerraProfiler;
|
||||||
import com.dfsek.terra.TerraWorld;
|
import com.dfsek.terra.TerraWorld;
|
||||||
|
import com.dfsek.terra.carving.SimplexCarver;
|
||||||
import com.dfsek.terra.config.ConfigPack;
|
import com.dfsek.terra.config.ConfigPack;
|
||||||
import com.dfsek.terra.config.base.ConfigUtil;
|
import com.dfsek.terra.config.base.ConfigUtil;
|
||||||
import com.dfsek.terra.config.genconfig.CarverConfig;
|
import com.dfsek.terra.config.genconfig.CarverConfig;
|
||||||
@ -31,6 +32,7 @@ public class CavePopulator extends BlockPopulator {
|
|||||||
if(ConfigUtil.masterDisableCaves) return;
|
if(ConfigUtil.masterDisableCaves) return;
|
||||||
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("CaveTime")) {
|
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("CaveTime")) {
|
||||||
ConfigPack config = TerraWorld.getWorld(world).getConfig();
|
ConfigPack config = TerraWorld.getWorld(world).getConfig();
|
||||||
|
|
||||||
for(CarverConfig c : config.getCarvers().values()) {
|
for(CarverConfig c : config.getCarvers().values()) {
|
||||||
Map<Location, Material> shiftCandidate = new HashMap<>();
|
Map<Location, Material> shiftCandidate = new HashMap<>();
|
||||||
Set<Block> updateNeeded = new HashSet<>();
|
Set<Block> updateNeeded = new HashSet<>();
|
||||||
@ -78,6 +80,10 @@ public class CavePopulator extends BlockPopulator {
|
|||||||
b.setBlockData(orig, true);
|
b.setBlockData(orig, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for(Map.Entry<Vector, CarvingData.CarvingType> e : new SimplexCarver(chunk.getX(), chunk.getZ()).carve(chunk.getX(), chunk.getZ(), world).getCarvedBlocks().entrySet()) {
|
||||||
|
Vector v = e.getKey();
|
||||||
|
chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ()).setBlockData(AIR, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,9 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to procedurally determine the spawn point of an object based on a grid with padding between cells.
|
||||||
|
*/
|
||||||
public class GridSpawn {
|
public class GridSpawn {
|
||||||
private final int separation;
|
private final int separation;
|
||||||
private final int width;
|
private final int width;
|
||||||
@ -16,7 +19,7 @@ public class GridSpawn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get nearest spawnpoint
|
* Get nearest spawn point
|
||||||
* @param x X coordinate
|
* @param x X coordinate
|
||||||
* @param z Z coordinate
|
* @param z Z coordinate
|
||||||
* @param seed Seed for RNG
|
* @param seed Seed for RNG
|
||||||
@ -40,7 +43,7 @@ public class GridSpawn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the X/Z coordinates of the spawnpoint in the nearest Chunk (not Minecraft chunk)
|
* Get the X/Z coordinates of the spawn point in the nearest Chunk (not Minecraft chunk)
|
||||||
* @param structureChunkX Chunk X coordinate
|
* @param structureChunkX Chunk X coordinate
|
||||||
* @param structureChunkZ Chunk Z coordinate
|
* @param structureChunkZ Chunk Z coordinate
|
||||||
* @param seed Seed for RNG
|
* @param seed Seed for RNG
|
||||||
@ -54,4 +57,12 @@ public class GridSpawn {
|
|||||||
int sz = structureChunkZ * (width + 2*separation) + offsetZ;
|
int sz = structureChunkZ * (width + 2*separation) + offsetZ;
|
||||||
return new Vector(sx, 0, sz);
|
return new Vector(sx, 0, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSeparation() {
|
||||||
|
return separation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.dfsek.terra.procgen.voxel;
|
||||||
|
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
public class Cylinder extends VoxelGeometry {
|
||||||
|
public Cylinder(Vector start, int rad, int height) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -20,7 +20,6 @@ public abstract class VoxelGeometry {
|
|||||||
geometry.addAll(other.getGeometry());
|
geometry.addAll(other.getGeometry());
|
||||||
}
|
}
|
||||||
public static VoxelGeometry getBlank() {
|
public static VoxelGeometry getBlank() {
|
||||||
return new Blank();
|
return new VoxelGeometry() {};
|
||||||
}
|
}
|
||||||
private static class Blank extends VoxelGeometry {}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user