All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bukkit.command.defaults.SpreadPlayersCommand Maven / Gradle / Ivy

package org.bukkit.command.defaults;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
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;

import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

@Deprecated
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      ";
    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;
    }

    final double x = getDouble(sender, args[0], -30000000, 30000000);
    final double z = getDouble(sender, args[1], -30000000, 30000000);
    final double distance = getDouble(sender, args[2]);
    final double range = getDouble(sender, args[3]);

    if (distance < 0.0D) {
      sender.sendMessage(ChatColor.RED + "Distance is too small.");
      return false;
    }

    if (range < distance + 1.0D) {
      sender.sendMessage(ChatColor.RED + "Max range is too small.");
      return false;
    }

    final String respectTeams = args[4];
    boolean teams = false;

    if (respectTeams.equalsIgnoreCase("true")) {
      teams = true;
    } else if (!respectTeams.equalsIgnoreCase("false")) {
      sender.sendMessage(String.format(ChatColor.RED + "'%s' is not true or false", args[4]));
      return false;
    }

    List 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;
    }

    final double xRangeMin = x - range;
    final double zRangeMin = z - range;
    final double xRangeMax = x + range;
    final double zRangeMax = z + range;

    final int spreadSize = teams ? getTeams(players) : players.size();

    final Location[] locations = getSpreadLocations(world, spreadSize, xRangeMin, zRangeMin, xRangeMax, zRangeMax);
    final int rangeSpread = range(world, distance, xRangeMin, zRangeMin, xRangeMax, zRangeMax, locations);

    if (rangeSpread == -1) {
      sender.sendMessage(String.format("Could not spread %d %s around %s,%s (too many players for space - try using spread of at most %s)", spreadSize, teams ? "teams" : "players", x, z));
      return false;
    }

    final 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;

    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 list, Location[] locations, boolean teams) {
    double distance = 0.0D;
    int i = 0;
    Map 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 players) {
    Set 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;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy