From d3f953e3dc4a6ea28aed634c4f07a79722521387 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sat, 8 Apr 2023 14:54:34 +0200 Subject: [PATCH] Add Leaderboard to BoatRace --- src/de/steamwar/lobby/boatrace/BoatRace.java | 17 ++-- src/de/steamwar/lobby/util/Leaderboard.java | 89 ++++++++++++++++++++ 2 files changed, 97 insertions(+), 9 deletions(-) create mode 100644 src/de/steamwar/lobby/util/Leaderboard.java diff --git a/src/de/steamwar/lobby/boatrace/BoatRace.java b/src/de/steamwar/lobby/boatrace/BoatRace.java index fadb539..1573941 100644 --- a/src/de/steamwar/lobby/boatrace/BoatRace.java +++ b/src/de/steamwar/lobby/boatrace/BoatRace.java @@ -4,6 +4,7 @@ import de.steamwar.entity.REntity; import de.steamwar.entity.REntityServer; import de.steamwar.entity.RPlayer; import de.steamwar.lobby.LobbySystem; +import de.steamwar.lobby.util.Leaderboard; import de.steamwar.sql.UserConfig; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -24,6 +25,8 @@ import org.bukkit.scheduler.BukkitTask; import java.util.*; +import static de.steamwar.lobby.util.Leaderboard.renderTime; + public class BoatRace implements EventListener, Listener { private static final double MIN_HEIGHT = 4.3; @@ -31,17 +34,20 @@ public class BoatRace implements EventListener, Listener { public static final REntityServer boatNpcServer; private static boolean oneNotStarted = false; + private static final Leaderboard leaderboard; static { boatNpcServer = new REntityServer(); - new REntity(boatNpcServer, EntityType.VILLAGER, BoatRacePositions.NPC); + REntity starter = new REntity(boatNpcServer, EntityType.VILLAGER, BoatRacePositions.NPC); boatNpcServer.setCallback((player, rEntity, entityAction) -> { + if (rEntity != starter) return; Bukkit.getWorlds().get(0).getEntities().stream().filter(entity -> entity.getType() == EntityType.ENDER_CRYSTAL).forEach(Entity::remove); if (entityAction == REntityServer.EntityAction.INTERACT && !oneNotStarted) { oneNotStarted = true; new BoatRace(player); } }); + leaderboard = new Leaderboard(boatNpcServer, "lobby@boatrace", BoatRacePositions.LEADERBOARD, 5); } private final Player player; @@ -101,6 +107,7 @@ public class BoatRace implements EventListener, Listener { if (time < best) { LobbySystem.getMessage().send("BOAT_RACE_NEW_BEST", player); UserConfig.updatePlayerConfig(player.getUniqueId(), "lobby@boatrace", String.valueOf(time)); + leaderboard.update(); } } else { player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1, 1); @@ -148,12 +155,4 @@ public class BoatRace implements EventListener, Listener { return p.getLocation().getX() >= x1 && p.getLocation().getY() >= y1 && p.getLocation().getZ() >= z1 && p.getLocation().getX() <= x2 && p.getLocation().getY() <= y2 && p.getLocation().getZ() <= z2; } - - private String renderTime(long time) { - return String.format( - "%d:%02d.%03d", - time / 60000, - (time / 1000) % 60, - time % 1000); - } } diff --git a/src/de/steamwar/lobby/util/Leaderboard.java b/src/de/steamwar/lobby/util/Leaderboard.java new file mode 100644 index 0000000..49a153c --- /dev/null +++ b/src/de/steamwar/lobby/util/Leaderboard.java @@ -0,0 +1,89 @@ +package de.steamwar.lobby.util; + +import de.steamwar.entity.RArmorStand; +import de.steamwar.entity.REntity; +import de.steamwar.entity.REntityServer; +import de.steamwar.lobby.LobbySystem; +import de.steamwar.sql.SteamwarUser; +import de.steamwar.sql.internal.Statement; +import lombok.AllArgsConstructor; +import org.bukkit.Location; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Leaderboard { + + private static final Statement LEADERBOARD = new Statement("SELECT User, CAST(Value as integer) AS Time from UserConfig WHERE Config = ? ORDER BY CAST(Value as integer) LIMIT ?"); + + private final REntityServer server; + private final String configKey; + private final Location location; + private final int best; + private final List entities; + + public Leaderboard(REntityServer server, String configKey, Location location, int best) { + this.server = server; + this.configKey = configKey; + this.location = location; + this.best = best; + entities = new ArrayList<>(best + 2); + update(); + } + + public void update() { + entities.forEach(REntity::die); + entities.clear(); + List leaderboard = getLeaderboard(); + long bestTime = leaderboard.get(0).time; + for (int i = 0; i <= best; i++) { + if (best - i >= leaderboard.size()) continue; + LeaderboardEntry entry = leaderboard.get(best - i); + RArmorStand entity = new RArmorStand(server, location.clone().add(0, i * 0.32, 0), RArmorStand.Size.MARKER); + SteamwarUser user = SteamwarUser.get(entry.user); + if (i == best) { + entity.setDisplayName("§6§l" + user.getUserName() + " §8• §6§l" + renderTime(entry.time)); + } else if (i <= best - 1 && i > best - 3) { + entity.setDisplayName("§e" + user.getUserName() + " §8• §e" + renderTime(entry.time) + " §8• §e+" + renderShortTime(entry.time - bestTime)); + } else { + entity.setDisplayName("§7" + user.getUserName() + " §8• §7" + renderTime(entry.time) + " §8• §7+" + renderShortTime(entry.time - bestTime)); + } + entity.setInvisible(true); + entities.add(entity); + } + } + + private List getLeaderboard() { + return LEADERBOARD.select(resultSet -> { + List leaderboard = new ArrayList<>(); + while (resultSet.next()) { + leaderboard.add(new LeaderboardEntry(resultSet.getInt("User"), resultSet.getLong("Time"))); + } + return leaderboard; + }, configKey, best); + } + + public static String renderTime(long time) { + return String.format( + "%d:%02d.%03d", + time / 60000, + (time / 1000) % 60, + time % 1000); + } + + public static String renderShortTime(long time) { + return String.format( + "%d.%03d", + time / 1000, + time % 1000); + } + + @AllArgsConstructor + private class LeaderboardEntry { + + private final int user; + private final long time; + } +}