/******************************************************************************* * This file is part of ASkyBlock. * * ASkyBlock is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ASkyBlock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ASkyBlock. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ package com.wasteofplastic.askyblock; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryType.SlotType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.SkullMeta; import com.wasteofplastic.askyblock.util.MapUtil; import com.wasteofplastic.askyblock.util.Util; /** * Handles all Top Ten List functions * * @author tastybento * */ public class TopTen implements Listener{ private static ASkyBlock plugin = ASkyBlock.getPlugin(); // Top ten list of players private static Map<UUID, Integer> topTenList = new HashMap<UUID, Integer>(); private static final int GUISIZE = 27; // Must be a multiple of 9 private static final int[] SLOTS = new int[] {4, 12, 14, 19, 20, 21, 22, 23, 24, 25}; // Store this as a static because it's the same for everyone and saves memory cleanup private static Inventory gui; public TopTen(ASkyBlock plugin) { TopTen.plugin = plugin; } /** * Adds a player to the top ten, if the level is good enough * * @param ownerUUID * @param level */ public static void topTenAddEntry(UUID ownerUUID, int level) { // Special case for removals. If a level of zero is given the player // needs to be removed from the list if (level < 1) { if (topTenList.containsKey(ownerUUID)) { topTenList.remove(ownerUUID); } return; } // Try and see if the player is online Player player = plugin.getServer().getPlayer(ownerUUID); if (player != null) { // Online if (!player.hasPermission(Settings.PERMPREFIX + "intopten")) { topTenList.remove(ownerUUID); return; } } topTenList.put(ownerUUID, level); topTenList = MapUtil.sortByValue(topTenList); } /** * Removes ownerUUID from the top ten list * * @param ownerUUID */ public static void topTenRemoveEntry(UUID ownerUUID) { topTenList.remove(ownerUUID); } /** * Generates a sorted map of islands for the Top Ten list from all player * files */ public static void topTenCreate() { topTenCreate(null); } /** * Creates the top ten list from scratch. Does not get the level of each island. Just * takes the level from the player's file. * Runs asynchronously from the main thread. * @param sender */ public static void topTenCreate(final CommandSender sender) { plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { @Override public void run() { // This map is a list of owner and island level YamlConfiguration player = new YamlConfiguration(); int index = 0; for (final File f : plugin.getPlayersFolder().listFiles()) { // Need to remove the .yml suffix String fileName = f.getName(); if (fileName.endsWith(".yml")) { try { String playerUUIDString = fileName.substring(0, fileName.length() - 4); final UUID playerUUID = UUID.fromString(playerUUIDString); if (playerUUID == null) { plugin.getLogger().warning("Player file contains erroneous UUID data."); plugin.getLogger().info("Looking at " + playerUUIDString); } player.load(f); index++; if (index % 1000 == 0) { plugin.getLogger().info("Processed " + index + " players for top ten"); } // Players player = new Players(this, playerUUID); int islandLevel = player.getInt("islandLevel", 0); String teamLeaderUUID = player.getString("teamLeader", ""); if (islandLevel > 0) { if (!player.getBoolean("hasTeam")) { // Single player topTenAddEntry(playerUUID, islandLevel); } else if (!teamLeaderUUID.isEmpty() && teamLeaderUUID.equals(playerUUIDString)) { // Only enter team leaders into the top ten topTenAddEntry(playerUUID, islandLevel); } } } catch (Exception e) { plugin.getLogger().severe("Error when reading player file. File is " + fileName); plugin.getLogger().severe("Look at the stack trace and edit the file - it probably has broken YAML in it for some reason."); e.printStackTrace(); } } } plugin.getLogger().info("Processed " + index + " players for top ten"); // Save the top ten topTenSave(); plugin.getServer().getScheduler().runTask(plugin, new Runnable() { @Override public void run() { if (sender != null) { Util.sendMessage(sender, ChatColor.YELLOW + plugin.myLocale().adminTopTenfinished); } else { plugin.getLogger().warning("Completed top ten creation."); } }}); }}); } public static void topTenSave() { if (topTenList == null) { return; } plugin.getLogger().info("Saving top ten list"); // Make file File topTenFile = new File(plugin.getDataFolder(), "topten.yml"); // Make configuration YamlConfiguration config = new YamlConfiguration(); // Save config int rank = 0; for (Map.Entry<UUID, Integer> m : topTenList.entrySet()) { if (rank++ == 10) { break; } config.set("topten." + m.getKey().toString(), m.getValue()); } try { config.save(topTenFile); plugin.getLogger().info("Saved top ten list"); } catch (Exception e) { plugin.getLogger().severe("Could not save top ten list!"); e.printStackTrace(); } } /** * Loads the top ten from the file system topten.yml. If it does not exist * then the top ten is created */ public static void topTenLoad() { topTenList.clear(); // Check to see if the top ten list exists File topTenFile = new File(plugin.getDataFolder(), "topten.yml"); if (!topTenFile.exists()) { plugin.getLogger().warning("Top ten file does not exist - creating it. This could take some time with a large number of players"); topTenCreate(); } else { // Load the top ten YamlConfiguration topTenConfig = Util.loadYamlFile("topten.yml"); // Load the values if (topTenConfig.isSet("topten")) { for (String playerUUID : topTenConfig.getConfigurationSection("topten").getKeys(false)) { // getLogger().info(playerUUID); try { UUID uuid = UUID.fromString(playerUUID); // getLogger().info(uuid.toString()); int level = topTenConfig.getInt("topten." + playerUUID); // getLogger().info("Level = " + level); TopTen.topTenAddEntry(uuid, level); } catch (Exception e) { e.printStackTrace(); plugin.getLogger().severe("Problem loading top ten list - recreating - this may take some time"); topTenCreate(); } } } } } /** * Displays the Top Ten list if it exists in chat * * @param player * - the requesting player * @return - true if successful, false if no Top Ten list exists */ public static boolean topTenShow(final Player player) { // Old chat display if(Settings.displayIslandTopTenInChat){ Util.sendMessage(player, ChatColor.GOLD + plugin.myLocale(player.getUniqueId()).topTenheader); if (topTenList == null) { topTenCreate(); // Util.sendMessage(player, ChatColor.RED + plugin.myLocale(player.getUniqueId()).topTenerrorNotReady); // return true; } topTenList = MapUtil.sortByValue(topTenList); int i = 1; // getLogger().info("DEBUG: " + topTenList.toString()); // getLogger().info("DEBUG: " + topTenList.values()); Iterator<Entry<UUID, Integer>> it = topTenList.entrySet().iterator(); while (it.hasNext()) { Map.Entry<UUID, Integer> m = it.next(); UUID playerUUID = m.getKey(); // Remove from TopTen if the player is online and has the permission Player entry = plugin.getServer().getPlayer(playerUUID); boolean show = true; if (entry != null) { if (!entry.hasPermission(Settings.PERMPREFIX + "intopten")) { it.remove(); show = false; } } if (show) { if (plugin.getPlayers().inTeam(playerUUID)) { // Island name + Island members + Island level final List<UUID> pMembers = plugin.getPlayers().getMembers(playerUUID); String memberList = ""; for (UUID members : pMembers) { memberList += plugin.getPlayers().getName(members) + ", "; } if (memberList.length() > 2) { memberList = memberList.substring(0, memberList.length() - 2); } Util.sendMessage(player, ChatColor.AQUA + "#" + i + ": " + plugin.getGrid().getIslandName(playerUUID) + ChatColor.AQUA + " (" + memberList + ") - " + plugin.myLocale(player.getUniqueId()).levelislandLevel + " " + m.getValue()); } else { // Island name + Island level Util.sendMessage(player, ChatColor.AQUA + "#" + i + ": " + plugin.getGrid().getIslandName(playerUUID) + ChatColor.AQUA + " - " + plugin.myLocale(player.getUniqueId()).levelislandLevel + " " + m.getValue()); } if (i++ == 10) { break; } } } } else { // New GUI display (shown by default) if (topTenList == null) topTenCreate(); topTenList = MapUtil.sortByValue(topTenList); // Create the top ten GUI if it does not exist if (gui == null) { gui = Bukkit.createInventory(null, GUISIZE, plugin.myLocale(player.getUniqueId()).topTenGuiTitle); } // Reset gui.clear(); int i = 1; Iterator<Entry<UUID, Integer>> it = topTenList.entrySet().iterator(); while (it.hasNext()) { Map.Entry<UUID, Integer> m = it.next(); UUID playerUUID = m.getKey(); //plugin.getLogger().info("DEBUG: " + i + ": " + playerUUID); // Remove from TopTen if the player is online and has the permission Player entry = plugin.getServer().getPlayer(playerUUID); boolean show = true; if (entry != null) { if (!entry.hasPermission(Settings.PERMPREFIX + "intopten")) { it.remove(); show = false; } } if (show) { gui.setItem(SLOTS[i-1], getSkull(i, m.getValue(), playerUUID)); if (i++ == 10) break; } } player.openInventory(gui); } return true; } static ItemStack getSkull(int rank, int levels, UUID player){ String playerName = plugin.getServer().getOfflinePlayer(player).getName(); ItemStack playerSkull = new ItemStack(Material.SKULL_ITEM, 1, (short) 3); if (playerName == null) return null; SkullMeta meta = (SkullMeta) playerSkull.getItemMeta(); meta.setOwner(playerName); meta.setDisplayName(ChatColor.YELLOW + "" + ChatColor.BOLD + "<!> " + ChatColor.YELLOW + "Island: " + ChatColor.GOLD + ChatColor.UNDERLINE + plugin.getGrid().getIslandName(player) + ChatColor.GRAY + " (#" + rank + ")"); List<String> lore = new ArrayList<String>(); lore.add(ChatColor.GOLD + "" + ChatColor.BOLD + "* " + ChatColor.YELLOW + plugin.myLocale(player).levelislandLevel + " " + levels); if (plugin.getPlayers().inTeam(player)) { final List<UUID> pMembers = plugin.getPlayers().getMembers(player); // Need to make this a vertical list, because some teams are very large and it'll go off the screen otherwise List<String> memberList = new ArrayList<>(); for (UUID members : pMembers) { memberList.add(ChatColor.AQUA + plugin.getPlayers().getName(members)); } lore.addAll(memberList); } //else lore.add(ChatColor.AQUA + playerName); meta.setLore(lore); playerSkull.setItemMeta(meta); return playerSkull; } static void remove(UUID owner) { topTenList.remove(owner); } @SuppressWarnings("deprecation") @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled=true) public void onInventoryClick(InventoryClickEvent event) { Inventory inventory = event.getInventory(); // The inventory that was clicked in if (inventory.getName() == null) { return; } if (!inventory.getTitle().equals(plugin.myLocale().topTenGuiTitle)) { return; } // The player that clicked the item Player player = (Player) event.getWhoClicked(); event.setCancelled(true); player.updateInventory(); if(event.getCurrentItem() != null && event.getCurrentItem().getType().equals(Material.SKULL_ITEM) && event.getCurrentItem().hasItemMeta()){ player.performCommand("is warp " + ((SkullMeta)event.getCurrentItem().getItemMeta()).getOwner()); player.closeInventory(); return; } if (event.getSlotType().equals(SlotType.OUTSIDE)) { player.closeInventory(); return; } if (event.getClick().equals(ClickType.SHIFT_RIGHT)) { player.closeInventory(); return; } } /** * Get a sorted descending map of the top players * @return the topTenList - may be more or less than ten */ public static Map<UUID, Integer> getTopTenList() { return topTenList; } }