package com.lifeknight.relaymchub.statistics; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.lifeknight.relaymchub.Main; import com.lifeknight.relaymchub.player.HubPlayer; import com.lifeknight.relaymcutils.RelayMCUtils; import com.lifeknight.relaymcutils.player.SmartPlayer; import com.lifeknight.relaymcutils.utilities.Parkour; import com.lifeknight.relayutils.RelayUtils; import com.lifeknight.relayutils.basic.Miscellaneous; import com.lifeknight.relayutils.basic.Text; import com.lifeknight.relayutils.game.GameAction; import com.lifeknight.relayutils.game.MainGame; import com.lifeknight.relayutils.game.SpecificGameAction; import com.lifeknight.relayutils.player.Group; import com.lifeknight.relayutils.player.data.ProfileColumn; import com.lifeknight.relayutils.utilities.ComponentBuilder; import com.lifeknight.relayutils.utilities.Jsonable; import com.lifeknight.relayutils.utilities.variables.SmartNumber; import com.lifeknight.relayutils.utilities.variables.SmartString; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.util.BoundingBox; import java.sql.ResultSet; import java.util.*; import static org.bukkit.ChatColor.*; public class StatisticsLeaderboard extends Jsonable { public static final List<StatisticsLeaderboard> LEADERBOARDS = new ArrayList<>(); public static int NEXT_ID = 0; public static final Map<HubPlayer, Integer> HUB_PLAYER_TO_SELECTED = new HashMap<>(); public final int id; public final SmartNumber.SmartDouble x; public final SmartNumber.SmartDouble y; public final SmartNumber.SmartDouble z; public final SmartString statisticName; public ArmorStand titleArmorStand; public List<ArmorStand> allTimeArmorStands = new ArrayList<>(); public List<ArmorStand> weeklyArmorStands = new ArrayList<>(); public List<ArmorStand> dailyArmorStands = new ArrayList<>(); public Map<UUID, Number> allTimeLeaderboard = new HashMap<>(); public Map<UUID, Number> weeklyLeaderboard = new HashMap<>(); public Map<UUID, Number> dailyLeaderboard = new HashMap<>(); public Map<UUID, ArmorStand> allTimePersonal = new HashMap<>(); public Map<UUID, ArmorStand> weeklyPersonal = new HashMap<>(); public Map<UUID, ArmorStand> dailyPersonal = new HashMap<>(); public final Map<UUID, Integer> playerToLeaderboardType = new HashMap<>(); public StatisticsLeaderboard(Location location, String statistic) { this(location.getX(), location.getY(), location.getZ(), statistic); } public StatisticsLeaderboard(double x, double y, double z, String statistic) { this.x = (SmartNumber.SmartDouble) super.createNumber("X", "Location", x); this.y = (SmartNumber.SmartDouble) super.createNumber("Y", "Location", y); this.z = (SmartNumber.SmartDouble) super.createNumber("Z", "Location", z); this.statisticName = super.createString("Statistic", "Data", statistic); this.createArmorStands(); LEADERBOARDS.add(this); this.id = NEXT_ID++; } public static StatisticsLeaderboard getFromStand(ArmorStand armorStand) { for (StatisticsLeaderboard leaderboard : LEADERBOARDS) { if (leaderboard.getAllArmorStands().contains(armorStand)) { return leaderboard; } } return null; } @Override public void fromJson(JsonObject jsonObject) { super.fromJson(jsonObject); this.removeArmorStands(); this.createArmorStands(); } public double getX() { return this.x.getValue(); } public double getY() { return this.y.getValue(); } public double getZ() { return this.z.getValue(); } public ArmorStand spawnArmorStand(Location location) { ArmorStand armorStand = (ArmorStand) this.getWorld().spawnEntity(location, EntityType.ARMOR_STAND); RelayUtils.log("Spawned armor stand %d (%s)", armorStand.getEntityId(), this.getStatisticName()); armorStand.setInvisible(true); armorStand.setGravity(false); return armorStand; } public ArmorStand spawnArmorStand() { return this.spawnArmorStand(this.getLocation()); } public String getTitle() { SpecificGameAction specificGameAction = SpecificGameAction.getSpecificGameAction(this.getStatisticName()); if (specificGameAction != null) { return specificGameAction.getGameType().getDisplaySuffix() + " " + specificGameAction.getGameAction().getPluralPrettyName(); } for (MainGame value : MainGame.values()) { String pretty = Text.prettify(this.getStatisticName()); if (pretty.contains(value.getName())) { return pretty.substring(value.getName().length() + 1); } } return Text.prettify(this.getStatisticName()); } public void createArmorStands() { this.titleArmorStand = this.spawnArmorStand(this.getLocation().add(0, -1.5F + 0.3F * 12, 0)); this.prepareArmorStand(this.titleArmorStand); GameAction gameAction = this.getGameAction(); if (gameAction != null) { this.titleArmorStand.setCustomName(GOLD + gameAction.getPluralPrettyName()); } else if (this.getSpecificGameAction() != null) { this.titleArmorStand.setCustomName(GOLD + this.getSpecificGameAction().getGameType().getDisplaySuffix() + " " + this.getSpecificGameAction().getGameAction().getPluralPrettyName()); } else if (this.isParkour()) { Parkour parkour = Parkour.getParkour(this.getStatisticName().split("_")[1]); if (parkour != null) { this.titleArmorStand.setCustomName(GOLD + "Parkour - " + parkour.getCompositeFormattedName()); } } else { this.titleArmorStand.setCustomName(GOLD + this.getTitle()); } this.allTimeArmorStands = this.getNewArmorStands(); this.setupTypes(this.allTimeArmorStands, 0); if (this.hasTimelyPositions()) { this.weeklyArmorStands = this.getNewArmorStands(); this.setupTypes(this.weeklyArmorStands, 1); this.dailyArmorStands = this.getNewArmorStands(); this.setupTypes(this.dailyArmorStands, 2); } } public void setupTypes(List<ArmorStand> armorStands, int type) { String title = AQUA + BOLD.toString(); switch (type) { case 0 -> title += "All Time"; case 1 -> title += "Weekly"; case 2 -> title += "Daily"; } armorStands.get(10).setCustomName(title); String editor = switch (type) { case 0 -> AQUA.toString() + BOLD + "All Time" + GRAY + " Weekly Daily"; case 1 -> GRAY + "All Time " + AQUA + BOLD + "Weekly " + GRAY + "Daily"; default -> GRAY + "All Time Weekly " + AQUA + BOLD + "Daily"; }; armorStands.get(11).setCustomName(editor); if (!this.hasTimelyPositions()) { armorStands.get(11).setCustomNameVisible(false); } } public List<ArmorStand> getNewArmorStands() { RelayUtils.log("Getting new armor stands"); double x = this.getX(); double y = this.getY(); double z = this.getZ(); World world = this.getWorld(); List<ArmorStand> armorStands = new ArrayList<>(); for (int i = 10; i > 0; i--) { ArmorStand armorStand = this.spawnArmorStand(); this.prepareArmorStand(armorStand); Location location = new Location(world, x, y - 1.5F + 0.3F * i, z); armorStand.teleport(location); armorStands.add(armorStand); this.clearArmorStand(armorStand); } ArmorStand typeName = this.spawnArmorStand(this.getLocation().add(0, -1.5F + 0.3F * 11, 0)); this.prepareArmorStand(typeName); armorStands.add(typeName); ArmorStand typeEditor = this.spawnArmorStand(this.getLocation().add(0, -2F, 0)); this.prepareArmorStand(typeEditor); armorStands.add(typeEditor); return armorStands; } public void prepareArmorStand(ArmorStand armorStand) { armorStand.setGravity(false); armorStand.setInvisible(false); armorStand.setInvisible(true); } public Location getLocation() { return new Location(this.getWorld(), this.getX(), this.getY(), this.getZ()); } public void removeArmorStands() { for (ArmorStand allArmorStand : this.getAllArmorStands()) { allArmorStand.remove(); } this.allTimeArmorStands.clear(); this.weeklyArmorStands.clear(); this.dailyArmorStands.clear(); this.titleArmorStand.remove(); } public void delete() { this.removeArmorStands(); LEADERBOARDS.remove(this); } public void info(HubPlayer hubPlayer) { hubPlayer.sendInfoMessage("%s -> %d | %d | %d", this.getStatisticName(), (int) this.getX(), (int) this.getY(), (int) this.getZ()); } public void setPosition(Location location) { this.x.setValue(location.getX()); this.y.setValue(location.getY()); this.z.setValue(location.getZ()); } public void updateData() { GameAction gameAction = this.getGameAction(); String statisticName = this.getStatisticName(); if (this.getSpecificGameAction() != null) { gameAction = this.getSpecificGameAction().getGameAction(); } /* if ((this.getSpecificGameAction() == null || this.getSpecificGameAction().getGameType() == null) && Main.isGameLobby() && gameAction != null) { statisticName = gameAction.getLeaderboardName(Main.mainGame); } if (Main.isGameLobby() && RelayUtils.EXTRA_COLUMNS.contains(statisticName)) { statisticName = Main.getMainGame().specifyName(statisticName); } */ if ("tokens".equalsIgnoreCase(statisticName)) { statisticName = "credits"; } List<ResultSet> resultSets = Main.getLeaderboards(statisticName); if (statisticName.contains("parkour")) { statisticName = "time"; } else if (statisticName.contains("arena")) { statisticName = statisticName.split("_")[1]; } else if (statisticName.equalsIgnoreCase("time_played")) { statisticName = "timePlayed"; } for (int i = 0; i < resultSets.size(); i++) { Map<UUID, Number> map = new LinkedHashMap<>(); ResultSet resultSet = resultSets.get(i); try { while (resultSet.next()) { try { UUID uuid = UUID.fromString(resultSet.getString(ProfileColumn.ID.toString())); Number value; if (gameAction != null && gameAction.isCalculated()) { value = resultSet.getDouble(statisticName); } else { value = resultSet.getLong(statisticName); } map.put(uuid, value); } catch (Exception exception) { Main.error("An error occurred while processing result set in leaderboard (%s): %s", statisticName, exception.getMessage()); } } } catch (Exception exception) { Main.error("An error occurred on reading next result set in leaderboard (%s): %s", statisticName, exception.getMessage()); } this.setMap(map, i); /*Main.info("%s (%d)", gameAction.getCodeName(), i); Main.info("Keys: %s", map.keySet()); Main.info("Values: %s", map.values());*/ } /*this.allTimeLeaderboard = LeaderboardProfile.getMap(gameActoin, 0); this.weeklyLeaderboard = LeaderboardProfile.getMap(gameActoin, 1); this.dailyLeaderboard = LeaderboardProfile.getMap(gameActoin, 2);*/ Main.synchronous(() -> { this.updateSpecificLeaderboard(this.allTimeArmorStands, this.allTimeLeaderboard); if (this.hasTimelyPositions()) { this.updateSpecificLeaderboard(this.weeklyArmorStands, this.weeklyLeaderboard); this.updateSpecificLeaderboard(this.dailyArmorStands, this.dailyLeaderboard); } for (HubPlayer onlineHubPlayer : HubPlayer.getOnlineHubPlayers()) { this.updatePersonalArmorStands(onlineHubPlayer); } List<UUID> toRemove = new ArrayList<>(); for (Map<UUID, ArmorStand> allPersonalMap : this.getAllPersonalMaps()) { for (Map.Entry<UUID, ArmorStand> uuidArmorStandEntry : allPersonalMap.entrySet()) { HubPlayer hubPlayer = HubPlayer.getHubPlayer(uuidArmorStandEntry.getKey()); if (hubPlayer == null || !hubPlayer.isOnline()) { uuidArmorStandEntry.getValue().remove(); toRemove.add(uuidArmorStandEntry.getKey()); } } } for (UUID uuid : toRemove) { for (Map<UUID, ArmorStand> allPersonalMap : this.getAllPersonalMaps()) { allPersonalMap.remove(uuid); } } }); } public boolean isParkour() { return this.getStatisticName().contains("parkour"); } public boolean isArena() { return this.getStatisticName().contains("arena"); } public void setMap(Map<UUID, Number> map, int type) { switch (type) { case 0 -> this.allTimeLeaderboard = map; case 1 -> this.weeklyLeaderboard = map; } this.dailyLeaderboard = map; } private static <K, V> Map<K, V> sortByValue(Map<K, V> unsortMap) { List<Map.Entry<K, V>> list = new LinkedList<>(unsortMap.entrySet()); Collections.sort(list, new Comparator<Object>() { @SuppressWarnings("unchecked") public int compare(Object o1, Object o2) { boolean o1Null = o1 == null || ((Map.Entry<K, V>) o1).getValue() == null; boolean o2Null = o2 == null || ((Map.Entry<K, V>) o2).getValue() == null; if (o1Null && o2Null) return 0; if (o1Null) return -1; if (o2Null) return 1; V a = ((Map.Entry<K, V>) o1).getValue(); V b = ((Map.Entry<K, V>) o2).getValue(); return ((Comparable<V>) b).compareTo(a); } }); Map<K, V> result = new LinkedHashMap<>(); for (Map.Entry<K, V> entry : list) { result.put(entry.getKey(), entry.getValue()); } return result; } List<Map<UUID, ArmorStand>> getAllPersonalMaps() { List<Map<UUID, ArmorStand>> allPersonalMaps = new ArrayList<>(); allPersonalMaps.add(this.allTimePersonal); allPersonalMaps.add(this.weeklyPersonal); allPersonalMaps.add(this.dailyPersonal); return allPersonalMaps; } /*public void processResultSet(Map<UUID, Long> leaderboard, ResultSet resultSet) { leaderboard.clear(); try { while (resultSet.next()) { UUID uuid = UUID.fromString(resultSet.getString(ProfileColumn.ID.getName())); long value = resultSet.getLong(tgi); leaderboard.put(uuid, value); } } catch (Exception exception) { Main.error("An error occurred while attempting to process result set: (%s) %s", this.getGameAction().codeName, exception.getMessage()); } }*/ public void clearArmorStands(List<ArmorStand> armorStands) { for (int i = 0; i < 10; i++) { this.clearArmorStand(armorStands.get(i)); } } public void clearArmorStand(ArmorStand armorStand) { armorStand.setCustomName(ChatColor.GRAY + ChatColor.BOLD.toString() + "..."); } public void updateSpecificLeaderboard(List<ArmorStand> armorStands, Map<UUID, Number> leaderboard) { try { //this.clearArmorStands(armorStands); List<UUID> asList = Miscellaneous.getList(leaderboard.keySet()); int index = 0; while (index < 10) { ArmorStand armorStand = armorStands.get(index); if (index > leaderboard.size() - 1) { this.clearArmorStand(armorStand); } else { UUID uuid = asList.get(index); Number value = leaderboard.get(uuid); SmartPlayer smartPlayer = SmartPlayer.getOrCreate(uuid); int finalIndex = index; Main.scheduleSyncDelayedTask(() -> { int number = finalIndex + 1; ComponentBuilder componentBuilder = new ComponentBuilder("%s%s. ", ChatColor.GRAY, number); componentBuilder.append(smartPlayer.getComponentRealFormattedName()).color(GRAY).append(" - "); componentBuilder.appendComponent(this.getDisplayValue(value, armorStands == this.allTimeArmorStands, false).getResult()); ((CraftEntity) armorStand).getHandle().b(RelayMCUtils.fromBaseComponent(componentBuilder.getResult())); }, 0.5); } index++; } } catch (Exception exception) { Main.error("An error occurred while attempting to update specific leaderboard: %s | %s", this.getStatisticName(), exception.getMessage()); } } public ComponentBuilder getDisplayValue(Number value, boolean isOverall, boolean personal) { if (value.doubleValue() < 0) { return new ComponentBuilder().append(GRAY).append("..."); } String statisticName = this.getStatisticName(); ComponentBuilder componentBuilder = new ComponentBuilder().append(personal ? GOLD : AQUA); if (this.isParkour()) { return componentBuilder.append(Text.formatTimeFromMilliseconds(value.longValue(), 3, true)); } if (statisticName.contains("time_played")) { return componentBuilder.append(Text.getShortTextualFormattedTime(value.longValue())); } else { if (isOverall) { if (statisticName.contains("experience")) { long xp = value.longValue(); MainGame mainGame = Main.getMainGame(); int level = RelayUtils.calculateLevel(mainGame, xp); return componentBuilder.append(RelayUtils.getColorForLevel(mainGame, level) + String.valueOf(level) + RelayUtils.getLevelCharacter(mainGame, level)); } else if (statisticName.contains("elo")) { return componentBuilder.appendComponent(SmartPlayer.getEloComponent(value.longValue(), false).getResult()); } } } boolean ratio = value instanceof Double; return componentBuilder.append(ratio ? Main.shortenNumber(value) : Text.addCommasToNumber(value.longValue())); } public GameAction getGameAction() { return GameAction.getGameAction(this.getStatisticName()); } public SpecificGameAction getSpecificGameAction() { return SpecificGameAction.getSpecificGameAction(this.getStatisticName()); } public String getStatisticName() { String statisticName = this.statisticName.getValue(); if (Main.isMainLobby()) { if (statisticName.equalsIgnoreCase("elo")) { statisticName = "tokens"; } } return statisticName; } public void playerJoin(HubPlayer hubPlayer) { this.updatePersonalArmorStands(hubPlayer); //Main.scheduleSyncDelayedTask(() -> this.showLeaderboard(hubPlayer), 0.5); } public void playerQuit(HubPlayer hubPlayer) { this.removePersonalArmorStands(hubPlayer); } private void removePersonalArmorStands(HubPlayer hubPlayer) { for (int i = 0; i < 3; i++) { Map<UUID, ArmorStand> map = this.getPersonalMap(i); if (map.containsKey(hubPlayer.getUUID())) { ArmorStand armorStand = map.get(hubPlayer.getUUID()); armorStand.remove(); map.remove(hubPlayer.getUUID()); } } } public void playerMove(HubPlayer hubPlayer, Location from, Location to) { BoundingBox boundingBox = BoundingBox.of(this.getLocation(), 30D, 30D, 30D); if (!boundingBox.contains(from.toVector()) && boundingBox.contains(to.toVector())) { this.showLeaderboard(hubPlayer); } } public void updatePersonalArmorStands(HubPlayer hubPlayer) { for (int i = 0; i < 3; i++) { this.updatePersonalArmorStand(hubPlayer, i); } } public ArmorStand updatePersonalArmorStand(HubPlayer hubPlayer, int type) { Map<UUID, ArmorStand> map = this.getPersonalMap(type); ArmorStand armorStand; if (!map.containsKey(hubPlayer.getUUID())) { RelayUtils.log("Creating armor stand for %s", hubPlayer.getName()); armorStand = this.spawnArmorStand(this.getLocation().add(0, -1.6F, 0)); this.prepareArmorStand(armorStand); for (HubPlayer onlineHubPlayer : HubPlayer.getOnlineHubPlayers()) { if (onlineHubPlayer != hubPlayer) { onlineHubPlayer.hideEntity(armorStand); } } map.put(hubPlayer.getUUID(), armorStand); } else { armorStand = map.get(hubPlayer.getUUID()); armorStand.setInvisible(true); } Map.Entry<Integer, Number> positionAndValue = this.getPositionOfPlayer(hubPlayer, type); int position = positionAndValue.getKey(); Number value = positionAndValue.getValue(); ComponentBuilder componentBuilder = new ComponentBuilder("%s%s%s. ", BOLD, GRAY, position == -1 ? "?" : position + 1); Group group = hubPlayer.getHighestGroup(); componentBuilder.color(group == Group.CHAMPION ? RelayUtils.getChampionTierColor(hubPlayer.getSmartPlayer().getChampionTier()) : hubPlayer.getHighestGroup().getOther()) .append(hubPlayer.getRealName()).color(GRAY).append(" - "); componentBuilder.appendComponent(this.getDisplayValue(value, type == 0, true).getResult()); ((CraftEntity) armorStand).getHandle().b(RelayMCUtils.fromBaseComponent(componentBuilder.getResult())); return armorStand; } public Map.Entry<Integer, Number> getPositionOfPlayer(HubPlayer hubPlayer, int type) { Map<UUID, Number> leaderboard = this.getLeaderboardOfType(type); int position = Miscellaneous.getList(leaderboard.keySet()).indexOf(hubPlayer.getUUID()); Number value = leaderboard.getOrDefault(hubPlayer.getUUID(), hubPlayer.getStatistic(type, this.getStatisticName())); return new AbstractMap.SimpleEntry<>(position, value); } public Map<UUID, Number> getLeaderboardOfType(int type) { return switch (type) { case 0 -> this.allTimeLeaderboard; case 1 -> this.weeklyLeaderboard; default -> this.dailyLeaderboard; }; } public ArmorStand getPersonalArmorStand(HubPlayer hubPlayer, int type) { return this.updatePersonalArmorStand(hubPlayer, type); } public World getWorld() { return Bukkit.getWorld("overworld"); } public Map<UUID, ArmorStand> getPersonalMap(int type) { return switch (type) { case 0 -> this.allTimePersonal; case 1 -> this.weeklyPersonal; default -> this.dailyPersonal; }; } public void showLeaderboard(HubPlayer hubPlayer) { this.showLeaderboard(hubPlayer, -1); } public List<ArmorStand> getArmorStandsOfType(int type) { return switch (type) { case 0 -> this.allTimeArmorStands; case 1 -> this.weeklyArmorStands; default -> this.dailyArmorStands; }; } public void hidePersonal(HubPlayer hubPlayer) { for (Map<UUID, ArmorStand> hubPlayerArmorStandMap : Miscellaneous.getList(this.allTimePersonal, this.weeklyPersonal, this.dailyPersonal)) { hubPlayerArmorStandMap.forEach((hubPlayer1, armorStand) -> { if (!hubPlayer1.equals(hubPlayer.getUUID())) { hubPlayer.hideEntity(armorStand); } }); } } public void showLeaderboard(HubPlayer hubPlayer, int previous) { for (StatisticsLeaderboard leaderboard : StatisticsLeaderboard.LEADERBOARDS) { Collection<ArmorStand> armorStands = getWorld().getNearbyEntitiesByType(ArmorStand.class, leaderboard.getLocation(), 2); for (ArmorStand armorStand : armorStands) { if (getFromStand(armorStand) == null && Miscellaneous.match(Parkour.PARKOUR_LIST, parkour -> Miscellaneous.match(parkour.getArmorStands(), armorStand1 -> armorStand1 == armorStand) != null) == null) { armorStand.remove(); } } } if (previous == -1) { for (ArmorStand armorStand : this.getAllArmorStands()) { hubPlayer.setEntityNameVisible(armorStand, false); } } else { ArmorStand armorStand = this.getPersonalMap(previous).get(hubPlayer.getUUID()); if (armorStand != null) { hubPlayer.setEntityNameVisible(armorStand, false); } for (ArmorStand stand : this.getArmorStandsOfType(previous)) { hubPlayer.setEntityNameVisible(stand, false); } } this.hidePersonal(hubPlayer); int type = this.getTypeForPlayer(hubPlayer); ArmorStand personalOfType = this.getPersonalArmorStand(hubPlayer, type); hubPlayer.setEntityNameVisible(personalOfType, true); switch (type) { case 0 -> { for (int i = 0; i < this.allTimeArmorStands.size(); i++) { ArmorStand armorStand = this.allTimeArmorStands.get(i); if (this.hasTimelyPositions() || i != 11) { hubPlayer.setEntityNameVisible(armorStand, true); } } } case 1 -> { for (ArmorStand weeklyArmorStand : this.weeklyArmorStands) { hubPlayer.setEntityNameVisible(weeklyArmorStand, true); } } default -> { for (ArmorStand dailyArmorStand : this.dailyArmorStands) { hubPlayer.setEntityNameVisible(dailyArmorStand, true); } } } hubPlayer.setEntityNameVisible(this.titleArmorStand, true); } public List<ArmorStand> getAllArmorStands() { List<ArmorStand> allArmorStands = new ArrayList<>(); allArmorStands.addAll(this.allTimeArmorStands); allArmorStands.addAll(this.allTimePersonal.values()); allArmorStands.addAll(this.weeklyArmorStands); allArmorStands.addAll(this.weeklyPersonal.values()); allArmorStands.addAll(this.dailyArmorStands); allArmorStands.addAll(this.dailyPersonal.values()); allArmorStands.add(this.titleArmorStand); return allArmorStands; } public void playerInteractEntity(Player player, int entityId) { RelayUtils.log("Checking for leaderboard interact %s", this.getStatisticName()); if (!this.hasTimelyPositions()) { RelayUtils.log("Cancelelind due to no timely positions"); return; } for (ArmorStand allArmorStand : this.getAllArmorStands()) { if (allArmorStand.getEntityId() == entityId) { this.cycleLeaderboard(HubPlayer.getHubPlayer(player)); break; } } RelayUtils.log("Requested id: %d", entityId); RelayUtils.log("This IDs: %s", Text.separateWithCommas(this.getAllArmorStands(), armorStand -> String.valueOf(armorStand.getEntityId()))); } public boolean hasTimelyPositions() { return !(this.isParkour() || this.isArena() || this.getStatisticName().contains("winstreak") || (Main.isMainLobby() && Miscellaneous.getList("experience", "tokens", "time_played").contains(this.getStatisticName()))); } public void cycleLeaderboard(HubPlayer hubPlayer) { int previous = this.getTypeForPlayer(hubPlayer); int current = previous == 2 ? 0 : previous + 1; this.playerToLeaderboardType.put(hubPlayer.getUUID(), current); this.showLeaderboard(hubPlayer, previous); String type = switch (current) { case 0 -> "All Time"; case 1 -> "Weekly"; default -> "Daily"; }; hubPlayer.sendInfoMessage("Now showing %s%s%s positions.", AQUA + BOLD.toString(), type, YELLOW); hubPlayer.playClickSound(); } public int getTypeForPlayer(HubPlayer hubPlayer) { if (!this.playerToLeaderboardType.containsKey(hubPlayer.getUUID())) { this.playerToLeaderboardType.put(hubPlayer.getUUID(), 0); return 0; } return this.playerToLeaderboardType.get(hubPlayer.getUUID()); } public String getSmartName() { return this.id + "-" + this.statisticName.getValue(); } public static StatisticsLeaderboard createFromJson(JsonObject jsonObject) { StatisticsLeaderboard leaderboard = new StatisticsLeaderboard(0, 0, 0, "experience"); leaderboard.fromJson(jsonObject); return leaderboard; } public static void onPlayerJoin(HubPlayer hubPlayer) { for (StatisticsLeaderboard leaderboard : LEADERBOARDS) { leaderboard.playerJoin(hubPlayer); } } public static void onPlayerQuit(HubPlayer hubPlayer) { for (StatisticsLeaderboard leaderboard : LEADERBOARDS) { leaderboard.playerQuit(hubPlayer); } } public static void showLeaderboards(HubPlayer hubPlayer) { for (StatisticsLeaderboard leaderboard : LEADERBOARDS) { leaderboard.showLeaderboard(hubPlayer); } } public static void onPlayerMove(Player player, Location from, Location to) { for (StatisticsLeaderboard leaderboard : LEADERBOARDS) { leaderboard.playerMove(HubPlayer.getHubPlayer(player), from, to); } } public static void updateLeaderboards() { Main.async(() -> { //LeaderboardProfile.refresh(); for (StatisticsLeaderboard leaderboard : LEADERBOARDS) { leaderboard.updateData(); } }); } public static void onTick() { } public static void onPlayerInteractEntity(Player player, int entityId) { for (StatisticsLeaderboard leaderboard : LEADERBOARDS) { leaderboard.playerInteractEntity(player, entityId); } } public static boolean hasLeaderboardSelected(HubPlayer hubPlayer) { return getSelectedLeaderboard(hubPlayer) != null; } public static StatisticsLeaderboard getSelectedLeaderboard(HubPlayer hubPlayer) { for (StatisticsLeaderboard leaderboard : LEADERBOARDS) { if (leaderboard.id == HUB_PLAYER_TO_SELECTED.getOrDefault(hubPlayer, -1)) { return leaderboard; } } return null; } public static StatisticsLeaderboard getLeaderboard(String argument) { for (StatisticsLeaderboard leaderboard : LEADERBOARDS) { if (String.valueOf(leaderboard.id).equalsIgnoreCase(argument) || leaderboard.getSmartName().equalsIgnoreCase(argument)) { return leaderboard; } } return null; } public static void selectLeaderboard(HubPlayer hubPlayer, int id) { HUB_PLAYER_TO_SELECTED.put(hubPlayer, id); } public static void deleteLeaderboard(HubPlayer hubPlayer) { StatisticsLeaderboard leaderboard = getSelectedLeaderboard(hubPlayer); if (leaderboard == null) return; leaderboard.delete(); } public static void teleportLeaderboard(HubPlayer hubPlayer) { StatisticsLeaderboard leaderboard = getSelectedLeaderboard(hubPlayer); if (leaderboard == null) return; leaderboard.removeArmorStands(); leaderboard.setPosition(hubPlayer.getLocation().add(0, 0.4, 0)); leaderboard.createArmorStands(); } public static void showInfo(HubPlayer hubPlayer) { StatisticsLeaderboard leaderboard = getSelectedLeaderboard(hubPlayer); if (leaderboard != null) leaderboard.info(hubPlayer); } public static void listLeaderboards(HubPlayer hubPlayer) { if (LEADERBOARDS.isEmpty()) { hubPlayer.sendInfoMessage("There are no leaderboards to display."); } else { hubPlayer.sendInfoMessage("-----------"); for (StatisticsLeaderboard leaderboard : LEADERBOARDS) { leaderboard.info(hubPlayer); } hubPlayer.sendInfoMessage("-----------"); } } public static List<String> getAllSmartNames() { List<String> names = new ArrayList<>(); for (StatisticsLeaderboard leaderboard : LEADERBOARDS) { names.add(leaderboard.getSmartName()); } return names; } public static void readConfig(JsonObject jsonObject) { if (!jsonObject.has("leaderboards")) { Main.error("No leaderboards in config"); return; } JsonArray jsonArray = jsonObject.get("leaderboards").getAsJsonArray(); for (JsonElement jsonElement : jsonArray) { try { createFromJson(jsonElement.getAsJsonObject()); } catch (Exception exception) { RelayMCUtils.error("An error occurred while attempting to create a leaderboard from the config: %s (%s)", exception.getMessage(), jsonElement.getAsJsonObject()); } } } public static JsonArray getLeaderboardsAsJsonArray() { JsonArray jsonArray = new JsonArray(); for (StatisticsLeaderboard leaderboard : LEADERBOARDS) { jsonArray.add(leaderboard.toJson()); } return jsonArray; } public static void clear() { while (!LEADERBOARDS.isEmpty()) { LEADERBOARDS.get(0).delete(); } } }