2024-10-20 17:05:26 +00:00
|
|
|
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<LeaderboardLineEntity> lines;
|
|
|
|
|
private final HashMap<Integer, PacketContainer> metaPacket = new HashMap<>();
|
|
|
|
|
private final HashMap<UUID, Player> 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> leaderboardLineEntity = hoverText.createLeaderboardLineEntity(clone);
|
|
|
|
|
if (leaderboardLineEntity.isEmpty()) {
|
|
|
|
|
log.error("Failed to create title");
|
|
|
|
|
throw new ExceptionInInitializerError("Failed to create title");
|
|
|
|
|
}
|
|
|
|
|
Optional<PacketContainer> 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<LeaderboardLineEntity> createLines(HoverText hoverText, Location location) throws ExceptionInInitializerError {
|
|
|
|
|
List<LeaderboardLineEntity> lines = new ArrayList<>();
|
|
|
|
|
for (int i = 0; i < leaderboardSize; i++) {
|
|
|
|
|
Location clone = location.clone();
|
|
|
|
|
clone.setY(clone.getY() + leaderboardSize - i);
|
|
|
|
|
Optional<LeaderboardLineEntity> 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> 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<Integer, String> 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> 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) {
|
2024-10-20 17:42:31 +00:00
|
|
|
if (viewers.containsKey(player.getUniqueId())) {
|
2024-10-20 17:05:26 +00:00
|
|
|
return; //Player was already in viewers list
|
|
|
|
|
}
|
|
|
|
|
protocolManager.sendServerPacket(player, title.entitySpawnPacket());
|
|
|
|
|
lines.forEach(line -> protocolManager.sendServerPacket(player, line.entitySpawnPacket()));
|
2024-10-20 17:42:31 +00:00
|
|
|
updateScoreboard(player);
|
|
|
|
|
viewers.put(player.getUniqueId(), player);
|
2024-10-20 17:05:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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()));
|
|
|
|
|
}
|
|
|
|
|
}
|