package in.twizmwaz.cardinal.module.modules.stats; import in.twizmwaz.cardinal.Cardinal; import in.twizmwaz.cardinal.chat.ChatConstant; import in.twizmwaz.cardinal.chat.ChatMessage; import in.twizmwaz.cardinal.chat.LocalizedChatMessage; import in.twizmwaz.cardinal.chat.UnlocalizedChatMessage; import in.twizmwaz.cardinal.event.CardinalDeathEvent; import in.twizmwaz.cardinal.event.PlayerChangeTeamEvent; import in.twizmwaz.cardinal.event.PlayerSettingChangeEvent; import in.twizmwaz.cardinal.module.Module; import in.twizmwaz.cardinal.settings.Settings; import in.twizmwaz.cardinal.util.PacketUtils; import in.twizmwaz.cardinal.util.bossBar.LocalizedBossBar; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.TextComponent; import net.minecraft.server.Packet; import net.minecraft.server.PacketPlayOutScoreboardScore; import net.minecraft.server.PacketPlayOutScoreboardTeam; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.boss.BarColor; import org.bukkit.boss.BarStyle; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; public class Stats implements Module { private static DecimalFormat format = new DecimalFormat("0.00"); private Map<UUID, Integer> kills = new HashMap<>(); private Map<UUID, Integer> deaths = new HashMap<>(); private List<UUID> sidebarView = new ArrayList<>(); private Map<UUID, LocalizedBossBar> bossBars = new HashMap<>(); private Map<UUID, Integer> actionBarTasks = new HashMap<>(); private static String scoreboardEntry = ChatColor.WHITE + " D:" + ChatColor.RED; private static PacketPlayOutScoreboardScore getScoreboardPacket(String entry, int score, PacketPlayOutScoreboardScore.EnumScoreboardAction action) { PacketPlayOutScoreboardScore packet = new PacketPlayOutScoreboardScore(); PacketUtils.setField("a", packet, entry); PacketUtils.setField("b", packet, "scoreboard"); PacketUtils.setField("c", packet, score); PacketUtils.setField("d", packet, action); return packet; } @Override public void unload() { kills.clear(); deaths.clear(); for (Player player : Bukkit.getOnlinePlayers()) { clearDisplay(player, Settings.getSettingByName("Stats").getValueByPlayer(player).getValue()); } HandlerList.unregisterAll(this); } public int getKills(UUID player) { if (!kills.containsKey(player)) kills.put(player, 0); return kills.get(player); } public void addKill(Player player) { kills.put(player.getUniqueId(), getKills(player.getUniqueId()) + 1); updateDisplay(player); } public int getDeaths(UUID player) { if (!deaths.containsKey(player)) deaths.put(player, 0); return deaths.get(player); } public void addDeath(Player player) { deaths.put(player.getUniqueId(), getDeaths(player.getUniqueId()) + 1); updateDisplay(player); } private boolean shouldShow(Player player) { return getKills(player.getUniqueId()) != 0 || getDeaths(player.getUniqueId()) != 0; } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerDeath(CardinalDeathEvent event) { if (event.getKiller() != null) addKill(event.getKiller()); addDeath(event.getPlayer()); } @EventHandler(priority = EventPriority.MONITOR) public void onTeamChange(PlayerChangeTeamEvent event) { updateDisplay(event.getPlayer()); } @EventHandler(priority = EventPriority.MONITOR) public void onPlayerJoin(PlayerJoinEvent event) { updateDisplay(event.getPlayer()); } @EventHandler(priority = EventPriority.MONITOR) public void onPlayerLeave(PlayerQuitEvent event) { clearDisplay(event.getPlayer(), Settings.getSettingByName("Stats").getValueByPlayer(event.getPlayer()).getValue()); } @EventHandler public void onPlayerChangeSetting(PlayerSettingChangeEvent event) { if (!event.getSetting().equals(Settings.getSettingByName("Stats"))) return; clearDisplay(event.getPlayer(), event.getOldValue().getValue()); updateDisplay(event.getPlayer()); } private void sendSlotPackets(Player player, boolean set) { PacketPlayOutScoreboardScore.EnumScoreboardAction action = set ? PacketPlayOutScoreboardScore.EnumScoreboardAction.CHANGE : PacketPlayOutScoreboardScore.EnumScoreboardAction.REMOVE; Packet blankSlot = getScoreboardPacket("", -1, action); Packet scoreSlot = getScoreboardPacket(ChatColor.WHITE + " D:" + ChatColor.RED, -2, action); PacketUtils.sendPacket(player, blankSlot); PacketUtils.sendPacket(player, scoreSlot); } private void sendTeamPackets(Player player, boolean set) { String prefix = "K:" + ChatColor.GREEN + "0"; String suffix = "0" + ChatColor.WHITE + " K/D:" + ChatColor.AQUA + "0.00"; PacketUtils.sendPacket(player, new PacketPlayOutScoreboardTeam(set ? 0 : 1, "scoreboard-stats", "scoreboard-stats", prefix, suffix, -1, "never", "never", 0, Collections.singletonList(scoreboardEntry))); } private void sendActionBarPacket(Player player, int kills, int deaths, String kd) { player.sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(getLocalizedMessage(kills, deaths, kd).getMessage(player.getLocale()))); } public void updateDisplay(final Player player) { if (!shouldShow(player)) return; final int kills = getKills(player.getUniqueId()); final int deaths = getDeaths(player.getUniqueId()); final String kd = format.format((double)kills / Math.max(deaths, 1)).replace(",", "."); switch (Settings.getSettingByName("Stats").getValueByPlayer(player).getValue()) { case "sidebar": if (!sidebarView.contains(player.getUniqueId())) { sidebarView.add(player.getUniqueId()); sendTeamPackets(player, true); } sendSlotPackets(player, true); String prefix = "K:" + ChatColor.GREEN + Math.min(kills, 999); String suffix = "" + Math.min(deaths, 999) + ChatColor.WHITE + " K/D:" + ChatColor.AQUA + kd; PacketUtils.sendPacket(player, new PacketPlayOutScoreboardTeam(2, "scoreboard-stats", "scoreboard-stats", prefix, suffix, -1, "never", "never", 0, Collections.singletonList(scoreboardEntry))); break; case "boss bar": if (!bossBars.containsKey(player.getUniqueId())) { LocalizedBossBar bossBar = new LocalizedBossBar(new UnlocalizedChatMessage(""), BarColor.PURPLE, BarStyle.SOLID); bossBar.addPlayer(player); bossBars.put(player.getUniqueId(), bossBar); } bossBars.get(player.getUniqueId()).setTitle(getLocalizedMessage(kills, deaths, kd)); break; case "action bar": if (actionBarTasks.containsKey(player.getUniqueId())) { Bukkit.getScheduler().cancelTask(actionBarTasks.get(player.getUniqueId())); } actionBarTasks.put(player.getUniqueId(), Bukkit.getScheduler().scheduleSyncRepeatingTask(Cardinal.getInstance(), new Runnable() { private int tick; @Override public void run() { if (tick > 40) { if (actionBarTasks.containsKey(player.getUniqueId())) { Bukkit.getScheduler().cancelTask(actionBarTasks.get(player.getUniqueId())); actionBarTasks.remove(player.getUniqueId()); } } else { sendActionBarPacket(player, kills, deaths, kd); tick++; } } }, 1L, 1L)); break; } } public void clearDisplay(Player player, String setting) { switch (setting) { case "sidebar": if (sidebarView.contains(player.getUniqueId())) { sendTeamPackets(player, false); sendSlotPackets(player, false); sidebarView.remove(player.getUniqueId()); } case "boss bar": if (bossBars.containsKey(player.getUniqueId())) { bossBars.get(player.getUniqueId()).removePlayer(player); bossBars.remove(player.getUniqueId()); } case "action bar": if (actionBarTasks.containsKey(player.getUniqueId())) { Bukkit.getScheduler().cancelTask(actionBarTasks.get(player.getUniqueId())); actionBarTasks.remove(player.getUniqueId()); } } } private ChatMessage getLocalizedMessage(int kills, int deaths, String kd) { return new LocalizedChatMessage(ChatConstant.UI_STATS_DISPLAY, ChatColor.GREEN + "" + kills + ChatColor.WHITE, ChatColor.RED + "" + deaths + ChatColor.WHITE, ChatColor.AQUA + kd + ChatColor.WHITE); } }