diff --git a/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java b/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java index 6eea13583..c2918201f 100644 --- a/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java +++ b/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java @@ -1,4 +1,63 @@ package com.dfsek.terra.async; -public class AsyncBiomeFinder { +import com.dfsek.terra.Terra; +import com.dfsek.terra.biome.TerraBiomeGrid; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.polydev.gaea.biome.Biome; +import org.polydev.gaea.generation.GenerationPhase; + +public class AsyncBiomeFinder implements Runnable { + private final TerraBiomeGrid grid; + private final int centerX; + private final int centerZ; + private final int startRadius; + private final int maxRadius; + private final Biome target; + private final Player p; + private final boolean tp; + public AsyncBiomeFinder(TerraBiomeGrid grid, Biome target, Player p, int startRadius, int maxRadius, boolean tp) { + this.grid = grid; + this.target = target; + this.p = p; + this.centerX = p.getLocation().getBlockX(); + this.centerZ = p.getLocation().getBlockZ(); + this.startRadius = startRadius; + this.maxRadius = maxRadius; + this.tp = tp; + } + @Override + public void run() { + int x = centerX; + int z = centerZ; + int run = 1; + boolean toggle = true; + main: for(int i = startRadius; i < maxRadius; i++) { + for(int j = 0; j < run; j++) { + if(toggle) x++; + else x--; + if(checkBiome(x, z).equals(target)) break main; + } + for(int j = 0; j < run; j++) { + if(toggle) z++; + else z--; + if(checkBiome(x, z).equals(target)) break main; + } + run++; + toggle = !toggle; + } + if(checkBiome(x, z).equals(target) && p.isOnline()) { + p.sendMessage("Located biome 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 biome."); + + } + private Biome checkBiome(int x, int z) { + return grid.getBiome(x, z, GenerationPhase.POST_GEN); + } } diff --git a/src/main/java/com/dfsek/terra/command/BiomeTeleportCommand.java b/src/main/java/com/dfsek/terra/command/BiomeTeleportCommand.java deleted file mode 100644 index 541ba76f3..000000000 --- a/src/main/java/com/dfsek/terra/command/BiomeTeleportCommand.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.dfsek.terra.command; - -import com.dfsek.terra.TerraWorld; -import com.dfsek.terra.command.type.WorldCommand; -import com.dfsek.terra.generation.TerraChunkGenerator; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public class BiomeTeleportCommand extends WorldCommand { - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - return false; - } - - @Override - public String getName() { - return "tpbiome"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 1; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - if(!(sender instanceof Player) || !(((Player) sender).getWorld().getGenerator() instanceof TerraChunkGenerator)) return Collections.emptyList(); - return TerraWorld.getWorld(((Player) sender).getWorld()).getConfig().getBiomeIDs(); - } -} diff --git a/src/main/java/com/dfsek/terra/command/TerraCommand.java b/src/main/java/com/dfsek/terra/command/TerraCommand.java index 3b494f2c1..2072e9bd0 100644 --- a/src/main/java/com/dfsek/terra/command/TerraCommand.java +++ b/src/main/java/com/dfsek/terra/command/TerraCommand.java @@ -1,5 +1,6 @@ package com.dfsek.terra.command; +import com.dfsek.terra.command.biome.BiomeCommand; import com.dfsek.terra.command.image.ImageCommand; import com.dfsek.terra.command.profile.ProfileCommand; import com.dfsek.terra.command.structure.StructureCommand; diff --git a/src/main/java/com/dfsek/terra/command/BiomeCommand.java b/src/main/java/com/dfsek/terra/command/biome/BiomeCommand.java similarity index 90% rename from src/main/java/com/dfsek/terra/command/BiomeCommand.java rename to src/main/java/com/dfsek/terra/command/biome/BiomeCommand.java index 6f4ab8c3c..45545083c 100644 --- a/src/main/java/com/dfsek/terra/command/BiomeCommand.java +++ b/src/main/java/com/dfsek/terra/command/biome/BiomeCommand.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.command; +package com.dfsek.terra.command.biome; import com.dfsek.terra.TerraWorld; import com.dfsek.terra.biome.TerraBiomeGrid; @@ -11,6 +11,7 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.polydev.gaea.generation.GenerationPhase; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -30,7 +31,7 @@ public class BiomeCommand extends WorldCommand { @Override public List getSubCommands() { - return Collections.emptyList(); + return Arrays.asList(new BiomeLocateCommand(true), new BiomeLocateCommand(false)); } @Override diff --git a/src/main/java/com/dfsek/terra/command/biome/BiomeLocateCommand.java b/src/main/java/com/dfsek/terra/command/biome/BiomeLocateCommand.java new file mode 100644 index 000000000..6cf4feca7 --- /dev/null +++ b/src/main/java/com/dfsek/terra/command/biome/BiomeLocateCommand.java @@ -0,0 +1,69 @@ +package com.dfsek.terra.command.biome; + +import com.dfsek.terra.Terra; +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.async.AsyncBiomeFinder; +import com.dfsek.terra.biome.UserDefinedBiome; +import com.dfsek.terra.command.type.WorldCommand; +import com.dfsek.terra.generation.TerraChunkGenerator; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class BiomeLocateCommand extends WorldCommand { + private final boolean tp; + public BiomeLocateCommand(boolean teleport) { + this.tp = teleport; + } + @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; + } + UserDefinedBiome b; + try { + b = TerraWorld.getWorld(world).getConfig().getBiome(id).getBiome(); + } catch(IllegalArgumentException | NullPointerException e) { + sender.sendMessage("Invalid biome ID: " + id); + return true; + } + Bukkit.getScheduler().runTaskAsynchronously(Terra.getInstance(), new AsyncBiomeFinder(TerraWorld.getWorld(world).getGrid(), b, sender, 0, maxRadius, tp)); + return false; + } + + @Override + public String getName() { + return tp ? "teleport" : "locate"; + } + + @Override + public List getSubCommands() { + return Collections.emptyList(); + } + + @Override + public int arguments() { + return 2; + } + + @Override + public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { + if(!(sender instanceof Player) || !(((Player) sender).getWorld().getGenerator() instanceof TerraChunkGenerator)) return Collections.emptyList(); + List ids = TerraWorld.getWorld(((Player) sender).getWorld()).getConfig().getBiomeIDs(); + if(args.length == 1) return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); + return Collections.emptyList(); + } +} diff --git a/src/main/java/com/dfsek/terra/command/type/Command.java b/src/main/java/com/dfsek/terra/command/type/Command.java index 0d52d39cd..dbb849bb4 100644 --- a/src/main/java/com/dfsek/terra/command/type/Command.java +++ b/src/main/java/com/dfsek/terra/command/type/Command.java @@ -67,7 +67,7 @@ public abstract class Command implements CommandExecutor, TabCompleter { if(c.getName().equals(args[0])) return c.onCommand(sender, command, label, Arrays.stream(args, 1, args.length).toArray(String[]::new)); } if(args.length != arguments()) { - sender.sendMessage("Invalid command."); + sender.sendMessage("Invalid command. (Expected " + arguments() + " arguments, found " + args.length + ")."); return true; } return execute(sender, command, label, args);