package com.alttd.halloween.leaderboard; import com.comphenix.protocol.ProtocolManager; import com.comphenix.protocol.events.PacketContainer; import lombok.extern.slf4j.Slf4j; import org.bukkit.Location; import org.bukkit.entity.Player; import java.util.*; import java.util.function.Function; @Slf4j public class Leaderboard { private final LeaderboardLineEntity title; private final List lines; private final HashMap metaPacket = new HashMap<>(); private final HashMap viewers = new HashMap<>(); private final ProtocolManager protocolManager; private final int leaderboardSize; public Leaderboard(Location location, int leaderboardSize, ProtocolManager protocolManager, String title) { this.leaderboardSize = leaderboardSize; this.protocolManager = protocolManager; if (leaderboardSize < 1) { throw new IllegalArgumentException("Leaderboard must have at least one line"); } HoverText hoverText = new HoverText(protocolManager); this.title = createTitle(hoverText, location, title, leaderboardSize + 1); this.lines = createLines(new HoverText(protocolManager), location); } private LeaderboardLineEntity createTitle(HoverText hoverText, Location location, String title, int titleLocation) { Location clone = location.clone(); clone.setY(clone.getY() + titleLocation); Optional leaderboardLineEntity = hoverText.createLeaderboardLineEntity(clone); if (leaderboardLineEntity.isEmpty()) { log.error("Failed to create title"); throw new ExceptionInInitializerError("Failed to create title"); } Optional packetContainer = hoverText.setLine(leaderboardLineEntity.get(), title); if (packetContainer.isEmpty()) { log.error("Failed to create title text"); throw new ExceptionInInitializerError("Failed to create title text"); } metaPacket.put(leaderboardLineEntity.get().entityId(), packetContainer.get()); return leaderboardLineEntity.get(); } private List createLines(HoverText hoverText, Location location) throws ExceptionInInitializerError { List lines = new ArrayList<>(); for (int i = 0; i < leaderboardSize; i++) { Location clone = location.clone(); clone.setY(clone.getY() + leaderboardSize - i); Optional optionalLeaderboardLineEntity = hoverText.createLeaderboardLineEntity(clone); if (optionalLeaderboardLineEntity.isEmpty()) { log.error("Failed to create leaderboard"); throw new ExceptionInInitializerError("Failed to create leaderboard"); } LeaderboardLineEntity leaderboardLineEntity = optionalLeaderboardLineEntity.get(); Optional packetContainer = hoverText.setLine(leaderboardLineEntity, ""); if (packetContainer.isEmpty()) { log.error("Failed to create line text"); throw new ExceptionInInitializerError("Failed to create line text"); } metaPacket.put(leaderboardLineEntity.entityId(), packetContainer.get()); lines.add(leaderboardLineEntity); } return lines; } public void updateScoreboard(Function func) {//TODO remove offline players and check if the player is still nearby? HoverText hoverText = new HoverText(protocolManager); //TODO make it so this doesnt have to be recreated? Could be static maybe for (int i = 0; i < lines.size(); i++) { LeaderboardLineEntity leaderboardLineEntity = lines.get(i); Optional packetContainer = hoverText.setLine(leaderboardLineEntity, func.apply(i)); if (packetContainer.isEmpty()) { log.error("Failed to update line text"); throw new ExceptionInInitializerError("Failed to update line text"); } metaPacket.put(leaderboardLineEntity.entityId(), packetContainer.get()); } viewers.values().forEach(this::updateScoreboard); } private void updateScoreboard(Player player) { // metaPacket.values().forEach(metaPacket -> protocolManager.sendServerPacket(player, metaPacket)); } public void addViewer(Player player) { if (viewers.containsKey(player.getUniqueId())) { return; //Player was already in viewers list } protocolManager.sendServerPacket(player, title.entitySpawnPacket()); lines.forEach(line -> protocolManager.sendServerPacket(player, line.entitySpawnPacket())); // updateScoreboard(player); viewers.put(player.getUniqueId(), player); } public void removeViewer(Player player) { Player removed = viewers.remove(player.getUniqueId()); if (removed == null || !removed.isOnline()) { return; } protocolManager.sendServerPacket(player, title.entityDestroyPacket()); lines.forEach(line -> protocolManager.sendServerPacket(player, line.entityDestroyPacket())); } }