diff --git a/Changelog.txt b/Changelog.txt index 8ffec4f87..bb5555621 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -8,6 +8,8 @@ Key: - Removal Version 1.4.06-dev + + Added global scoreboards to track skill rankings (display using /mctop) + + Added per-player scoreboard displays for the /inspect, /mcrank, /mcstats, and / commands + Added tab-complete support for all commands + Added ability to configure drops from Shake in treasures.yml + Added "Master Angler" ability to Fishing. diff --git a/src/main/java/com/gmail/nossr50/commands/player/InspectCommand.java b/src/main/java/com/gmail/nossr50/commands/player/InspectCommand.java index cfd78c4e5..b1b95628a 100644 --- a/src/main/java/com/gmail/nossr50/commands/player/InspectCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/player/InspectCommand.java @@ -10,6 +10,7 @@ import org.bukkit.command.TabExecutor; import org.bukkit.entity.Player; import org.bukkit.util.StringUtil; +import com.gmail.nossr50.config.Config; import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.player.PlayerProfile; import com.gmail.nossr50.datatypes.skills.SkillType; @@ -17,6 +18,7 @@ import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.commands.CommandUtils; import com.gmail.nossr50.util.player.UserManager; +import com.gmail.nossr50.util.scoreboards.ScoreboardManager; import com.google.common.collect.ImmutableList; @@ -25,6 +27,10 @@ public class InspectCommand implements TabExecutor { public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { switch (args.length) { case 1: + if (sender instanceof Player && Config.getInstance().getInspectScoreboardEnabled()) { + ScoreboardManager.setupPlayerScoreboard(sender.getName()); + } + McMMOPlayer mcMMOPlayer = UserManager.getPlayer(args[0]); // If the mcMMOPlayer doesn't exist, create a temporary profile and check if it's present in the database. If it's not, abort the process. @@ -35,6 +41,11 @@ public class InspectCommand implements TabExecutor { return true; } + if (sender instanceof Player && Config.getInstance().getInspectScoreboardEnabled()) { + ScoreboardManager.enablePlayerInspectScoreboardOffline((Player) sender, profile); + return true; + } + sender.sendMessage(LocaleLoader.getString("Inspect.OfflineStats", args[0])); sender.sendMessage(LocaleLoader.getString("Stats.Header.Gathering")); @@ -62,6 +73,11 @@ public class InspectCommand implements TabExecutor { return true; } + if (sender instanceof Player && Config.getInstance().getInspectScoreboardEnabled()) { + ScoreboardManager.enablePlayerInspectScoreboardOnline((Player) sender, mcMMOPlayer); + return true; + } + sender.sendMessage(LocaleLoader.getString("Inspect.Stats", target.getName())); CommandUtils.printGatheringSkills(target, sender); CommandUtils.printCombatSkills(target, sender); diff --git a/src/main/java/com/gmail/nossr50/commands/player/McrankCommand.java b/src/main/java/com/gmail/nossr50/commands/player/McrankCommand.java index f007bda10..4ec06d233 100644 --- a/src/main/java/com/gmail/nossr50/commands/player/McrankCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/player/McrankCommand.java @@ -7,15 +7,18 @@ import java.util.Set; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; import org.bukkit.util.StringUtil; import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.config.Config; import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.player.PlayerProfile; import com.gmail.nossr50.runnables.commands.McrankCommandAsyncTask; import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.commands.CommandUtils; import com.gmail.nossr50.util.player.UserManager; +import com.gmail.nossr50.util.scoreboards.ScoreboardManager; import com.google.common.collect.ImmutableList; public class McrankCommand implements TabExecutor { @@ -32,7 +35,14 @@ public class McrankCommand implements TabExecutor { return true; } - display(sender, sender.getName()); + if (Config.getInstance().getMcrankScoreboardEnabled()) { + ScoreboardManager.setupPlayerScoreboard(sender.getName()); + ScoreboardManager.enablePlayerRankScoreboard((Player) sender); + } + else { + display(sender, sender.getName()); + } + return true; case 1: @@ -55,7 +65,13 @@ public class McrankCommand implements TabExecutor { return true; } - display(sender, playerName); + if (sender instanceof Player && Config.getInstance().getMcrankScoreboardEnabled()) { + ScoreboardManager.setupPlayerScoreboard(sender.getName()); + ScoreboardManager.enablePlayerRankScoreboardOthers((Player) sender, playerName); + } + else { + display(sender, playerName); + } return true; default: diff --git a/src/main/java/com/gmail/nossr50/commands/player/McstatsCommand.java b/src/main/java/com/gmail/nossr50/commands/player/McstatsCommand.java index eccca9189..8218e7aa3 100644 --- a/src/main/java/com/gmail/nossr50/commands/player/McstatsCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/player/McstatsCommand.java @@ -12,7 +12,7 @@ import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.util.commands.CommandUtils; import com.gmail.nossr50.util.player.UserManager; - +import com.gmail.nossr50.util.scoreboards.ScoreboardManager; import com.google.common.collect.ImmutableList; public class McstatsCommand implements TabExecutor { @@ -27,20 +27,26 @@ public class McstatsCommand implements TabExecutor { McMMOPlayer mcMMOPlayer = UserManager.getPlayer(sender.getName()); Player player = mcMMOPlayer.getPlayer(); - player.sendMessage(LocaleLoader.getString("Stats.Own.Stats")); - player.sendMessage(LocaleLoader.getString("mcMMO.NoSkillNote")); - - CommandUtils.printGatheringSkills(player); - CommandUtils.printCombatSkills(player); - CommandUtils.printMiscSkills(player); - - int powerLevelCap = Config.getInstance().getPowerLevelCap(); - - if (powerLevelCap != Integer.MAX_VALUE) { - player.sendMessage(LocaleLoader.getString("Commands.PowerLevel.Capped", UserManager.getPlayer(player).getPowerLevel(), powerLevelCap)); + if (Config.getInstance().getMcstatsScoreboardsEnabled()) { + ScoreboardManager.setupPlayerScoreboard(player.getName()); + ScoreboardManager.enablePlayerStatsScoreboard(mcMMOPlayer); } else { - player.sendMessage(LocaleLoader.getString("Commands.PowerLevel", UserManager.getPlayer(player).getPowerLevel())); + player.sendMessage(LocaleLoader.getString("Stats.Own.Stats")); + player.sendMessage(LocaleLoader.getString("mcMMO.NoSkillNote")); + + CommandUtils.printGatheringSkills(player); + CommandUtils.printCombatSkills(player); + CommandUtils.printMiscSkills(player); + + int powerLevelCap = Config.getInstance().getPowerLevelCap(); + + if (powerLevelCap != Integer.MAX_VALUE) { + player.sendMessage(LocaleLoader.getString("Commands.PowerLevel.Capped", UserManager.getPlayer(player).getPowerLevel(), powerLevelCap)); + } + else { + player.sendMessage(LocaleLoader.getString("Commands.PowerLevel", UserManager.getPlayer(player).getPowerLevel())); + } } return true; diff --git a/src/main/java/com/gmail/nossr50/commands/player/MctopCommand.java b/src/main/java/com/gmail/nossr50/commands/player/MctopCommand.java index 663912609..cc296cfca 100644 --- a/src/main/java/com/gmail/nossr50/commands/player/MctopCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/player/MctopCommand.java @@ -7,17 +7,20 @@ import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; import org.bukkit.util.StringUtil; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.database.FlatfileDatabaseManager; +import com.gmail.nossr50.datatypes.database.PlayerStat; import com.gmail.nossr50.datatypes.skills.SkillType; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.runnables.commands.MctopCommandAsyncTask; import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.StringUtils; import com.gmail.nossr50.util.commands.CommandUtils; +import com.gmail.nossr50.util.scoreboards.ScoreboardManager; import com.google.common.collect.ImmutableList; @@ -77,11 +80,16 @@ public class MctopCommand implements TabExecutor { return; } - if (Config.getInstance().getUseMySQL()) { - sqlDisplay(page, skill, sender); + if (sender instanceof Player && Config.getInstance().getMctopScoreboardEnabled()) { + ScoreboardManager.enableGlobalStatsScoreboard((Player) sender, skill, page); } else { - flatfileDisplay(page, skill, sender); + if (Config.getInstance().getUseMySQL()) { + sqlDisplay(page, skill, sender); + } + else { + flatfileDisplay(page, skill, sender); + } } } @@ -97,21 +105,11 @@ public class MctopCommand implements TabExecutor { int position = (page * 10) - 9; - for (String playerStat : FlatfileDatabaseManager.retrieveInfo(skill, page)) { - if (playerStat == null) { - continue; - } - - String digit = String.valueOf(position); - - if (position < 10) { - digit = "0" + digit; - } - - String[] splitStat = playerStat.split(":"); + for (PlayerStat stat : FlatfileDatabaseManager.retrieveInfo(skill, page, 10)) { + String digit = (position < 10) ? "0" : "" + String.valueOf(position); // Format: 1. Playername - skill value - sender.sendMessage(digit + ". " + ChatColor.GREEN + splitStat[1] + " - " + ChatColor.WHITE + splitStat[0]); + sender.sendMessage(digit + ". " + ChatColor.GREEN + stat.name + " - " + ChatColor.WHITE + stat.statVal); position++; } diff --git a/src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java b/src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java index 6635d68fb..9c68bf3a1 100644 --- a/src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java @@ -11,6 +11,7 @@ import org.bukkit.command.TabExecutor; import org.bukkit.entity.Player; import com.gmail.nossr50.config.AdvancedConfig; +import com.gmail.nossr50.config.Config; import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.player.PlayerProfile; import com.gmail.nossr50.datatypes.skills.SkillType; @@ -20,6 +21,7 @@ import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.StringUtils; import com.gmail.nossr50.util.commands.CommandUtils; import com.gmail.nossr50.util.player.UserManager; +import com.gmail.nossr50.util.scoreboards.ScoreboardManager; import com.gmail.nossr50.util.skills.PerksUtils; import com.gmail.nossr50.util.skills.SkillUtils; @@ -71,7 +73,14 @@ public abstract class SkillCommand implements TabExecutor { if (!skill.isChildSkill()) { player.sendMessage(LocaleLoader.getString("Skills.Header", skillName)); player.sendMessage(LocaleLoader.getString("Commands.XPGain", LocaleLoader.getString("Commands.XPGain." + StringUtils.getCapitalized(skill.toString())))); - player.sendMessage(LocaleLoader.getString("Effects.Level", (int) skillValue, profile.getSkillXpLevel(skill), profile.getXpToLevel(skill))); + + if (Config.getInstance().getSkillScoreboardEnabled()) { + ScoreboardManager.setupPlayerScoreboard(player.getName()); + ScoreboardManager.enablePlayerSkillScoreboard(mcMMOPlayer, skill); + } + else { + player.sendMessage(LocaleLoader.getString("Effects.Level", (int) skillValue, profile.getSkillXpLevel(skill), profile.getXpToLevel(skill))); + } } else { player.sendMessage(LocaleLoader.getString("Skills.Header", skillName + " " + LocaleLoader.getString("Skills.Child"))); diff --git a/src/main/java/com/gmail/nossr50/config/Config.java b/src/main/java/com/gmail/nossr50/config/Config.java index 1b6599e20..adf70a2fd 100644 --- a/src/main/java/com/gmail/nossr50/config/Config.java +++ b/src/main/java/com/gmail/nossr50/config/Config.java @@ -61,6 +61,22 @@ public class Config extends AutoUpdateConfigLoader { public int getMobHealthbarTime() { return config.getInt("Mob_Healthbar.Display_Time", 3); } + /* Scoreboards */ + public boolean getMcrankScoreboardEnabled() { return config.getBoolean("Scoreboards.Mcrank.Use", true); } + public int getMcrankScoreboardTime() { return config.getInt("Scoreboards.Mcrank.Display_Time", 10); } + + public boolean getMcstatsScoreboardsEnabled() { return config.getBoolean("Scoreboards.Mcstats.Use", true); } + public int getMcstatsScoreboardTime() { return config.getInt("Scoreboards.Mctop.Display_Time", 10); } + + public boolean getMctopScoreboardEnabled() { return config.getBoolean("Scoreboards.Mctop.Use", true); } + public int getMctopScoreboardTime() { return config.getInt("Scoreboards.Mctop.Display_Time", 10); } + + public boolean getInspectScoreboardEnabled() { return config.getBoolean("Scoreboards.Inspect.Use", true); } + public int getInspectScoreboardTime() { return config.getInt("Scoreboards.Inspect.Display_Time", 10); } + + public boolean getSkillScoreboardEnabled() { return config.getBoolean("Scoreboards.Skillname.Use", true); } + public int getSkillScoreboardTime() { return config.getInt("Scoreboards.Skillname.Display_Time", 10); } + /* Database Purging */ public int getPurgeInterval() { return config.getInt("Database_Purging.Purge_Interval", -1); } public int getOldUsersCutoff() { return config.getInt("Database_Purging.Old_User_Cutoff", 6); } diff --git a/src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java b/src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java index 1206ee713..0b0921e78 100644 --- a/src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java +++ b/src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java @@ -131,30 +131,11 @@ public final class FlatfileDatabaseManager { * @param pageNumber Which page in the leaderboards to retrieve * @return the requested leaderboard information */ - public static String[] retrieveInfo(String skillType, int pageNumber) { - String[] info = new String[10]; - List statsList; + public static List retrieveInfo(String skillType, int pageNumber, int statsPerPage) { + List statsList = skillType.equalsIgnoreCase("all") ? powerLevels : playerStatHash.get(SkillType.getSkill(skillType)); + int fromIndex = (Math.max(pageNumber, 1) - 1) * statsPerPage; - if (skillType.equalsIgnoreCase("all")) { - statsList = powerLevels; - } - else { - statsList = playerStatHash.get(SkillType.getSkill(skillType)); - } - - if (pageNumber < 1) { - pageNumber = 1; - } - int destination = (pageNumber - 1) * 10; - - for (int i = 0; i < 10; i++) { - if (destination + i < statsList.size()) { - PlayerStat ps = statsList.get(destination + i); - info[i] = ps.name + ":" + ps.statVal; - } - } - - return info; + return statsList.subList(Math.min(fromIndex, statsList.size()), Math.min(fromIndex + statsPerPage, statsList.size())); } public static boolean removeFlatFileUser(String playerName) { @@ -326,6 +307,10 @@ public final class FlatfileDatabaseManager { return skills; } + public static List getPlayerStats(String skillName) { + return (skillName.equalsIgnoreCase("all")) ? powerLevels : playerStatHash.get(SkillType.getSkill(skillName)); + } + private static int loadStat(List statList, String playerName, String[] data, int dataIndex) { if (data.length > dataIndex) { int statValue = Integer.parseInt(data[dataIndex]); diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java b/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java index bb52dfc0a..1d07d713f 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java @@ -9,6 +9,8 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; +import org.bukkit.scoreboard.Scoreboard; + import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.spout.SpoutConfig; @@ -30,6 +32,7 @@ public class PlayerProfile { private HudType hudType; private MobHealthbarType mobHealthbarType; private McMMOHud spoutHud; + private Scoreboard playerStatsScoreboard; /* Skill Data */ private final Map skills = new HashMap(); // Skill & Level @@ -70,6 +73,10 @@ public class PlayerProfile { } } + public String getPlayerName() { + return playerName; + } + public boolean isLoaded() { return loaded; } @@ -106,6 +113,18 @@ public class PlayerProfile { this.mobHealthbarType = mobHealthbarType; } + /* + * Scoreboards + */ + + public Scoreboard getPlayerStatsScoreboard() { + return playerStatsScoreboard; + } + + public void setPlayerStatsScoreboard(Scoreboard statsScoreboard) { + this.playerStatsScoreboard = statsScoreboard; + } + /* * Cooldowns */ diff --git a/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java b/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java index 08cf68db3..d5c5053cc 100644 --- a/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java @@ -32,7 +32,7 @@ public class McrankCommandDisplayTask extends BukkitRunnable { sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Player", playerName)); for (SkillType skill : SkillType.values()) { - if (skill.isChildSkill() || !Permissions.skillEnabled(player, skill)) { + if (skill.isChildSkill() || (player != null && !Permissions.skillEnabled(player, skill))) { continue; } diff --git a/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandAsyncTask.java b/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandAsyncTask.java index ad29b1abb..a74757a1b 100644 --- a/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandAsyncTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandAsyncTask.java @@ -1,7 +1,7 @@ package com.gmail.nossr50.runnables.commands; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Collection; import org.bukkit.command.CommandSender; import org.bukkit.scheduler.BukkitRunnable; @@ -11,7 +11,6 @@ import com.gmail.nossr50.config.Config; import com.gmail.nossr50.database.SQLDatabaseManager; public class MctopCommandAsyncTask extends BukkitRunnable { - private CommandSender sender; private String query; private int page; @@ -25,8 +24,8 @@ public class MctopCommandAsyncTask extends BukkitRunnable { @Override public void run() { String tablePrefix = Config.getInstance().getMySQLTablePrefix(); - final HashMap> userslist = SQLDatabaseManager.read("SELECT " + query + ", user, NOW() FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON (user_id = id) WHERE " + query + " > 0 ORDER BY " + query + " DESC, user LIMIT " + ((page * 10) - 10) + ",10"); + final Collection> userStats = SQLDatabaseManager.read("SELECT " + query + ", user, NOW() FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON (user_id = id) WHERE " + query + " > 0 ORDER BY " + query + " DESC, user LIMIT " + ((page * 10) - 10) + ",10").values(); - new MctopCommandDisplayTask(userslist, page, tablePrefix, sender).runTaskLater(mcMMO.p, 1); + new MctopCommandDisplayTask(userStats, page, tablePrefix, sender).runTaskLater(mcMMO.p, 1); } } diff --git a/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandDisplayTask.java b/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandDisplayTask.java index 472bb8e8b..d50eba990 100644 --- a/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandDisplayTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandDisplayTask.java @@ -1,7 +1,7 @@ package com.gmail.nossr50.runnables.commands; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Collection; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; @@ -11,13 +11,13 @@ import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.util.StringUtils; public class MctopCommandDisplayTask extends BukkitRunnable { - private HashMap> userslist; + private Collection> userStats; private CommandSender sender; private String query; private int page; - public MctopCommandDisplayTask(HashMap> userslist, int page, String query, CommandSender sender) { - this.userslist = userslist; + public MctopCommandDisplayTask(Collection> userStats, int page, String query, CommandSender sender) { + this.userStats = userStats; this.page = page; this.query = query; this.sender = sender; @@ -33,13 +33,12 @@ public class MctopCommandDisplayTask extends BukkitRunnable { } int place = (page * 10) - 9; - for (int i = 1; i <= 10; i++) { - if (userslist.get(i) == null) { - break; - } + + for (ArrayList stat : userStats) { + String digit = (place < 10) ? "0" : "" + String.valueOf(place); // Format: 1. Playername - skill value - sender.sendMessage(place + ". " + ChatColor.GREEN + userslist.get(i).get(1) + " - " + ChatColor.WHITE + userslist.get(i).get(0)); + sender.sendMessage(digit + ". " + ChatColor.GREEN + stat.get(1) + " - " + ChatColor.WHITE + stat.get(0)); place++; } diff --git a/src/main/java/com/gmail/nossr50/runnables/scoreboards/ScoreboardChangeTask.java b/src/main/java/com/gmail/nossr50/runnables/scoreboards/ScoreboardChangeTask.java new file mode 100644 index 000000000..c24766114 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/runnables/scoreboards/ScoreboardChangeTask.java @@ -0,0 +1,23 @@ +package com.gmail.nossr50.runnables.scoreboards; + +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scoreboard.Scoreboard; + +import com.gmail.nossr50.util.scoreboards.ScoreboardManager; + +public class ScoreboardChangeTask extends BukkitRunnable { + private Player player; + private Scoreboard oldScoreboard; + + public ScoreboardChangeTask(Player player, Scoreboard oldScoreboard) { + this.player = player; + this.oldScoreboard = oldScoreboard; + } + + @Override + public void run() { + player.setScoreboard(oldScoreboard); + ScoreboardManager.clearPendingTask(player.getName()); + } +} diff --git a/src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java b/src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java new file mode 100644 index 000000000..84b3a421f --- /dev/null +++ b/src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java @@ -0,0 +1,312 @@ +package com.gmail.nossr50.util.scoreboards; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.bukkit.ChatColor; +import org.bukkit.Server; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.DisplaySlot; +import org.bukkit.scoreboard.Objective; +import org.bukkit.scoreboard.Scoreboard; + +import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.database.FlatfileDatabaseManager; +import com.gmail.nossr50.database.SQLDatabaseManager; +import com.gmail.nossr50.config.Config; +import com.gmail.nossr50.datatypes.database.PlayerStat; +import com.gmail.nossr50.datatypes.player.McMMOPlayer; +import com.gmail.nossr50.datatypes.player.PlayerProfile; +import com.gmail.nossr50.datatypes.skills.SkillType; +import com.gmail.nossr50.runnables.scoreboards.ScoreboardChangeTask; +import com.gmail.nossr50.util.Permissions; +import com.gmail.nossr50.util.skills.SkillUtils; + +public class ScoreboardManager { + private static final Map PLAYER_SCOREBOARDS = new HashMap(); + private static final Scoreboard GLOBAL_STATS_SCOREBOARD = mcMMO.p.getServer().getScoreboardManager().getNewScoreboard(); + + private final static String PLAYER_STATS_HEADER = "mcMMO Stats"; + private final static String PLAYER_RANK_HEADER = "mcMMO Rankings"; + private final static String PLAYER_INSPECT_HEADER = "mcMMO Stats: "; + + private final static List SCOREBOARD_TASKS = new ArrayList(); + + public static void setupPlayerScoreboard(String playerName) { + if (PLAYER_SCOREBOARDS.containsKey(playerName)) { + return; + } + + PLAYER_SCOREBOARDS.put(playerName, mcMMO.p.getServer().getScoreboardManager().getNewScoreboard()); + } + + public static void enablePlayerSkillScoreboard(McMMOPlayer mcMMOPlayer, SkillType skill) { + Player player = mcMMOPlayer.getPlayer(); + Scoreboard oldScoreboard = player.getScoreboard(); + Scoreboard newScoreboard = PLAYER_SCOREBOARDS.get(player.getName()); + Objective objective = newScoreboard.getObjective(SkillUtils.getSkillName(skill)); + + if (objective == null) { + objective = newScoreboard.registerNewObjective(SkillUtils.getSkillName(skill), "dummy"); + } + + updatePlayerSkillScores(mcMMOPlayer.getProfile(), skill, objective); + changeScoreboard(player, oldScoreboard, newScoreboard, Config.getInstance().getSkillScoreboardTime()); + } + + public static void enablePlayerStatsScoreboard(McMMOPlayer mcMMOPlayer) { + Player player = mcMMOPlayer.getPlayer(); + Scoreboard oldScoreboard = player.getScoreboard(); + Scoreboard newScoreboard = PLAYER_SCOREBOARDS.get(player.getName()); + Objective objective = newScoreboard.getObjective(PLAYER_STATS_HEADER); + + if (objective == null) { + objective = newScoreboard.registerNewObjective(PLAYER_STATS_HEADER, "dummy"); + } + + updatePlayerStatsScores(mcMMOPlayer, objective); + changeScoreboard(player, oldScoreboard, newScoreboard, Config.getInstance().getMcstatsScoreboardTime()); + } + + public static void enablePlayerRankScoreboard(Player player) { + Scoreboard oldScoreboard = player.getScoreboard(); + Scoreboard newScoreboard = PLAYER_SCOREBOARDS.get(player.getName()); + Objective objective = newScoreboard.getObjective(PLAYER_RANK_HEADER); + + if (objective == null) { + objective = newScoreboard.registerNewObjective(PLAYER_RANK_HEADER, "dummy"); + } + + updatePlayerRankScores(player, objective); + changeScoreboard(player, oldScoreboard, newScoreboard, Config.getInstance().getMcrankScoreboardTime()); + } + + public static void enablePlayerRankScoreboardOthers(Player player, String targetName) { + Scoreboard oldScoreboard = player.getScoreboard(); + Scoreboard newScoreboard = PLAYER_SCOREBOARDS.get(player.getName()); + Objective objective = newScoreboard.getObjective(PLAYER_RANK_HEADER); + + if (objective == null) { + objective = newScoreboard.registerNewObjective(PLAYER_RANK_HEADER, "dummy"); + } + + updatePlayerRankOthersScores(targetName, objective); + changeScoreboard(player, oldScoreboard, newScoreboard, Config.getInstance().getMcrankScoreboardTime()); + } + + public static void enablePlayerInspectScoreboardOnline(Player player, McMMOPlayer mcMMOTarget) { + Scoreboard oldScoreboard = player.getScoreboard(); + Scoreboard newScoreboard = PLAYER_SCOREBOARDS.get(player.getName()); + Objective objective = newScoreboard.getObjective(PLAYER_INSPECT_HEADER); + + if (objective == null) { + objective = newScoreboard.registerNewObjective(PLAYER_INSPECT_HEADER, "dummy"); + } + + updatePlayerInspectOnlineScores(mcMMOTarget, objective); + changeScoreboard(player, oldScoreboard, newScoreboard, Config.getInstance().getInspectScoreboardTime()); + } + + public static void enablePlayerInspectScoreboardOffline(Player player, PlayerProfile targetProfile) { + Scoreboard oldScoreboard = player.getScoreboard(); + Scoreboard newScoreboard = PLAYER_SCOREBOARDS.get(player.getName()); + Objective objective = newScoreboard.getObjective(PLAYER_INSPECT_HEADER); + + if (objective == null) { + objective = newScoreboard.registerNewObjective(PLAYER_INSPECT_HEADER, "dummy"); + } + + updatePlayerInspectOfflineScores(targetProfile, objective); + changeScoreboard(player, oldScoreboard, newScoreboard, Config.getInstance().getInspectScoreboardTime()); + } + + public static void enableGlobalStatsScoreboard(Player player, String skillName, int pageNumber) { + Objective oldObjective = GLOBAL_STATS_SCOREBOARD.getObjective(skillName); + Scoreboard oldScoreboard = player.getScoreboard(); + + if (oldObjective != null) { + oldObjective.unregister(); + } + + Objective newObjective = GLOBAL_STATS_SCOREBOARD.registerNewObjective(skillName, "dummy"); + newObjective.setDisplayName(ChatColor.GOLD + (skillName.equalsIgnoreCase("all") ? "Power Level" : SkillUtils.getSkillName(SkillType.getSkill(skillName)))); + + updateGlobalStatsScores(player, newObjective, skillName, pageNumber); + changeScoreboard(player, oldScoreboard, GLOBAL_STATS_SCOREBOARD, Config.getInstance().getMctopScoreboardTime()); + } + + private static void updatePlayerSkillScores(PlayerProfile profile, SkillType skill, Objective objective) { + Server server = mcMMO.p.getServer(); + + objective.getScore(server.getOfflinePlayer("Level")).setScore(profile.getSkillLevel(skill)); + objective.getScore(server.getOfflinePlayer("Current XP")).setScore(profile.getSkillXpLevel(skill)); + objective.getScore(server.getOfflinePlayer("Remaining XP")).setScore(profile.getXpToLevel(skill)); + + objective.setDisplaySlot(DisplaySlot.SIDEBAR); + } + + private static void updatePlayerStatsScores(McMMOPlayer mcMMOPlayer, Objective objective) { + Player player = mcMMOPlayer.getPlayer(); + PlayerProfile profile = mcMMOPlayer.getProfile(); + Server server = mcMMO.p.getServer(); + + for (SkillType skill : SkillType.values()) { + if (skill.isChildSkill() || !Permissions.skillEnabled(player, skill)) { + continue; + } + + objective.getScore(server.getOfflinePlayer(SkillUtils.getSkillName(skill))).setScore(profile.getSkillLevel(skill)); + } + + objective.getScore(server.getOfflinePlayer(ChatColor.GOLD + "Power Level")).setScore(mcMMOPlayer.getPowerLevel()); + objective.setDisplaySlot(DisplaySlot.SIDEBAR); + } + + private static void updatePlayerRankScores(Player player, Objective objective) { + String playerName = player.getName(); + Server server = mcMMO.p.getServer(); + Integer rank; + + Map skills = Config.getInstance().getUseMySQL() ? SQLDatabaseManager.readSQLRank(playerName) : FlatfileDatabaseManager.getPlayerRanks(playerName); + + for (SkillType skill : SkillType.values()) { + if (skill.isChildSkill() || !Permissions.skillEnabled(player, skill)) { + continue; + } + + rank = skills.get(skill.name()); + + if (rank != null) { + objective.getScore(server.getOfflinePlayer(SkillUtils.getSkillName(skill))).setScore(rank); + } + } + + rank = skills.get("ALL"); + + if (rank != null) { + objective.getScore(server.getOfflinePlayer(ChatColor.GOLD + "Overall")).setScore(rank); + } + + objective.setDisplaySlot(DisplaySlot.SIDEBAR); + } + + private static void updatePlayerRankOthersScores(String targetName, Objective objective) { + Server server = mcMMO.p.getServer(); + Integer rank; + + Map skills = Config.getInstance().getUseMySQL() ? SQLDatabaseManager.readSQLRank(targetName) : FlatfileDatabaseManager.getPlayerRanks(targetName); + + for (SkillType skill : SkillType.values()) { + if (skill.isChildSkill()) { + continue; + } + + rank = skills.get(skill.name()); + + if (rank != null) { + objective.getScore(server.getOfflinePlayer(SkillUtils.getSkillName(skill))).setScore(rank); + } + } + + rank = skills.get("ALL"); + + if (rank != null) { + objective.getScore(server.getOfflinePlayer(ChatColor.GOLD + "Overall")).setScore(rank); + } + + objective.setDisplayName(PLAYER_RANK_HEADER + ": " + targetName); + objective.setDisplaySlot(DisplaySlot.SIDEBAR); + } + + private static void updatePlayerInspectOnlineScores(McMMOPlayer mcMMOTarget, Objective objective) { + Player target = mcMMOTarget.getPlayer(); + PlayerProfile profile = mcMMOTarget.getProfile(); + Server server = mcMMO.p.getServer(); + int powerLevel = 0; + int skillLevel; + + for (SkillType skill : SkillType.values()) { + if (skill.isChildSkill() || !Permissions.skillEnabled(target, skill)) { + continue; + } + + skillLevel = profile.getSkillLevel(skill); + objective.getScore(server.getOfflinePlayer(SkillUtils.getSkillName(skill))).setScore(skillLevel); + powerLevel += skillLevel; + } + + objective.getScore(server.getOfflinePlayer(ChatColor.GOLD + "Power Level")).setScore(powerLevel); + objective.setDisplayName(PLAYER_INSPECT_HEADER + target.getName()); + objective.setDisplaySlot(DisplaySlot.SIDEBAR); + } + + private static void updatePlayerInspectOfflineScores(PlayerProfile targetProfile, Objective objective) { + Server server = mcMMO.p.getServer(); + int powerLevel = 0; + int skillLevel; + + for (SkillType skill : SkillType.values()) { + if (skill.isChildSkill()) { + continue; + } + + skillLevel = targetProfile.getSkillLevel(skill); + objective.getScore(server.getOfflinePlayer(SkillUtils.getSkillName(skill))).setScore(skillLevel); + powerLevel += skillLevel; + } + + objective.getScore(server.getOfflinePlayer(ChatColor.GOLD + "Power Level")).setScore(powerLevel); + objective.setDisplayName(PLAYER_INSPECT_HEADER + targetProfile.getPlayerName()); + } + + private static void updateGlobalStatsScores(Player player, Objective objective, String skillName, int pageNumber) { + int position = (pageNumber * 15) - 14; + String startPosition = ((position < 10) ? "0" : "") + String.valueOf(position); + String endPosition = String.valueOf(position + 14); + Server server = mcMMO.p.getServer(); + + if (Config.getInstance().getUseMySQL()) { + String tablePrefix = Config.getInstance().getMySQLTablePrefix(); + String query = (skillName.equalsIgnoreCase("all") ? "taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing" : skillName); + final Collection> userStats = SQLDatabaseManager.read("SELECT " + query + ", user, NOW() FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON (user_id = id) WHERE " + query + " > 0 ORDER BY " + query + " DESC, user LIMIT " + ((pageNumber * 15) - 15) + ",15").values(); + + for (ArrayList stat : userStats) { + String playerName = stat.get(1); + playerName = (playerName.equals(player.getName()) ? ChatColor.GOLD : "") + playerName; + + objective.getScore(server.getOfflinePlayer(playerName)).setScore(Integer.valueOf(stat.get(0))); + } + } + else { + for (PlayerStat stat : FlatfileDatabaseManager.retrieveInfo(skillName, pageNumber, 15)) { + String playerName = stat.name; + playerName = (playerName.equals(player.getName()) ? ChatColor.GOLD : "") + playerName; + + objective.getScore(server.getOfflinePlayer(playerName)).setScore(stat.statVal); + } + } + + objective.setDisplayName(objective.getDisplayName() + " (" + startPosition + " - " + endPosition + ")"); + objective.setDisplaySlot(DisplaySlot.SIDEBAR); + } + + private static void changeScoreboard(Player player, Scoreboard oldScoreboard, Scoreboard newScoreboard, int displayTime) { + if (oldScoreboard != newScoreboard) { + String playerName = player.getName(); + + player.setScoreboard(newScoreboard); + + if (displayTime != -1 && !SCOREBOARD_TASKS.contains(playerName)) { + new ScoreboardChangeTask(player, oldScoreboard).runTaskLater(mcMMO.p, displayTime * 20); + SCOREBOARD_TASKS.add(playerName); + } + } + } + + public static void clearPendingTask(String playerName) { + SCOREBOARD_TASKS.remove(playerName); + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index f9a7e3e27..f287d0421 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -27,6 +27,34 @@ General: # Should mcMMO over-write configs to update, or make new ones ending in .new? Config_Update_Overwrite: true +Scoreboards: + Inspect: + # Should mcMMO use scoreboards for /inspect? + Use: true + # Amount of time (in seconds) to display. To display permanently, set to -1 + Display_Time: 10 + Mcrank: + # Should mcMMO use scoreboards for /mcrank? + Use: true + # Amount of time (in seconds) to display. To display permanently, set to -1 + Display_Time: 10 + Mcstats: + # Should mcMMO use scoreboards for /mcstats? + Use: true + # Amount of time (in seconds) to display. To display permanently, set to -1 + Display_Time: 10 + Mctop: + # Should mcMMO use scoreboards for /mctop? + Use: true + # Amount of time (in seconds) to display. To display permanently, set to -1 + Display_Time: 10 + Skillname: + # Should mcMMO use scoreboards for /skillname (/mining, /fishing, etc.)? + Use: true + # Amount of time (in seconds) to display. To display permanently, set to -1 + Display_Time: 10 + + Mob_Healthbar: # Default display for mob health bars - HEARTS, BAR, or DISABLED Display_Type: HEARTS