Halloween2024/src/main/java/com/alttd/halloween/leaderboard/Leaderboard.java

109 lines
5.2 KiB
Java
Raw Normal View History

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) {
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()));
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()));
}
}