summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorh31ix <zero_gravity@outlook.com>2013-07-19 18:02:40 -0400
committerWesley Wolfe <weswolf@aol.com>2013-08-02 15:38:55 -0500
commit2f044fe1f8085087f232a2feff5e668d4fe9b87d (patch)
tree158158e558e2f25080064d0801e22f19602e8df2 /src
parent8cc0d89751e099193674a1f5d3f3d407601c0660 (diff)
downloadbukkit-2f044fe1f8085087f232a2feff5e668d4fe9b87d.tar
bukkit-2f044fe1f8085087f232a2feff5e668d4fe9b87d.tar.gz
bukkit-2f044fe1f8085087f232a2feff5e668d4fe9b87d.tar.lz
bukkit-2f044fe1f8085087f232a2feff5e668d4fe9b87d.tar.xz
bukkit-2f044fe1f8085087f232a2feff5e668d4fe9b87d.zip
Add 1.6 SpreadPlayers command. Fixes BUKKIT-4508
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/bukkit/command/SimpleCommandMap.java1
-rw-r--r--src/main/java/org/bukkit/command/defaults/SpreadPlayersCommand.java254
2 files changed, 255 insertions, 0 deletions
diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java
index 5e1e233d..f567dc0e 100644
--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java
+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java
@@ -59,6 +59,7 @@ public class SimpleCommandMap implements CommandMap {
fallbackCommands.add(new EffectCommand());
fallbackCommands.add(new ScoreboardCommand());
fallbackCommands.add(new PlaySoundCommand());
+ fallbackCommands.add(new SpreadPlayersCommand());
}
public SimpleCommandMap(final Server server) {
diff --git a/src/main/java/org/bukkit/command/defaults/SpreadPlayersCommand.java b/src/main/java/org/bukkit/command/defaults/SpreadPlayersCommand.java
new file mode 100644
index 00000000..506c8fe7
--- /dev/null
+++ b/src/main/java/org/bukkit/command/defaults/SpreadPlayersCommand.java
@@ -0,0 +1,254 @@
+package org.bukkit.command.defaults;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.scoreboard.Team;
+
+public class SpreadPlayersCommand extends VanillaCommand {
+ private static final Random random = new Random();
+
+ public SpreadPlayersCommand() {
+ super("spreadplayers");
+ this.description = "Spreads players around a point";
+ this.usageMessage = "/spreadplayers <x> <z> <spreadDistance> <maxRange> <respectTeams true|false> <player ...>";
+ this.setPermission("bukkit.command.spreadplayers");
+ }
+
+ @Override
+ public boolean execute(CommandSender sender, String commandLabel, String[] args) {
+ if (!testPermission(sender)) {
+ return true;
+ }
+
+ if (args.length < 6) {
+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
+ return false;
+ }
+ double x = getDouble(sender, args[0]);
+ double z = getDouble(sender, args[1]);
+ double distance = getDouble(sender, args[2]);
+
+ if (distance < 0.0D) {
+ sender.sendMessage(ChatColor.RED + "Distance is too small.");
+ return false;
+ }
+
+ double range = getDouble(sender, args[3]);
+ if (range < distance + 1.0D) {
+ sender.sendMessage(ChatColor.RED + "Max range is too small.");
+ return false;
+ }
+
+ boolean teams = false;
+ if ("true".equalsIgnoreCase(args[4])) {
+ teams = true;
+ } else if (!"false".equalsIgnoreCase(args[4])) {
+ sender.sendMessage(String.format(ChatColor.RED + "'%s' is not true or false", args[4]));
+ return false;
+ }
+
+ List<Player> players = Lists.newArrayList();
+ World world = null;
+
+ for (int i = 5; i < args.length; i++) {
+ Player player = Bukkit.getPlayerExact(args[i]);
+ if (player == null) {
+ continue;
+ }
+
+ if (world != null) {
+ world = player.getWorld();
+ }
+ players.add(player);
+ }
+
+ if (world == null) {
+ return true;
+ }
+
+ double xRangeMin = x - range;
+ double zRangeMin = z - range;
+ double xRangeMax = x + range;
+ double zRangeMax = z + range;
+
+ Location[] locations = getSpreadLocations(world, teams ? getTeams(players) : players.size(), xRangeMin, zRangeMin, xRangeMax, zRangeMax);
+ int rangeSpread = range(world, distance, xRangeMin, zRangeMin, xRangeMax, zRangeMax, locations);
+ double distanceSpread = spread(world, players, locations, teams);
+
+ sender.sendMessage(String.format("Succesfully spread %d %s around %s,%s", locations.length, teams ? "teams" : "players", x, z));
+ if (locations.length > 1) {
+ sender.sendMessage(String.format("(Average distance between %s is %s blocks apart after %s iterations)", teams ? "teams" : "players", String.format("%.2f", distanceSpread), rangeSpread));
+ }
+ return true;
+ }
+
+ private int range(World world, double distance, double xRangeMin, double zRangeMin, double xRangeMax, double zRangeMax, Location[] locations) {
+ boolean flag = true;
+ double max = Float.MAX_VALUE;
+
+ int i;
+
+ for (i = 0; i < 10000 && flag; ++i) {
+ flag = false;
+ max = Float.MAX_VALUE;
+
+ Location loc1;
+ int j;
+
+ for (int k = 0; k < locations.length; ++k) {
+ Location loc2 = locations[k];
+
+ j = 0;
+ loc1 = new Location(world, 0, 0, 0);
+
+ for (int l = 0; l < locations.length; ++l) {
+ if (k != l) {
+ Location loc3 = locations[l];
+ double dis = loc2.distanceSquared(loc3);
+
+ max = Math.min(dis, max);
+ if (dis < distance) {
+ ++j;
+ loc1.add(loc3.getX() - loc2.getX(), 0, 0);
+ loc1.add(loc3.getZ() - loc2.getZ(), 0, 0);
+ }
+ }
+ }
+
+ if (j > 0) {
+ loc2.setX(loc2.getX() / j);
+ loc2.setZ(loc2.getZ() / j);
+ double d7 = Math.sqrt(loc1.getX() * loc1.getX() + loc1.getZ() * loc1.getZ());
+
+ if (d7 > 0.0D) {
+ loc1.setX(loc1.getX() / d7);
+ loc2.add(-loc1.getX(), 0, -loc1.getZ());
+ } else {
+ double x = xRangeMin >= xRangeMax ? xRangeMin : random.nextDouble() * (xRangeMax - xRangeMin) + xRangeMin;
+ double z = zRangeMin >= zRangeMax ? zRangeMin : random.nextDouble() * (zRangeMax - zRangeMin) + zRangeMin;
+ loc2.setX(x);
+ loc2.setZ(z);
+ }
+
+ flag = true;
+ }
+
+ boolean swap = false;
+
+ if (loc2.getX() < xRangeMin) {
+ loc2.setX(xRangeMin);
+ swap = true;
+ } else if (loc2.getX() > xRangeMax) {
+ loc2.setX(xRangeMax);
+ swap = true;
+ }
+
+ if (loc2.getZ() < zRangeMin) {
+ loc2.setZ(zRangeMin);
+ swap = true;
+ } else if (loc2.getZ() > zRangeMax) {
+ loc2.setZ(zRangeMax);
+ swap = true;
+ }
+ if (swap) {
+ flag = true;
+ }
+ }
+
+ if (!flag) {
+ Location[] locs = locations;
+ int i1 = locations.length;
+
+ for (j = 0; j < i1; ++j) {
+ loc1 = locs[j];
+ if (world.getHighestBlockYAt(loc1) == 0) {
+ double x = xRangeMin >= xRangeMax ? xRangeMin : random.nextDouble() * (xRangeMax - xRangeMin) + xRangeMin;
+ double z = zRangeMin >= zRangeMax ? zRangeMin : random.nextDouble() * (zRangeMax - zRangeMin) + zRangeMin;
+ locations[i] = (new Location(world, x, 0, z));
+ loc1.setX(x);
+ loc1.setZ(z);
+ flag = true;
+ }
+ }
+ }
+ }
+
+ if (i >= 10000) {
+ return -1;
+ } else {
+ return i;
+ }
+ }
+
+ private double spread(World world, List<Player> list, Location[] locations, boolean teams) {
+ double distance = 0.0D;
+ int i = 0;
+ Map<Team, Location> hashmap = Maps.newHashMap();
+
+ for (int j = 0; j < list.size(); ++j) {
+ Player player = list.get(j);
+ Location location;
+
+ if (teams) {
+ Team team = player.getScoreboard().getPlayerTeam(player);
+
+ if (!hashmap.containsKey(team)) {
+ hashmap.put(team, locations[i++]);
+ }
+
+ location = hashmap.get(team);
+ } else {
+ location = locations[i++];
+ }
+
+ player.teleport(new Location(world, Math.floor(location.getX()) + 0.5D, world.getHighestBlockYAt((int) location.getX(), (int) location.getZ()), Math.floor(location.getZ()) + 0.5D));
+ double value = Double.MAX_VALUE;
+
+ for (int k = 0; k < locations.length; ++k) {
+ if (location != locations[k]) {
+ double d = location.distanceSquared(locations[k]);
+ value = Math.min(d, value);
+ }
+ }
+
+ distance += value;
+ }
+
+ distance /= list.size();
+ return distance;
+ }
+
+ private int getTeams(List<Player> players) {
+ Set<Team> teams = Sets.newHashSet();
+
+ for (Player player : players) {
+ teams.add(player.getScoreboard().getPlayerTeam(player));
+ }
+
+ return teams.size();
+ }
+
+ private Location[] getSpreadLocations(World world, int size, double xRangeMin, double zRangeMin, double xRangeMax, double zRangeMax) {
+ Location[] locations = new Location[size];
+
+ for (int i = 0; i < size; ++i) {
+ double x = xRangeMin >= xRangeMax ? xRangeMin : random.nextDouble() * (xRangeMax - xRangeMin) + xRangeMin;
+ double z = zRangeMin >= zRangeMax ? zRangeMin : random.nextDouble() * (zRangeMax - zRangeMin) + zRangeMin;
+ locations[i] = (new Location(world, x, 0, z));
+ }
+
+ return locations;
+ }
+}