Fix #790, add playercount and switching scoreboards

* Switching scoreboard jumps between all scoreboard types every minute
* Playercount scoreboard shows number of players per team
This commit is contained in:
Connor Monahan 2017-07-29 02:14:18 -05:00
parent 22cbba62b3
commit 821c66c556
5 changed files with 266 additions and 231 deletions

View File

@ -1,17 +1,10 @@
package com.tommytony.war;
import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.logging.Level;
import com.tommytony.war.config.*;
import com.tommytony.war.spout.SpoutDisplayer;
import com.tommytony.war.utility.Direction;
import com.tommytony.war.volume.Volume;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
@ -22,21 +15,15 @@ import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.Sign;
import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Objective;
import org.getspout.spoutapi.SpoutManager;
import org.getspout.spoutapi.player.SpoutPlayer;
import org.kitteh.tag.TagAPI;
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.TeamSpawnStyle;
import com.tommytony.war.spout.SpoutDisplayer;
import com.tommytony.war.utility.Direction;
import com.tommytony.war.volume.Volume;
import java.io.File;
import java.text.MessageFormat;
import java.util.*;
import java.util.Map.Entry;
import java.util.logging.Level;
/**
*
@ -44,6 +31,8 @@ import com.tommytony.war.volume.Volume;
*
*/
public class Team {
private final Warzone warzone;
Random teamSpawnRandomizer = new Random();
private List<Player> players = new ArrayList<Player>();
private List<Player> teamChatPlayers = new ArrayList<Player>();
private List<Location> teamSpawns;
@ -53,9 +42,7 @@ public class Team {
private int points = 0;
private Map<Location, Volume> spawnVolumes;
private Volume flagVolume;
private final Warzone warzone;
private TeamKind kind;
private TeamConfigBag teamConfig;
private InventoryBag inventories;
@ -119,6 +106,7 @@ public class Team {
initializeTeamSpawn(teamSpawn);
}
}
public void initializeTeamSpawn(Location teamSpawn) {
// Set the spawn
int x = teamSpawn.getBlockX();
@ -382,7 +370,6 @@ public class Team {
return this.teamSpawns;
}
Random teamSpawnRandomizer = new Random();
public Location getRandomSpawn() {
return this.teamSpawns.get(teamSpawnRandomizer.nextInt(this.teamSpawns.size()));
}
@ -395,6 +382,7 @@ public class Team {
if (this.warzone.getScoreboard() != null && this.warzone.getScoreboardType() != ScoreboardType.NONE) {
player.setScoreboard(this.warzone.getScoreboard());
}
warzone.updateScoreboard();
}
public List<Player> getPlayers() {
@ -464,14 +452,14 @@ public class Team {
}
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public void removePlayer(Player thePlayer) {
this.players.remove(thePlayer);
synchronized (teamChatPlayers) {
@ -490,21 +478,18 @@ public class Team {
this.warzone.restorePlayerState(thePlayer);
}
this.warzone.getLoadoutSelections().remove(thePlayer);
}
public void setRemainingLives(int remainingLives) {
this.remainingLives = remainingLives;
if (this.warzone.getScoreboard() != null && this.warzone.getScoreboardType() == ScoreboardType.LIFEPOOL) {
String teamName = kind.getColor() + name + ChatColor.RESET;
Objective obj = this.warzone.getScoreboard().getObjective("Lifepool");
obj.getScore(teamName).setScore(remainingLives);
}
warzone.updateScoreboard();
}
public int getRemainingLives() {
return this.remainingLives;
}
public void setRemainingLives(int remainingLives) {
this.remainingLives = remainingLives;
warzone.updateScoreboard();
}
public void addPoint() {
boolean atLeastOnePlayerOnTeam = this.players.size() != 0;
boolean atLeastOnePlayerOnOtherTeam = false;
@ -518,11 +503,7 @@ public class Team {
} else if (!atLeastOnePlayerOnOtherTeam) {
this.teamcast("zone.score.empty");
}
if (this.warzone.getScoreboardType() == ScoreboardType.POINTS) {
String teamName = kind.getColor() + name + ChatColor.RESET;
this.warzone.getScoreboard().getObjective(DisplaySlot.SIDEBAR)
.getScore(teamName).setScore(points);
}
this.warzone.updateScoreboard();
}
public int getPoints() {
@ -553,22 +534,17 @@ public class Team {
public void resetPoints() {
this.points = 0;
if (this.warzone.getScoreboardType() == ScoreboardType.POINTS
&& this.warzone.getScoreboard() != null) {
String teamName = kind.getColor() + name + ChatColor.RESET;
this.warzone.getScoreboard().getObjective(DisplaySlot.SIDEBAR)
.getScore(teamName).setScore(points);
}
}
public void setFlagVolume(Volume flagVolume) {
this.flagVolume = flagVolume;
warzone.updateScoreboard();
}
public Volume getFlagVolume() {
return this.flagVolume;
}
public void setFlagVolume(Volume flagVolume) {
this.flagVolume = flagVolume;
}
private void setFlagVolume() {
if (this.flagVolume == null) {
this.flagVolume = new Volume(this.getName() + "flag", this.warzone.getWorld());
@ -689,16 +665,6 @@ public class Team {
}
}
public void setTeamFlag(Location teamFlag) {
this.teamFlag = teamFlag;
// this resets the block to old state
this.setFlagVolume();
this.getFlagVolume().saveBlocks();
this.initializeTeamFlag();
}
public boolean isTeamFlagBlock(Block block) {
if (this.teamFlag != null) {
int flagX = this.teamFlag.getBlockX();
@ -715,6 +681,16 @@ public class Team {
return this.teamFlag;
}
public void setTeamFlag(Location teamFlag) {
this.teamFlag = teamFlag;
// this resets the block to old state
this.setFlagVolume();
this.getFlagVolume().saveBlocks();
this.initializeTeamFlag();
}
public void deleteTeamFlag() {
this.getFlagVolume().resetBlocks();
this.setFlagVolume(null);

View File

@ -1,17 +1,23 @@
package com.tommytony.war;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import com.tommytony.war.command.WarCommandHandler;
import com.tommytony.war.config.*;
import com.tommytony.war.event.*;
import com.tommytony.war.job.CapturePointTimer;
import com.tommytony.war.job.HelmetProtectionTask;
import com.tommytony.war.job.ScoreboardSwitchTimer;
import com.tommytony.war.job.SpoutFadeOutMessageJob;
import com.tommytony.war.mapper.WarYmlMapper;
import com.tommytony.war.mapper.WarzoneYmlMapper;
import com.tommytony.war.spout.SpoutDisplayer;
import com.tommytony.war.structure.*;
import com.tommytony.war.ui.UIManager;
import com.tommytony.war.utility.Loadout;
import com.tommytony.war.utility.PlayerState;
import com.tommytony.war.utility.SizeCounter;
import com.tommytony.war.utility.WarLogFormatter;
import com.tommytony.war.volume.Volume;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
@ -29,41 +35,13 @@ import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import com.tommytony.war.command.WarCommandHandler;
import com.tommytony.war.config.FlagReturn;
import com.tommytony.war.config.InventoryBag;
import com.tommytony.war.config.ScoreboardType;
import com.tommytony.war.config.KillstreakReward;
import com.tommytony.war.config.MySQLConfig;
import com.tommytony.war.config.TeamConfig;
import com.tommytony.war.config.TeamConfigBag;
import com.tommytony.war.config.TeamKind;
import com.tommytony.war.config.TeamSpawnStyle;
import com.tommytony.war.config.WarConfig;
import com.tommytony.war.config.WarConfigBag;
import com.tommytony.war.config.WarzoneConfig;
import com.tommytony.war.config.WarzoneConfigBag;
import com.tommytony.war.event.WarBlockListener;
import com.tommytony.war.event.WarEntityListener;
import com.tommytony.war.event.WarPlayerListener;
import com.tommytony.war.event.WarServerListener;
import com.tommytony.war.event.WarTagListener;
import com.tommytony.war.job.HelmetProtectionTask;
import com.tommytony.war.job.SpoutFadeOutMessageJob;
import com.tommytony.war.mapper.WarYmlMapper;
import com.tommytony.war.mapper.WarzoneYmlMapper;
import com.tommytony.war.spout.SpoutDisplayer;
import com.tommytony.war.structure.Bomb;
import com.tommytony.war.structure.Cake;
import com.tommytony.war.structure.HubLobbyMaterials;
import com.tommytony.war.structure.Monument;
import com.tommytony.war.structure.WarHub;
import com.tommytony.war.structure.ZoneLobby;
import com.tommytony.war.utility.Loadout;
import com.tommytony.war.utility.PlayerState;
import com.tommytony.war.utility.SizeCounter;
import com.tommytony.war.utility.WarLogFormatter;
import com.tommytony.war.volume.Volume;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
/**
* Main class of War
@ -72,47 +50,38 @@ import com.tommytony.war.volume.Volume;
* @package bukkit.tommytony.war
*/
public class War extends JavaPlugin {
static final boolean HIDE_BLANK_MESSAGES = true;
public static War war;
private static ResourceBundle messages = ResourceBundle.getBundle("messages");
private final List<String> zoneMakerNames = new ArrayList<String>();
private final List<String> commandWhitelist = new ArrayList<String>();
private final List<Warzone> incompleteZones = new ArrayList<Warzone>();
private final List<String> zoneMakersImpersonatingPlayers = new ArrayList<String>();
private final HashMap<String, String> wandBearers = new HashMap<String, String>(); // playername to zonename
private final List<String> deadlyAdjectives = new ArrayList<String>();
private final List<String> killerVerbs = new ArrayList<String>();
private final InventoryBag defaultInventories = new InventoryBag();
private final WarConfigBag warConfig = new WarConfigBag();
private final WarzoneConfigBag warzoneDefaultConfig = new WarzoneConfigBag();
private final TeamConfigBag teamDefaultConfig = new TeamConfigBag();
// general
private WarPlayerListener playerListener = new WarPlayerListener();
private WarEntityListener entityListener = new WarEntityListener();
private WarBlockListener blockListener = new WarBlockListener();
private WarServerListener serverListener = new WarServerListener();
private WarCommandHandler commandHandler = new WarCommandHandler();
private PluginDescriptionFile desc = null;
private boolean loaded = false;
private boolean isSpoutServer = false;
private boolean tagServer = false;
// Zones and hub
private List<Warzone> warzones = new ArrayList<Warzone>();
private WarHub warHub;
private final List<String> zoneMakerNames = new ArrayList<String>();
private final List<String> commandWhitelist = new ArrayList<String>();
private final List<Warzone> incompleteZones = new ArrayList<Warzone>();
private final List<String> zoneMakersImpersonatingPlayers = new ArrayList<String>();
private HashMap<String, PlayerState> disconnected = new HashMap<String, PlayerState>();
private final HashMap<String, String> wandBearers = new HashMap<String, String>(); // playername to zonename
private final List<String> deadlyAdjectives = new ArrayList<String>();
private final List<String> killerVerbs = new ArrayList<String>();
private final InventoryBag defaultInventories = new InventoryBag();
private KillstreakReward killstreakReward;
private MySQLConfig mysqlConfig;
private Economy econ = null;
private final WarConfigBag warConfig = new WarConfigBag();
private final WarzoneConfigBag warzoneDefaultConfig = new WarzoneConfigBag();
private final TeamConfigBag teamDefaultConfig = new TeamConfigBag();
private SpoutDisplayer spoutMessenger = null;
private static ResourceBundle messages = ResourceBundle.getBundle("messages");
private HubLobbyMaterials warhubMaterials = new HubLobbyMaterials(
new ItemStack(Material.GLASS), new ItemStack(Material.WOOD),
new ItemStack(Material.OBSIDIAN), new ItemStack(Material.GLOWSTONE));
@ -123,6 +92,15 @@ public class War extends JavaPlugin {
War.war = this;
}
public static void reloadLanguage() {
String[] parts = War.war.getWarConfig().getString(WarConfig.LANGUAGE).replace("-", "_").split("_");
Locale lang = new Locale(parts[0]);
if (parts.length >= 2) {
lang = new Locale(parts[0], parts[1]);
}
War.messages = ResourceBundle.getBundle("messages", lang);
}
/**
* @see JavaPlugin#onEnable()
* @see War#loadWar()
@ -295,6 +273,8 @@ public class War extends JavaPlugin {
CapturePointTimer cpt = new CapturePointTimer();
cpt.runTaskTimer(this, 100, 20);
ScoreboardSwitchTimer sst = new ScoreboardSwitchTimer();
sst.runTaskTimer(this, 500, 20 * 60);
if (this.isSpoutServer) {
SpoutFadeOutMessageJob fadeOutMessagesTask = new SpoutFadeOutMessageJob();
@ -343,15 +323,6 @@ public class War extends JavaPlugin {
this.log("War v" + this.desc.getVersion() + " is on.", Level.INFO);
}
public static void reloadLanguage() {
String[] parts = War.war.getWarConfig().getString(WarConfig.LANGUAGE).replace("-", "_").split("_");
Locale lang = new Locale(parts[0]);
if (parts.length >= 2) {
lang = new Locale(parts[0], parts[1]);
}
War.messages = ResourceBundle.getBundle("messages", lang);
}
/**
* Cleans up war
*/
@ -805,7 +776,7 @@ public class War extends JavaPlugin {
}
}
return " ::" + teamColor + "Team " + team.getName() + teamColor + " config" + normalColor + "::"
return " ::" + teamColor + "Team " + team.getName() + teamColor + " config" + normalColor + "::"
+ ifEmptyInheritedForTeam(teamConfigStr);
}
@ -909,7 +880,7 @@ public class War extends JavaPlugin {
return normalColor + "::" + globalColor + "War config" + normalColor + "::" + warConfigStr
+ normalColor + " ::" + zoneColor + "Warzone defaults" + normalColor + "::" + warzoneDefaultsStr
+ normalColor + " ::" + teamColor + "Team defaults" + normalColor + "::" + teamDefaultsStr;
+ normalColor + " ::" + teamColor + "Team defaults" + normalColor + "::" + teamDefaultsStr;
}
private void setZoneRallyPoint(String warzoneName, Player player) {
@ -959,8 +930,6 @@ public class War extends JavaPlugin {
return activeZones;
}
static final boolean HIDE_BLANK_MESSAGES = true;
public void msg(CommandSender sender, String str) {
if (messages.containsKey(str)) str = this.getString(str);
if (HIDE_BLANK_MESSAGES && (str == null || str.isEmpty())) return;
@ -1227,10 +1196,7 @@ public class War extends JavaPlugin {
}
public boolean inAnyWarzoneLobby(Location location) {
if (ZoneLobby.getLobbyByLocation(location) == null) {
return false;
}
return true;
return ZoneLobby.getLobbyByLocation(location) != null;
}
public List<String> getZoneMakersImpersonatingPlayers() {
@ -1293,14 +1259,14 @@ public class War extends JavaPlugin {
return this.spoutMessenger ;
}
public void setWarhubMaterials(HubLobbyMaterials warhubMaterials) {
this.warhubMaterials = warhubMaterials;
}
public HubLobbyMaterials getWarhubMaterials() {
return this.warhubMaterials;
}
public void setWarhubMaterials(HubLobbyMaterials warhubMaterials) {
this.warhubMaterials = warhubMaterials;
}
public boolean isTagServer() {
return tagServer;
}

View File

@ -114,6 +114,7 @@ public class Warzone {
private Random killSeed = new Random();
// prevent tryCallDelayedPlayers from being recursively called by Warzone#assign
private boolean activeDelayedCall = false;
private ScoreboardType scoreboardType;
public Warzone(World world, String name) {
this.world = world;
@ -123,6 +124,9 @@ public class Warzone {
this.volume = new ZoneVolume(name, this.getWorld(), this);
this.lobbyMaterials = War.war.getWarhubMaterials().clone();
this.pvpReady = true;
this.scoreboardType = this.getWarzoneConfig().getScoreboardType(WarzoneConfig.SCOREBOARD);
if (scoreboardType == ScoreboardType.SWITCHING)
scoreboardType = ScoreboardType.LIFEPOOL;
}
public static Warzone getZoneByName(String name) {
@ -386,18 +390,7 @@ public class Warzone {
this.cakeThieves.clear();
if (this.getScoreboardType() != ScoreboardType.NONE) {
this.scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
scoreboard.registerNewObjective(this.getScoreboardType().getDisplayName(), "dummy");
Objective obj = scoreboard.getObjective(this.getScoreboardType().getDisplayName());
Validate.isTrue(obj.isModifiable(), "Cannot modify players' scores on the " + this.name + " scoreboard.");
for (Team team : this.getTeams()) {
String teamName = team.getKind().getColor() + team.getName() + ChatColor.RESET;
if (this.getScoreboardType() == ScoreboardType.POINTS) {
obj.getScore(teamName).setScore(team.getPoints());
} else if (this.getScoreboardType() == ScoreboardType.LIFEPOOL) {
obj.getScore(teamName).setScore(team.getRemainingLives());
}
}
obj.setDisplaySlot(DisplaySlot.SIDEBAR);
this.updateScoreboard();
for (Team team : this.getTeams()) {
for (Player player : team.getPlayers()) {
player.setScoreboard(scoreboard);
@ -1117,10 +1110,7 @@ public class Warzone {
if (attackerTeam.getTeamConfig().resolveBoolean(TeamConfig.KILLSTREAK)) {
War.war.getKillstreakReward().rewardPlayer(attacker, this.getKillCount(attacker.getName()));
}
if (this.getScoreboard() != null && this.getScoreboardType() == ScoreboardType.TOPKILLS) {
Objective obj = this.getScoreboard().getObjective("Top kills");
obj.getScore(attacker.getName()).setScore(this.getKillCount(attacker.getName()));
}
this.updateScoreboard();
if (defenderTeam.getTeamConfig().resolveBoolean(TeamConfig.INVENTORYDROP)) {
dropItems(defender.getLocation(), defender.getInventory().getContents());
dropItems(defender.getLocation(), defender.getInventory().getArmorContents());
@ -1128,6 +1118,53 @@ public class Warzone {
this.handleDeath(defender);
}
public void updateScoreboard() {
if (this.getScoreboardType() == ScoreboardType.NONE)
return;
if (this.getScoreboard() == null)
return;
if (this.scoreboard.getObjective(this.getScoreboardType().getDisplayName()) == null) {
for (String entry : this.scoreboard.getEntries()) {
this.scoreboard.resetScores(entry);
}
this.scoreboard.clearSlot(DisplaySlot.SIDEBAR);
for (Objective obj : this.scoreboard.getObjectives()) {
obj.unregister();
}
scoreboard.registerNewObjective(this.getScoreboardType().getDisplayName(), "dummy");
Objective obj = scoreboard.getObjective(this.getScoreboardType().getDisplayName());
Validate.isTrue(obj.isModifiable(), "Cannot modify players' scores on the " + this.name + " scoreboard.");
obj.setDisplaySlot(DisplaySlot.SIDEBAR);
}
switch (this.getScoreboardType()) {
case POINTS:
for (Team team : this.getTeams()) {
String teamName = team.getKind().getColor() + team.getName() + ChatColor.RESET;
this.getScoreboard().getObjective(DisplaySlot.SIDEBAR).getScore(teamName).setScore(team.getPoints());
}
break;
case LIFEPOOL:
for (Team team : this.getTeams()) {
String teamName = team.getKind().getColor() + team.getName() + ChatColor.RESET;
this.getScoreboard().getObjective(DisplaySlot.SIDEBAR).getScore(teamName).setScore(team.getRemainingLives());
}
break;
case TOPKILLS:
for (Player player : this.getPlayers()) {
this.getScoreboard().getObjective(DisplaySlot.SIDEBAR).getScore(player.getName()).setScore(this.getKillCount(player.getName()));
}
break;
case PLAYERCOUNT:
for (Team team : this.getTeams()) {
String teamName = team.getKind().getColor() + team.getName() + ChatColor.RESET;
this.getScoreboard().getObjective(DisplaySlot.SIDEBAR).getScore(teamName).setScore(team.getPlayers().size());
}
break;
default:
break;
}
}
/**
* Handle death messages before passing to {@link #handleDeath(Player)}
* for post-processing. It's like
@ -1831,7 +1868,17 @@ public class Warzone {
}
public ScoreboardType getScoreboardType() {
return this.getWarzoneConfig().getScoreboardType(WarzoneConfig.SCOREBOARD);
return scoreboardType;
}
/**
* Sets the TEMPORARY scoreboard type for use in this warzone.
* This type will NOT be persisted in the Warzone config.
*
* @param scoreboardType temporary scoreboard type
*/
public void setScoreboardType(ScoreboardType scoreboardType) {
this.scoreboardType = scoreboardType;
}
public boolean hasKillCount(String player) {

View File

@ -5,18 +5,15 @@ public enum ScoreboardType {
NONE(null),
POINTS("Points"),
LIFEPOOL("Lifepool"),
TOPKILLS("Top kills");
TOPKILLS("Top kills"),
PLAYERCOUNT("Player count"),
SWITCHING("Switching");
private final String displayName;
private ScoreboardType(String displayName) {
ScoreboardType(String displayName) {
this.displayName = displayName;
}
@Override
public String toString() {
return super.toString().toLowerCase();
}
public static ScoreboardType getFromString(String string) {
for (ScoreboardType boardMode : ScoreboardType.values()) {
if (string.toLowerCase().equals(boardMode.toString())) {
@ -27,6 +24,11 @@ public enum ScoreboardType {
return ScoreboardType.NONE;
}
@Override
public String toString() {
return super.toString().toLowerCase();
}
public String getDisplayName() {
return displayName;
}

View File

@ -0,0 +1,44 @@
package com.tommytony.war.job;
import com.tommytony.war.War;
import com.tommytony.war.Warzone;
import com.tommytony.war.config.ScoreboardType;
import com.tommytony.war.config.WarzoneConfig;
import org.bukkit.scheduler.BukkitRunnable;
/**
* Switches scoreboards periodically
* Github #790
*/
public class ScoreboardSwitchTimer extends BukkitRunnable {
@Override
public void run() {
if (!War.war.isLoaded()) {
return;
}
for (Warzone zone : War.war.getEnabledWarzones()) {
if (zone.getWarzoneConfig().getScoreboardType(WarzoneConfig.SCOREBOARD) == ScoreboardType.SWITCHING) {
switch (zone.getScoreboardType()) {
case SWITCHING:
zone.setScoreboardType(ScoreboardType.POINTS);
break;
case POINTS:
zone.setScoreboardType(ScoreboardType.LIFEPOOL);
break;
case LIFEPOOL:
zone.setScoreboardType(ScoreboardType.TOPKILLS);
break;
case TOPKILLS:
zone.setScoreboardType(ScoreboardType.PLAYERCOUNT);
break;
case PLAYERCOUNT:
zone.setScoreboardType(ScoreboardType.POINTS);
break;
default:
break;
}
zone.updateScoreboard();
}
}
}
}