Fix #412, auto team balance for autoassign warzones

This commit is contained in:
Connor Monahan 2017-07-29 01:26:30 -05:00
parent eb7b600aef
commit 22cbba62b3

View File

@ -1,37 +1,34 @@
package com.tommytony.war;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.Level;
import com.google.common.collect.ImmutableList;
import com.tommytony.war.config.*;
import com.tommytony.war.event.WarBattleWinEvent;
import com.tommytony.war.event.WarPlayerLeaveEvent;
import com.tommytony.war.event.WarPlayerThiefEvent;
import com.tommytony.war.event.WarScoreCapEvent;
import com.tommytony.war.job.InitZoneJob;
import com.tommytony.war.job.LoadoutResetJob;
import com.tommytony.war.job.LogKillsDeathsJob;
import com.tommytony.war.job.LogKillsDeathsJob.KillsDeathsRecord;
import com.tommytony.war.job.ZoneTimeJob;
import com.tommytony.war.mapper.LoadoutYmlMapper;
import com.tommytony.war.mapper.VolumeMapper;
import com.tommytony.war.mapper.ZoneVolumeMapper;
import com.tommytony.war.spout.SpoutDisplayer;
import com.tommytony.war.structure.*;
import com.tommytony.war.utility.*;
import com.tommytony.war.volume.Volume;
import com.tommytony.war.volume.ZoneVolume;
import net.milkbowl.vault.economy.EconomyResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.*;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.*;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
@ -50,33 +47,13 @@ import org.bukkit.scoreboard.Scoreboard;
import org.getspout.spoutapi.SpoutManager;
import org.getspout.spoutapi.player.SpoutPlayer;
import com.google.common.collect.ImmutableList;
import com.tommytony.war.config.InventoryBag;
import com.tommytony.war.config.ScoreboardType;
import com.tommytony.war.config.TeamConfig;
import com.tommytony.war.config.TeamConfigBag;
import com.tommytony.war.config.TeamKind;
import com.tommytony.war.config.WarzoneConfig;
import com.tommytony.war.config.WarzoneConfigBag;
import com.tommytony.war.event.WarBattleWinEvent;
import com.tommytony.war.event.WarPlayerLeaveEvent;
import com.tommytony.war.event.WarPlayerThiefEvent;
import com.tommytony.war.event.WarScoreCapEvent;
import com.tommytony.war.job.InitZoneJob;
import com.tommytony.war.job.LoadoutResetJob;
import com.tommytony.war.job.LogKillsDeathsJob;
import com.tommytony.war.job.LogKillsDeathsJob.KillsDeathsRecord;
import com.tommytony.war.mapper.LoadoutYmlMapper;
import com.tommytony.war.mapper.VolumeMapper;
import com.tommytony.war.mapper.ZoneVolumeMapper;
import com.tommytony.war.spout.SpoutDisplayer;
import com.tommytony.war.utility.Direction;
import com.tommytony.war.utility.Loadout;
import com.tommytony.war.utility.LoadoutSelection;
import com.tommytony.war.utility.PlayerState;
import com.tommytony.war.utility.PotionEffectHelper;
import com.tommytony.war.volume.Volume;
import com.tommytony.war.volume.ZoneVolume;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.Level;
/**
*
@ -86,28 +63,29 @@ import com.tommytony.war.volume.ZoneVolume;
public class Warzone {
public enum LeaveCause {
COMMAND, DISCONNECT, SCORECAP, RESET;
public boolean useRallyPoint() {
return this == SCORECAP ? true : false;
static final Comparator<Team> LEAST_PLAYER_COUNT_ORDER = new Comparator<Team>() {
@Override
public int compare(Team arg0, Team arg1) {
return arg0.getPlayers().size() - arg1.getPlayers().size();
}
}
private String name;
private ZoneVolume volume;
private World world;
};
private final List<Team> teams = new ArrayList<Team>();
private final List<Monument> monuments = new ArrayList<Monument>();
private final List<CapturePoint> capturePoints = new ArrayList<CapturePoint>();
private final List<Bomb> bombs = new ArrayList<Bomb>();
private final List<Cake> cakes = new ArrayList<Cake>();
private final List<String> authors = new ArrayList<String>();
private final int minSafeDistanceFromWall = 6;
private final List<Player> respawn = new ArrayList<Player>();
private final List<String> reallyDeadFighters = new ArrayList<String>();
private final WarzoneConfigBag warzoneConfig;
private final TeamConfigBag teamDefaultConfig;
private String name;
private ZoneVolume volume;
private World world;
private Location teleport;
private ZoneLobby lobby;
private Location rallyPoint;
private final List<String> authors = new ArrayList<String>();
private final int minSafeDistanceFromWall = 6;
private List<ZoneWallGuard> zoneWallGuards = new ArrayList<ZoneWallGuard>();
private HashMap<String, PlayerState> playerStates = new HashMap<String, PlayerState>();
private HashMap<UUID, Team> flagThieves = new HashMap<UUID, Team>();
@ -116,15 +94,9 @@ public class Warzone {
private HashMap<String, LoadoutSelection> loadoutSelections = new HashMap<String, LoadoutSelection>();
private HashMap<String, PlayerState> deadMenInventories = new HashMap<String, PlayerState>();
private HashMap<String, Integer> killCount = new HashMap<String, Integer>();
private final List<Player> respawn = new ArrayList<Player>();
private final List<String> reallyDeadFighters = new ArrayList<String>();
private HashMap<Player, PermissionAttachment> attachments = new HashMap<Player, PermissionAttachment>();
private HashMap<Player, Team> delayedJoinPlayers = new HashMap<Player, Team>();
private List<LogKillsDeathsJob.KillsDeathsRecord> killsDeathsTracker = new ArrayList<KillsDeathsRecord>();
private final WarzoneConfigBag warzoneConfig;
private final TeamConfigBag teamDefaultConfig;
private InventoryBag defaultInventories = new InventoryBag();
private Scoreboard scoreboard;
@ -139,6 +111,9 @@ public class Warzone {
//private final Object gameEndLock = new Object();
private boolean pvpReady = true;
private Random killSeed = new Random();
// prevent tryCallDelayedPlayers from being recursively called by Warzone#assign
private boolean activeDelayedCall = false;
public Warzone(World world, String name) {
this.world = world;
@ -204,10 +179,7 @@ public class Warzone {
}
public boolean ready() {
if (this.volume.hasTwoCorners() && !this.volume.tooSmall() && !this.volume.tooBig()) {
return true;
}
return false;
return this.volume.hasTwoCorners() && !this.volume.tooSmall() && !this.volume.tooBig();
}
public List<Team> getTeams() {
@ -244,19 +216,24 @@ public class Warzone {
return this.name;
}
public void setName(String newName) {
this.name = newName;
this.volume.setName(newName);
}
@Override
public String toString() {
return this.getName();
}
public void setTeleport(Location location) {
this.teleport = location;
}
public Location getTeleport() {
return this.teleport;
}
public void setTeleport(Location location) {
this.teleport = location;
}
public int saveState(boolean clearArtifacts) {
if (this.ready()) {
if (clearArtifacts) {
@ -1025,20 +1002,13 @@ public class Warzone {
playerGuards.clear();
}
public void setLobby(ZoneLobby lobby) {
this.lobby = lobby;
}
public ZoneLobby getLobby() {
return this.lobby;
}
static final Comparator<Team> LEAST_PLAYER_COUNT_ORDER = new Comparator<Team>() {
@Override
public int compare(Team arg0, Team arg1) {
return arg0.getPlayers().size() - arg1.getPlayers().size();
public void setLobby(ZoneLobby lobby) {
this.lobby = lobby;
}
};
public Team autoAssign(Player player) {
Collections.sort(teams, LEAST_PLAYER_COUNT_ORDER);
@ -1101,8 +1071,6 @@ public class Warzone {
}
}
private Random killSeed = new Random();
/**
* Send death messages and process other records before passing off the
* death to the {@link #handleDeath(Player)} method.
@ -1311,12 +1279,51 @@ public class Warzone {
War.war.getLogger().log(Level.INFO, "Last player left warzone {0}. Warzone blocks resetting automatically...", new Object[] {this.getName()});
}
}
this.autoTeamBalance();
WarPlayerLeaveEvent event1 = new WarPlayerLeaveEvent(player.getName());
War.war.getServer().getPluginManager().callEvent(event1);
}
}
/**
* Moves players from team to team if the player size delta is greater than or equal to 2.
* Only works for autoassign zones.
*/
private void autoTeamBalance() {
if (!this.getWarzoneConfig().getBoolean(WarzoneConfig.AUTOASSIGN)) {
return;
}
boolean rerun = false;
for (Team team1 : this.teams) {
for (Team team2 : this.teams) {
if (team1 == team2) {
continue;
}
int t1p = team1.getPlayers().size();
int t2p = team2.getPlayers().size();
if (t1p - t2p >= 2) {
Player eject = team1.getPlayers().get(killSeed.nextInt(t1p));
team1.removePlayer(eject);
team1.resetSign();
this.assign(eject, team2);
rerun = true;
break;
} else if (t2p - t1p >= 2) {
Player eject = team2.getPlayers().get(killSeed.nextInt(t2p));
team2.removePlayer(eject);
team2.resetSign();
this.assign(eject, team1);
rerun = true;
break;
}
}
}
if (rerun) {
this.autoTeamBalance();
}
}
public boolean isEnemyTeamFlagBlock(Team playerTeam, Block block) {
for (Team team : this.teams) {
if (!team.getName().equals(playerTeam.getName()) && team.isTeamFlagBlock(block)) {
@ -1414,12 +1421,12 @@ public class Warzone {
return this.bombThieves.get(thief.getUniqueId());
}
// Cake
public void removeBombThief(Player thief) {
this.bombThieves.remove(thief.getUniqueId());
}
// Cake
public void addCakeThief(Cake cake, Player cakeThief) {
this.cakeThieves.put(cakeThief.getUniqueId(), cake);
WarPlayerThiefEvent event1 = new WarPlayerThiefEvent(cakeThief, WarPlayerThiefEvent.StolenObject.CAKE);
@ -1526,10 +1533,7 @@ public class Warzone {
}
public boolean isDeadMan(String playerName) {
if (this.deadMenInventories.containsKey(playerName)) {
return true;
}
return false;
return this.deadMenInventories.containsKey(playerName);
}
public void restoreDeadmanInventory(Player player) {
@ -1539,14 +1543,14 @@ public class Warzone {
}
}
public void setRallyPoint(Location location) {
this.rallyPoint = location;
}
public Location getRallyPoint() {
return this.rallyPoint;
}
public void setRallyPoint(Location location) {
this.rallyPoint = location;
}
public void unload() {
War.war.log("Unloading zone " + this.getName() + "...", Level.INFO);
for (Team team : this.getTeams()) {
@ -1572,10 +1576,7 @@ public class Warzone {
teamsWithEnough++;
}
}
if (teamsWithEnough >= this.getWarzoneConfig().getInt(WarzoneConfig.MINTEAMS)) {
return true;
}
return false;
return teamsWithEnough >= this.getWarzoneConfig().getInt(WarzoneConfig.MINTEAMS);
}
/**
@ -1616,8 +1617,6 @@ public class Warzone {
tryCallDelayedPlayers();
}
// prevent tryCallDelayedPlayers from being recursively called by Warzone#assign
private boolean activeDelayedCall = false;
private void tryCallDelayedPlayers() {
if (activeDelayedCall || (!isEnoughPlayers() && !testEnoughPlayers(null, true))) {
return;
@ -1693,7 +1692,7 @@ public class Warzone {
int i = 0;
Iterator<String> it = sortedNames.iterator();
while (it.hasNext()) {
String name = (String) it.next();
String name = it.next();
if (i == currentIndex) {
if (playerTeam.getTeamConfig().resolveBoolean(TeamConfig.PLAYERLOADOUTASDEFAULT) && name.equals("default")) {
// Use player's own inventory as loadout
@ -1789,11 +1788,6 @@ public class Warzone {
// return gameEndLock;
// }
public void setName(String newName) {
this.name = newName;
this.volume.setName(newName);
}
public HubLobbyMaterials getLobbyMaterials() {
return this.lobbyMaterials;
}
@ -1824,14 +1818,14 @@ public class Warzone {
return false;
}
public void setWarzoneMaterials(WarzoneMaterials warzoneMaterials) {
this.warzoneMaterials = warzoneMaterials;
}
public WarzoneMaterials getWarzoneMaterials() {
return warzoneMaterials;
}
public void setWarzoneMaterials(WarzoneMaterials warzoneMaterials) {
this.warzoneMaterials = warzoneMaterials;
}
public Scoreboard getScoreboard() {
return scoreboard;
}
@ -1839,6 +1833,7 @@ public class Warzone {
public ScoreboardType getScoreboardType() {
return this.getWarzoneConfig().getScoreboardType(WarzoneConfig.SCOREBOARD);
}
public boolean hasKillCount(String player) {
return killCount.containsKey(player);
}
@ -1934,7 +1929,6 @@ public class Warzone {
return zoneCap;
}
/**
* Get the amount of players in all teams in this warzone. Same as
* {@link #getPlayerCount()}, except only checks teams that the specified
@ -2117,11 +2111,19 @@ public class Warzone {
return this.isFlagThief(suspect) || this.isBombThief(suspect) || this.isCakeThief(suspect);
}
public boolean getPvpReady() {
return this.pvpReady;
}
public void setPvpReady(boolean ready) {
this.pvpReady = ready;
}
public boolean getPvpReady() {
return this.pvpReady;
public enum LeaveCause {
COMMAND, DISCONNECT, SCORECAP, RESET;
public boolean useRallyPoint() {
return this == SCORECAP;
}
}
}