package org.mctourney.autoreferee;
import java.util.Collections;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.logging.Level;
import com.google.common.collect.Maps;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import org.jdom2.Element;
import org.mctourney.autoreferee.event.player.PlayerTeamJoinEvent;
import org.mctourney.autoreferee.event.player.PlayerTeamLeaveEvent;
import org.mctourney.autoreferee.event.team.ObjectiveUpdateEvent;
import org.mctourney.autoreferee.goals.AutoRefGoal;
import org.mctourney.autoreferee.goals.BlockGoal;
import org.mctourney.autoreferee.goals.scoreboard.AutoRefObjective;
import org.mctourney.autoreferee.listeners.GoalsInventorySnapshot;
import org.mctourney.autoreferee.listeners.ZoneListener;
import org.mctourney.autoreferee.regions.AutoRefRegion;
import org.mctourney.autoreferee.util.BlockData;
import org.mctourney.autoreferee.util.Metadatable;
import org.mctourney.autoreferee.util.PlayerKit;
import org.mctourney.autoreferee.util.PlayerUtil;
import org.apache.commons.lang.StringUtils;
import com.google.common.collect.Sets;
/**
* Represents a collection of players in a match.
*
* @author authorblues
*/
public class AutoRefTeam implements Metadatable, Comparable<AutoRefTeam>
{
public class JSONTeamData
{
public String defaultname;
public String customname;
public Map<String, AutoRefPlayer.JSONPlayerData> players;
// TODO goal data?
}
// reference to the match
protected AutoRefMatch match = null;
/**
* Gets this team's match.
*
* @return match object
*/
public AutoRefMatch getMatch()
{ return match; }
org.bukkit.scoreboard.Team scoreboardTeam;
org.bukkit.scoreboard.Team infoboardTeam;
// player information
protected Set<AutoRefPlayer> players = Sets.newHashSet();
private Set<AutoRefPlayer> playersCache = Sets.newHashSet();
private int playerlives = -1;
public String toString()
{ return this.getClass().getSimpleName() + "[" + this.getName() + "]"; }
public boolean equals(Object o)
{
return this.getClass().isInstance(o)
&& this.getMatch().equals(((AutoRefTeam) o).getMatch())
&& this.name.equals(((AutoRefTeam) o).name);
}
public int hashCode()
{ return this.name.hashCode() ^ (17 * this.getMatch().hashCode()); }
protected Map<String, Object> metadata = Maps.newHashMap();
public void addMetadata(String key, Object value)
{ this.metadata.put(key, value); }
public Object getMetadata(String key)
{ return this.metadata.get(key); }
public boolean hasMetadata(String key)
{ return this.metadata.containsKey(key); }
public Object removeMetadata(String key)
{ return this.metadata.remove(key); }
public void clearMetadata()
{ this.metadata.clear(); }
/**
* Gets the members of this team.
*
* @return collection of players
*/
public Set<AutoRefPlayer> getPlayers()
{ return players; }
public Set<AutoRefPlayer> getCachedPlayers()
{ return playersCache; }
protected String getPlayerList()
{
Set<String> plist = Sets.newHashSet();
for (AutoRefPlayer apl : getPlayers())
plist.add(apl.getName());
if (plist.size() == 0) return "{empty}";
return StringUtils.join(plist, ", ");
}
private Set<String> expectedPlayers = Sets.newHashSet();
/**
* Adds a player to the list of expected players for this team.
*/
public void addExpectedPlayer(OfflinePlayer opl)
{ addExpectedPlayer(opl.getName()); }
/**
* Adds a player to the list of expected players for this team by name.
*/
public void addExpectedPlayer(String name)
{ expectedPlayers.add(name.toLowerCase()); }
/**
* Gets the players expected to join this team.
*
* @return collection of players
*/
public Set<String> getExpectedPlayers()
{ return expectedPlayers; }
// team's name, may or may not be color-related
private String name = null;
private String customName = null;
protected String scoreboardTeamName = null;
/**
* Gets the default name of the team.
*/
public String getDefaultName()
{ return name; }
/**
* Gets the name of the team.
*/
public String getName()
{
if (customName != null) return customName;
return this.getDefaultName();
}
/**
* Sets the name of the team.
*
* @param name new team name
*/
public void setName(String name)
{
// send name change event before we actually change the name
match.messageReferees("team", getName(), "name", name);
String oldName = getDisplayName();
customName = name;
if (!oldName.equals(getDisplayName()))
match.broadcast(oldName + " is now known as " + getDisplayName());
scoreboardTeam.setDisplayName(name);
// update objectives to propagate name changes
this.updateObjectives();
}
public String getScoreboardTeamName()
{ return scoreboardTeamName == null ? ("ar#" + name) : scoreboardTeamName; }
/**
* Gets the colored name of the team.
*/
public String getDisplayName()
{ return color + getName() + ChatColor.RESET; }
// color to use for members of this team
private ChatColor color = ChatColor.WHITE;
/**
* Gets the color associated with this team.
*/
public ChatColor getColor()
{ return color; }
/**
* Sets the color associated with this team.
*/
public void setColor(ChatColor color)
{ this.color = color; }
// maximum size of a team
protected Integer maxsize = null;
protected Integer minsize = null;
public int getMaxSize()
{ return maxsize == null ? 4 : maxsize; }
public int getMinSize()
{ return minsize == null ? (3 * getMaxSize() / 4) : minsize; }
// is this team ready to play?
private boolean ready = false;
/**
* Checks if this team is ready for the match to begin.
*
* @return true if team is ready, otherwise false
*/
public boolean isReady()
{ return ready || this.isEmptyTeam(); }
/**
* Sets whether this team is ready for the match to begin.
*/
public void setReady(boolean ready)
{
if (ready == this.ready) return;
this.ready = ready;
for (Player pl : getMatch().getWorld().getPlayers())
pl.sendMessage(getDisplayName() + " is now marked as " +
ChatColor.DARK_GRAY + (this.ready ? "READY" : "NOT READY"));
if (!this.ready) getMatch().cancelCountdown();
}
/**
* Checks whether this team is empty. Takes expected players into account.
*
* @return true if team is empty, otherwise false
*/
public boolean isEmptyTeam()
{ return getPlayers().size() == 0 && getExpectedPlayers().size() == 0; }
private Location lastObjectiveLocation = null;
/**
* Gets location of this team's last objective event.
*/
public Location getLastObjectiveLocation()
{ return lastObjectiveLocation; }
public void setLastObjectiveLocation(Location loc)
{
lastObjectiveLocation = loc;
getMatch().setLastObjectiveLocation(loc);
}
private static final Vector HALF_BLOCK_VECTOR = new Vector(0.5, 0.5, 0.5);
/**
* Gets location of this team's victory monument. Victory monument location
* is synthesized based on objective target locations.
*/
public Location getVictoryMonumentLocation()
{
Vector vmin = null, vmax = null;
for (BlockGoal goal : this.getTeamGoals(BlockGoal.class))
{
Vector v = goal.getTarget().toVector().add(HALF_BLOCK_VECTOR);
vmin = vmin == null ? v : Vector.getMinimum(vmin, v);
vmax = vmax == null ? v : Vector.getMaximum(vmax, v);
}
// if we didn't find any block goals, no victory monument
if (vmin == null || vmax == null) return null;
World w = getMatch().getWorld();
return vmin.getMidpoint(vmax).toLocation(w);
}
/**
* Gets all regions owned by this team.
*
* @return collection of regions
*/
public Set<AutoRefRegion> getRegions()
{ return match.getRegions(this); }
public boolean addRegion(AutoRefRegion reg)
{
for (AutoRefRegion ereg : match.getRegions())
if (reg.equals(ereg)) { ereg.addOwners(this); return true; }
reg.addOwners(this);
match.getRegions().add(reg);
return true;
}
// location of custom spawn
private Set<AutoRefRegion> spawnRegions = Sets.newHashSet();
private static Random random = new Random();
/**
* Clears this team's spawn locations.
*/
public void clearSpawnRegions()
{ this.spawnRegions = Sets.newHashSet(); }
/**
* Adds to this team's spawn locations.
*/
public void addSpawnRegion(AutoRefRegion reg)
{ this.spawnRegions.add(reg); }
/**
* Adds to this team's spawn locations.
*/
public void addSpawnRegion(Location loc)
{ this.addSpawnRegion(new org.mctourney.autoreferee.regions.PointRegion(loc)); }
/**
* Gets a valid spawn location for this team.
*/
public Location getSpawnLocation()
{
if (spawnRegions == null || spawnRegions.isEmpty())
return match.getWorldSpawn();
AutoRefRegion[] regs = spawnRegions.toArray(new AutoRefRegion[0]);
return regs[random.nextInt(spawnRegions.size())].getLocation();
}
private Set<AutoRefGoal> goals = Sets.newHashSet();
/**
* Get this team's win conditions.
*
* @return collection of win conditions
*/
public Set<AutoRefGoal> getTeamGoals()
{ return Collections.unmodifiableSet(goals); }
/**
* Get this team's win conditions by type.
*
* @return collection of win conditions
*/
public <T extends AutoRefGoal> Set<T> getTeamGoals(Class<T> clazz)
{
Set<T> typedGoals = Sets.newHashSet();
for (AutoRefGoal goal : goals)
if (clazz.isInstance(goal)) typedGoals.add((T) goal);
return typedGoals;
}
Set<AutoRefObjective> scoreboardObjectives;
public void updateObjectives()
{
if (scoreboardObjectives != null)
for (AutoRefObjective obj : scoreboardObjectives)
obj.update();
}
// does a provided search string match this team?
public int matches(String needle)
{
if (needle == null) return 0;
needle = needle.toLowerCase();
String a = name, b = customName;
if (b != null && needle.contains(b.toLowerCase())) return b.length();
if (a != null && needle.contains(a.toLowerCase())) return a.length();
return 0;
}
public void startMatch()
{
// if there is no match associated, most of this work is moot
assert getMatch() != null : "Match is null";
for (AutoRefGoal goal : goals) if (goal.hasItem())
goal.setItemStatus(AutoRefGoal.ItemStatus.NONE);
for (AutoRefPlayer apl : getPlayers())
{
Player player = apl.getPlayer();
if (player != null && !getMatch().inStartRegion(player.getLocation()))
player.teleport(getMatch().getPlayerSpawn(player));
apl.heal();
apl.updateCarrying();
}
// save all players currently on team
playersCache.addAll(players);
}
// a factory for processing config xml
public static AutoRefTeam fromElement(Element elt, AutoRefMatch match)
{
// the element we are building on needs to be a team element
assert "team".equals(elt.getName().toLowerCase());
AutoRefTeam newTeam = new AutoRefTeam();
newTeam.color = ChatColor.RESET;
newTeam.match = match;
// get name from map
if (null == (newTeam.name = elt.getChildTextTrim("name"))) return null;
String sbteam = elt.getAttributeValue("scoreboard");
if (sbteam != null)
{
if (sbteam.length() > 16) sbteam = sbteam.substring(0, 16);
newTeam.scoreboardTeamName = sbteam;
}
String clr = elt.getAttributeValue("color");
String maxsz = elt.getAttributeValue("maxsize");
String minsz = elt.getAttributeValue("minsize");
if (clr != null) try
{ newTeam.color = ChatColor.valueOf(clr.toUpperCase()); }
catch (IllegalArgumentException e) { }
// initialize this team for referees
match.messageReferees("team", newTeam.getName(), "init");
match.messageReferees("team", newTeam.getName(), "color", newTeam.color.toString());
// get the min and max size from the team tag
if (maxsz != null) newTeam.maxsize = Integer.parseInt(maxsz);
if (minsz != null) newTeam.minsize = Integer.parseInt(minsz);
if (elt.getAttributeValue("kit") != null)
{
newTeam.setKit(match.getKit(elt.getAttributeValue("kit")));
if (!Boolean.parseBoolean(match.getWorld().getGameRuleValue("keepInventory")))
{
AutoReferee.log("A kit has been specified with keepInventory=false", Level.WARNING);
AutoReferee.log("To turn this feature on, type '/gamerule keepInventory true'", Level.WARNING);
AutoReferee.log("This map should (maybe) be reconfigured with keepInventory", Level.WARNING);
}
}
Element spawn = elt.getChild("spawn");
if (spawn != null) for (Element reg : spawn.getChildren())
newTeam.addSpawnRegion(AutoRefRegion.fromElement(match, reg));
if (elt.getAttribute("lives") != null)
try { newTeam.playerlives = Integer.parseInt(elt.getAttributeValue("lives").trim()); }
catch (NumberFormatException e) { e.printStackTrace(); }
newTeam.setupScoreboard();
newTeam.players = Sets.newHashSet();
return newTeam;
}
// a factory for creating raw teams
public static AutoRefTeam create(AutoRefMatch match, String name, ChatColor color)
{
AutoRefTeam newTeam = new AutoRefTeam();
newTeam.color = color;
newTeam.match = match;
newTeam.name = name;
// initialize this team for referees
match.messageReferees("team", newTeam.getName(), "init");
match.messageReferees("team", newTeam.getName(), "color", newTeam.color.toString());
newTeam.setupScoreboard();
newTeam.players = Sets.newHashSet();
return newTeam;
}
protected void setupScoreboard()
{
String sbteam = this.getScoreboardTeamName();
// set team data on spectators' scoreboard
infoboardTeam = match.getInfoboard().registerNewTeam(sbteam);
infoboardTeam.setPrefix(color.toString());
infoboardTeam.setDisplayName(getName());
// set team data on players' scoreboard
AutoReferee.log("Setting up scoreboard for " + sbteam);
scoreboardTeam = match.getScoreboard().getTeam(sbteam);
if (scoreboardTeam == null && this.scoreboardTeamName == null)
scoreboardTeam = match.getScoreboard().registerNewTeam(sbteam);
if (scoreboardTeam != null)
{
scoreboardTeam.setPrefix(color.toString());
scoreboardTeam.setDisplayName(getName());
// this stuff is only really necessary for the players themselves
scoreboardTeam.setAllowFriendlyFire(match.allowFriendlyFire());
scoreboardTeam.setCanSeeFriendlyInvisibles(true);
}
}
public Element toElement()
{
Element elt = new Element("team");
elt.addContent(new Element("name").setText(getDefaultName()));
if (scoreboardTeamName != null)
elt.setAttribute("scoreboard", scoreboardTeamName);
if (this.getColor() != ChatColor.RESET) elt.setAttribute("color", this.getColor().name());
if (this.maxsize != null) elt.setAttribute("maxsize", Integer.toString(this.maxsize));
if (this.minsize != null) elt.setAttribute("minsize", Integer.toString(this.minsize));
if (this.playerlives > 0) elt.setAttribute("lives", Integer.toString(this.playerlives));
PlayerKit teamKit = this.getKit();
if (teamKit != null) elt.setAttribute("kit", teamKit.getName());
if (this.spawnRegions != null)
{
Element spawnElement = new Element("spawn");
for (AutoRefRegion reg : this.spawnRegions)
spawnElement.addContent(reg.toElement());
elt.addContent(spawnElement);
}
return elt;
}
private PlayerKit startKit = null;
public PlayerKit getKit()
{ return startKit; }
public void setKit(PlayerKit kit)
{ this.startKit = kit; }
/**
* Gets a player from this team by name.
*
* @return player object if one exists, otherwise null
*/
public AutoRefPlayer getPlayer(String name)
{
AutoRefPlayer bapl = null;
if (name != null)
{
int score, b = Integer.MAX_VALUE;
for (AutoRefPlayer apl : players)
{
score = apl.nameSearch(name);
if (score < b) { b = score; bapl = apl; }
}
}
return bapl;
}
/**
* Gets a player from this team associated with the specified player.
*
* @return player object if one exists, otherwise null
*/
public AutoRefPlayer getPlayer(Player player)
{ return player == null ? null : getPlayer(player.getName()); }
protected void addPlayer(AutoRefPlayer apl)
{
if (scoreboardTeam != null) scoreboardTeam.addPlayer(Bukkit.getOfflinePlayer(apl.getName()));
if ( infoboardTeam != null) infoboardTeam.addPlayer(Bukkit.getOfflinePlayer(apl.getName()));
apl.setTeam(this); this.players.add(apl);
if (this.getMatch() != null && this.getMatch().getCurrentState().inProgress())
this.playersCache.add(apl);
}
protected boolean removePlayer(AutoRefPlayer apl)
{
if (scoreboardTeam != null) scoreboardTeam.removePlayer(Bukkit.getOfflinePlayer(apl.getName()));
if ( infoboardTeam != null) infoboardTeam.removePlayer(Bukkit.getOfflinePlayer(apl.getName()));
return this.players.remove(apl);
}
/**
* Adds a player to this team. Players may not be added to teams if the match
* is already in progress.
*
* @return true if player was successfully added, otherwise false
*/
public boolean join(Player player, PlayerTeamJoinEvent.Reason reason)
{ return join(player, reason, false); }
/**
* Adds a player to this team.
*
* @param force force join operation, even if match is in progress
* @return true if player was successfully added, otherwise false
*/
public boolean join(Player player, PlayerTeamJoinEvent.Reason reason, boolean force)
{
PlayerTeamJoinEvent event = new PlayerTeamJoinEvent(player, this, reason);
AutoReferee.callEvent(event);
if (event.isCancelled()) return false;
// if this player is using the client mod and is not an op, they may not join
if (!player.isOp() && PlayerUtil.hasClientMod(player))
{
if (!getMatch().isReferee(player))
player.sendMessage("You may not join a team with a modified client");
String warning = ChatColor.DARK_GRAY + player.getName() + " attempted to join "
+ this.getDisplayName() + ChatColor.DARK_GRAY + " with a modified client";
for (Player ref : getMatch().getReferees(true)) ref.sendMessage(warning);
return false;
}
// create an APL object for this player.
AutoRefPlayer apl = new AutoRefPlayer(player, this);
if (this.playerlives > 0) apl.setLivesRemaining(this.playerlives);
// quit if they are already on this team
if (players.contains(apl)) return true;
// if there is no match object, drop out here
if (match == null) return false;
// if the match is in progress, no one may join
if (!match.getCurrentState().isBeforeMatch() && !force) return false;
// prepare the player
if (!match.getCurrentState().inProgress() && !this.spawnRegions.isEmpty())
player.teleport(this.getSpawnLocation());
Location bed = player.getBedSpawnLocation();
if (bed != null && bed.getWorld() != match.getWorld())
player.setBedSpawnLocation(null);
this.addPlayer(apl);
match.messageReferees("team", getName(), "player", "+" + apl.getName());
match.messageReferees("player", apl.getName(), "login");
match.updatePlayerList();
match.broadcast(apl.getDisplayName() + " has joined " + getDisplayName());
match.setupSpectators(player);
match.checkTeamsReady();
return true;
}
/**
* Removes a player from this team. Players may not be removed from teams if the
* match is already in progress.
*
* @return true if player was successfully removed, otherwise false
*/
public boolean leave(Player player)
{ return leave(player, false); }
/**
* Removes a player from this team.
*
* @param force force leave operation, even if match is in progress
* @return true if player was successfully removed, otherwise false
*/
public boolean leave(Player player, boolean force)
{
PlayerTeamLeaveEvent event = new PlayerTeamLeaveEvent(player, this);
AutoReferee.callEvent(event);
if (event.isCancelled()) return false;
// if the match is in progress, no one may leave their team
if (!match.getCurrentState().isBeforeMatch() && !force &&
match.getReferees().size() > 0) return false;
String name = match.getDisplayName(player);
if (!this.leaveQuietly(player)) return false;
match.broadcast(name + " has left " + getDisplayName());
return true;
}
/**
* Removes a player from this team quietly.
*
* @return true if player was successfully removed, otherwise false
*/
public boolean leaveQuietly(Player player)
{
// create an APL object for this player.
AutoRefPlayer apl = new AutoRefPlayer(player);
if (!this.removePlayer(apl)) return false;
match.updatePlayerList();
// by the time this is actually called, they may have left the world to join
// a different match. this teleport shouldn't occur if they aren't in this world
if (player.getWorld() == match.getWorld() && !match.inStartRegion(player.getLocation()))
player.teleport(match.getWorldSpawn());
match.messageReferees("team", getName(), "player", "-" + apl.getName());
match.setupSpectators(player);
match.checkTeamsReady();
return true;
}
/**
* Returns distance from location to this team's closest region.
*
* @return distance
*/
public double distanceToClosestRegion(Location loc)
{
double distance = match.distanceToStartRegion(loc);
Set<AutoRefRegion> regions = getRegions();
if (regions != null) for ( AutoRefRegion reg : regions ) if (distance > 0)
distance = Math.min(distance, reg.distanceToRegion(loc));
return distance;
}
/**
* Checks if players on this team can be in a given location, including sneak distance.
*
* @return true if location is valid, otherwise false
*/
public boolean canEnter(Location loc)
{ return canEnter(loc, ZoneListener.SNEAK_DISTANCE); }
/**
* Checks if players on this team can be in a given location, within a specified distance.
*
* @param distance maximum distance a player may move from this location
* @return true if location is valid, otherwise false
*/
public boolean canEnter(Location loc, Double distance)
{
double bestdist = match.distanceToStartRegion(loc);
Set<AutoRefRegion> regions = getRegions();
if (regions != null) for ( AutoRefRegion reg : regions ) if (bestdist > 0)
{
bestdist = Math.min(bestdist, reg.distanceToRegion(loc));
if (reg.is(AutoRefRegion.Flag.NO_ENTRY) &&
reg.distanceToRegion(loc) <= distance) return false;
}
return bestdist <= distance;
}
/**
* Checks if a region is marked with a specific region flag.
*
* @return true if location contains flag, otherwise false
*/
public boolean hasFlag(Block b, AutoRefRegion.Flag flag)
{ return hasFlag(b, flag, flag.defaultValue); }
/**
* Checks if a region is marked with a specific region flag.
*
* @return true if location contains flag, otherwise false
*/
public boolean hasFlag(Block b, AutoRefRegion.Flag flag, boolean def)
{ return hasFlag(b.getLocation().clone().add(0.5, 0.5, 0.5), flag, def); }
/**
* Checks if a region is marked with a specific region flag.
*
* @return true if location contains flag, otherwise false
*/
public boolean hasFlag(Location loc, AutoRefRegion.Flag flag)
{ return hasFlag(loc, flag, flag.defaultValue); }
/**
* Checks if a region is marked with a specific region flag.
*
* @return true if location contains flag, otherwise false
*/
public boolean hasFlag(Location loc, AutoRefRegion.Flag flag, boolean def)
{
// check start region flags
if (getMatch().inStartRegion(loc))
return getMatch().getStartRegionFlags().contains(flag);
boolean is = def; Set<AutoRefRegion> regions = getRegions();
if (regions != null) for ( AutoRefRegion reg : regions )
if (reg.contains(loc)) { is = false; if (reg.is(flag)) return true; }
return is;
}
/**
* Sets a new win condition.
*/
public void addGoal(Element elt)
{ this.addGoal(AutoRefGoal.fromElement(this, elt)); }
/**
* Sets a new win condition.
*/
public void addGoal(AutoRefGoal goal)
{
if (goal == null) return;
goals.add(goal);
for (Player ref : getMatch().getReferees(false))
goal.updateReferee(ref);
// broadcast the update
for (Player cfg : getMatch().getWorld().getPlayers()) if (cfg.hasPermission("autoreferee.configure"))
cfg.sendMessage(goal.toString() + " is now a win condition for " + getDisplayName());
}
/**
* Gets a list of team objectives for this match.
*
* @return collection of block types to be retrieved
*/
public Set<BlockData> getObjectives()
{
Set<BlockData> objectives = Sets.newHashSet();
for (AutoRefGoal goal : goals)
if (goal.hasItem()) objectives.add(goal.getItem());
objectives.remove(BlockData.AIR);
return objectives;
}
/**
* Gets a list of team objectives for this match.
*
* @return collection of block types to be retrieved
*/
public Map<BlockData, AutoRefGoal> getGoalsByObjective()
{
Map<BlockData, AutoRefGoal> goalsByObjective = Maps.newHashMap();
for (AutoRefGoal goal : goals)
if (goal.hasItem()) goalsByObjective.put(goal.getItem(), goal);
goalsByObjective.remove(BlockData.AIR);
return goalsByObjective;
}
public boolean canCraft(BlockData bdata)
{
for (AutoRefGoal goal : goals)
if (goal.hasItem() && goal.getItem().equals(bdata) && goal.canCraftItem())
return false;
return true;
}
private void changeObjectiveStatus(AutoRefGoal goal, AutoRefGoal.ItemStatus status)
{
if (!goal.hasItem() || goal.getItemStatus() == status) return;
getMatch().messageReferees("team", this.getName(), "state",
goal.getItem().serialize(), status.toString());
goal.setItemStatus(status);
ObjectiveUpdateEvent event = new ObjectiveUpdateEvent(goal);
AutoReferee.callEvent(event);
}
protected void updateBlockGoals()
{
objloop: for (BlockGoal goal : this.getTeamGoals(BlockGoal.class))
{
if (goal.isSatisfied(getMatch()))
{ changeObjectiveStatus(goal, AutoRefGoal.ItemStatus.TARGET); continue objloop; }
for (AutoRefPlayer apl : getPlayers())
{
if (!apl.getCarrying().containsKey(goal.getItem())) continue;
changeObjectiveStatus(goal, AutoRefGoal.ItemStatus.CARRYING); continue objloop;
}
if (goal.getItemStatus() != AutoRefGoal.ItemStatus.NONE)
{ changeObjectiveStatus(goal, AutoRefGoal.ItemStatus.SEEN); continue objloop; }
}
}
public double getObjectiveScore()
{
double score = 0.0f;
for (AutoRefGoal goal : getTeamGoals())
score += goal.getScore(this.match);
return score;
}
protected void updateCarrying(AutoRefPlayer apl, GoalsInventorySnapshot oldCarrying, GoalsInventorySnapshot newCarrying)
{
match.updateCarrying(apl, oldCarrying, newCarrying);
this.updateBlockGoals();
// pass this information along to the scoreboard
this.updateObjectives();
}
protected void updateHealthArmor(AutoRefPlayer apl,
int currentHealth, int currentArmor, int newHealth, int newArmor)
{
match.updateHealthArmor(apl,
currentHealth, currentArmor, newHealth, newArmor);
}
public int compareTo(AutoRefTeam team)
{ return this.getName().compareTo(team.getName()); }
/**
* Swap the configuration of two teams, including players and custom names.
*/
public static void switchTeams(AutoRefTeam team1, AutoRefTeam team2)
{
// no work to be done
if (team1 == null || team2 == null || team1 == team2) return;
// must be in the same match
if (team1.getMatch() != team2.getMatch()) return;
// switch the sets of players
Set<AutoRefPlayer> t1apls = team1.getPlayers();
Set<AutoRefPlayer> t2apls = team2.getPlayers();
team1.players = t2apls;
team2.players = t1apls;
for (AutoRefPlayer apl1 : team1.getPlayers()) apl1.setTeam(team1);
for (AutoRefPlayer apl2 : team2.getPlayers()) apl2.setTeam(team2);
// switch the custom names
String t1cname = team1.customName;
String t2cname = team2.customName;
team1.customName = t2cname;
team2.customName = t1cname;
}
public JSONTeamData getJSONTeam()
{
JSONTeamData data = new JSONTeamData();
data.customname = this.customName;
data.defaultname = this.getDefaultName();
data.players = Maps.newHashMap();
for (AutoRefPlayer player : this.getPlayers())
data.players.put(player.getName(), player.getJSONPlayer());
return data;
}
}