diff --git a/CommonCore/SQL/src/de/steamwar/sql/Leaderboard.java b/CommonCore/SQL/src/de/steamwar/sql/Leaderboard.java
new file mode 100644
index 00000000..16ee2a41
--- /dev/null
+++ b/CommonCore/SQL/src/de/steamwar/sql/Leaderboard.java
@@ -0,0 +1,73 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.sql;
+
+import de.steamwar.sql.internal.Field;
+import de.steamwar.sql.internal.SelectStatement;
+import de.steamwar.sql.internal.Statement;
+import de.steamwar.sql.internal.Table;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.sql.Timestamp;
+import java.util.List;
+
+@AllArgsConstructor
+@Getter
+public class Leaderboard {
+ private static final Table table = new Table<>(Leaderboard.class);
+
+ private static final SelectStatement LEADERBOARD = new SelectStatement<>(table, "SELECT * from Leaderboard WHERE LeaderboardName = ? ORDER BY Time ASC LIMIT 5");
+ private static final SelectStatement PLAYER_TIME = new SelectStatement<>(table, "SELECT * FROM Leaderboard WHERE LeaderboardName = ? AND UserId = ?");
+ private static final Statement PLAYER_PLACEMENT = new Statement("SELECT COUNT(*) AS Placement FROM Leaderboard WHERE LeaderboardName = ? AND time < (SELECT time FROM UserConfig WHERE WHERE = ? AND LeaderboardName = ?)");
+
+ private static final Statement INSERT = new Statement("INSERT INTO Leaderboard (UserId, LeaderboardName, Time, BestTime) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE Time = VALUES(Time), BestTime = VALUES(BestTime)");
+
+ public static List getLeaderboard(String leaderboardName) {
+ return LEADERBOARD.listSelect(leaderboardName);
+ }
+
+ public static Leaderboard getPlayerTime(SteamwarUser user, String leaderboardName) {
+ return PLAYER_TIME.select(leaderboardName, user);
+ }
+
+ public static int getPlayerPlacement(SteamwarUser user, String leaderboardName) {
+ return PLAYER_PLACEMENT.select(rs -> {
+ if(!rs.next())
+ return Integer.MAX_VALUE;
+ return rs.getInt("Placement");
+ }, leaderboardName, user, leaderboardName);
+ }
+
+ public static void upsert(int userId, String leaderboardName, long time, boolean bestTime) {
+ INSERT.update(userId, leaderboardName, time, bestTime);
+ }
+
+ @Field(keys = Table.PRIMARY)
+ private final int userId;
+ @Field(keys = Table.PRIMARY)
+ private final String leaderboardName;
+ @Field
+ private final long time;
+ @Field
+ private final Timestamp updatedAt;
+ @Field
+ private final boolean bestTime;
+}
diff --git a/LobbySystem/src/de/steamwar/lobby/boatrace/BoatRace.java b/LobbySystem/src/de/steamwar/lobby/boatrace/BoatRace.java
index 55c6daf7..e61533e0 100644
--- a/LobbySystem/src/de/steamwar/lobby/boatrace/BoatRace.java
+++ b/LobbySystem/src/de/steamwar/lobby/boatrace/BoatRace.java
@@ -22,8 +22,9 @@ package de.steamwar.lobby.boatrace;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import de.steamwar.lobby.LobbySystem;
-import de.steamwar.lobby.util.Leaderboard;
-import de.steamwar.sql.UserConfig;
+import de.steamwar.lobby.util.LeaderboardManager;
+import de.steamwar.sql.Leaderboard;
+import de.steamwar.sql.SteamwarUser;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Sound;
@@ -43,16 +44,18 @@ import org.bukkit.scheduler.BukkitTask;
import java.util.EventListener;
-import static de.steamwar.lobby.util.Leaderboard.renderTime;
+import static de.steamwar.lobby.util.LeaderboardManager.renderTime;
public class BoatRace implements EventListener, Listener {
+ private static final String CONFIG_KEY = "lobby@boatrace";
+
private static final double MIN_HEIGHT = 4.3;
public static final REntityServer boatNpcServer;
private static boolean oneNotStarted = false;
- private static final Leaderboard leaderboard;
+ private static final LeaderboardManager leaderboard;
static {
boatNpcServer = new REntityServer();
@@ -65,7 +68,7 @@ public class BoatRace implements EventListener, Listener {
new BoatRace(player);
}
});
- leaderboard = new Leaderboard(boatNpcServer, "lobby@boatrace", BoatRacePositions.LEADERBOARD, 5);
+ leaderboard = new LeaderboardManager(boatNpcServer, CONFIG_KEY, BoatRacePositions.LEADERBOARD);
}
private final Player player;
@@ -123,12 +126,11 @@ public class BoatRace implements EventListener, Listener {
HandlerList.unregisterAll(this);
task.cancel();
LobbySystem.getMessage().send("BOAT_RACE_TIME", player, renderTime(time));
- String conf = UserConfig.getConfig(player.getUniqueId(), "lobby@boatrace");
- long best = Long.parseLong(conf == null ? String.valueOf(Long.MAX_VALUE) : conf);
+ SteamwarUser user = SteamwarUser.get(player.getUniqueId());
+ long best = leaderboard.getPlayerTime(user);
if (time < best) {
LobbySystem.getMessage().send("BOAT_RACE_NEW_BEST", player);
- UserConfig.updatePlayerConfig(player.getUniqueId(), "lobby@boatrace", String.valueOf(time));
- leaderboard.update();
+ leaderboard.updateBestTime(user, time);
}
} else {
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1, 1);
diff --git a/LobbySystem/src/de/steamwar/lobby/jumpandrun/JumpAndRun.java b/LobbySystem/src/de/steamwar/lobby/jumpandrun/JumpAndRun.java
index adc63951..274a2b7f 100644
--- a/LobbySystem/src/de/steamwar/lobby/jumpandrun/JumpAndRun.java
+++ b/LobbySystem/src/de/steamwar/lobby/jumpandrun/JumpAndRun.java
@@ -22,8 +22,8 @@ package de.steamwar.lobby.jumpandrun;
import de.steamwar.linkage.Linked;
import de.steamwar.lobby.LobbySystem;
import de.steamwar.lobby.listener.PlayerSpawn;
-import de.steamwar.lobby.util.Leaderboard;
-import de.steamwar.sql.UserConfig;
+import de.steamwar.lobby.util.LeaderboardManager;
+import de.steamwar.sql.SteamwarUser;
import net.md_5.bungee.api.ChatMessageType;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -58,7 +58,7 @@ public class JumpAndRun implements Listener {
private static final Map CLICKED = new HashMap<>();
private static final Map CLICKED_COUNT = new HashMap<>();
- private static final Leaderboard LEADERBOARD = new Leaderboard(LobbySystem.getEntityServer(false), JUMP_AND_RUN_CONFIG, new Location(Bukkit.getWorlds().get(0), 2338.5, 42.5, 1231.5), 5);
+ private static final LeaderboardManager LEADERBOARD = new LeaderboardManager(LobbySystem.getEntityServer(false), JUMP_AND_RUN_CONFIG, new Location(Bukkit.getWorlds().get(0), 2338.5, 42.5, 1231.5));
{
Bukkit.getScheduler().runTaskTimer(LobbySystem.getInstance(), () -> {
@@ -161,18 +161,14 @@ public class JumpAndRun implements Listener {
}
private void updateJumpAndRunTime(Player player, long time) {
- String jumpAndRunTimeConfig = UserConfig.getConfig(player.getUniqueId(), JUMP_AND_RUN_CONFIG);
- if (jumpAndRunTimeConfig == null) {
- UserConfig.updatePlayerConfig(player.getUniqueId(), JUMP_AND_RUN_CONFIG, time + "");
- } else {
- long jumpAndRunTime = Long.parseLong(jumpAndRunTimeConfig);
- if (time < jumpAndRunTime) {
+ long best = LEADERBOARD.getPlayerTime(SteamwarUser.get(player.getUniqueId()));
+ if (time < best) {
+ if (best != Long.MAX_VALUE) {
SimpleDateFormat format = new SimpleDateFormat(LobbySystem.getMessage().parse("JUMP_AND_RUN_TIME", player), Locale.ROOT);
- String parsed = format.format(new Date(jumpAndRunTime - time));
+ String parsed = format.format(new Date(best - time));
LobbySystem.getMessage().sendPrefixless("JUMP_AND_RUN_PERSONAL_BEST", player, parsed);
- UserConfig.updatePlayerConfig(player.getUniqueId(), JUMP_AND_RUN_CONFIG, time + "");
- LEADERBOARD.update();
}
+ LEADERBOARD.updateBestTime(SteamwarUser.get(player.getUniqueId()), time);
}
}
diff --git a/LobbySystem/src/de/steamwar/lobby/util/Leaderboard.java b/LobbySystem/src/de/steamwar/lobby/util/LeaderboardManager.java
similarity index 73%
rename from LobbySystem/src/de/steamwar/lobby/util/Leaderboard.java
rename to LobbySystem/src/de/steamwar/lobby/util/LeaderboardManager.java
index f0a33a4a..7bfebbab 100644
--- a/LobbySystem/src/de/steamwar/lobby/util/Leaderboard.java
+++ b/LobbySystem/src/de/steamwar/lobby/util/LeaderboardManager.java
@@ -23,9 +23,8 @@ import de.steamwar.entity.RArmorStand;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import de.steamwar.lobby.LobbySystem;
+import de.steamwar.sql.Leaderboard;
import de.steamwar.sql.SteamwarUser;
-import de.steamwar.sql.internal.Statement;
-import lombok.AllArgsConstructor;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
@@ -39,25 +38,18 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-public class Leaderboard implements Listener {
-
- 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) ASC LIMIT ?");
- private static final Statement PLAYER_TIME = new Statement("SELECT CAST(Value as integer) AS Time FROM UserConfig WHERE Config = ? AND User = ?");
- private static final Statement PLAYER_PLACEMENT = new Statement("SELECT COUNT(*) AS Placement FROM UserConfig WHERE Config = ? AND CAST(Value as integer) < (SELECT CAST(Value as integer) AS Time FROM UserConfig WHERE Config = ? AND User = ?)");
-
+public class LeaderboardManager implements Listener {
private final REntityServer server;
private final String configKey;
private final Location location;
- private final int best;
private long bestTime;
private final List entities = new ArrayList<>();
private final Map playerPlacements = new HashMap<>();
- public Leaderboard(REntityServer server, String configKey, Location location, int best) {
+ public LeaderboardManager(REntityServer server, String configKey, Location location) {
this.server = server;
this.configKey = configKey;
this.location = location;
- this.best = best;
Bukkit.getPluginManager().registerEvents(this, LobbySystem.getInstance());
update();
}
@@ -65,11 +57,11 @@ public class Leaderboard implements Listener {
public void update() {
entities.forEach(REntity::die);
entities.clear();
- List leaderboard = getLeaderboard();
+ List leaderboard = getLeaderboard();
if (leaderboard.isEmpty()) return;
- bestTime = leaderboard.get(0).time;
+ bestTime = leaderboard.get(0).getTime();
for (int i = 0; i < leaderboard.size(); i++) {
- LeaderboardEntry entry = leaderboard.get(i);
+ Leaderboard entry = leaderboard.get(i);
RArmorStand entity = new RArmorStand(server, location.clone().add(0, (leaderboard.size() - i - 1) * 0.32, 0), RArmorStand.Size.MARKER);
SteamwarUser user = SteamwarUser.byId(entry.user);
String color = "§7";
@@ -78,7 +70,7 @@ public class Leaderboard implements Listener {
} else if (i < 3) {
color = "§e";
}
- entity.setDisplayName(calcName(user, color, i + 1, entry.time));
+ entity.setDisplayName(calcName(user, color, i + 1, entry.getTime()));
entity.setInvisible(true);
entities.add(entity);
}
@@ -135,32 +127,27 @@ public class Leaderboard implements Listener {
return st.toString();
}
- 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);
+ private boolean isNewBestTime(long time) {
+ return time < bestTime;
}
- private long getPlayerTime(SteamwarUser user) {
- return PLAYER_TIME.select(resultSet -> {
- if (!resultSet.next()) {
- return Long.MAX_VALUE;
- }
- return resultSet.getLong("Time");
- }, configKey, user.getId());
+ public void updateBestTime(SteamwarUser user, long time) {
+ Leaderboard.upsert(user.getId(), configKey, time, isNewBestTime(time));
+ update();
+ }
+
+ private List getLeaderboard() {
+ return Leaderboard.getLeaderboard(configKey);
+ }
+
+ public long getPlayerTime(SteamwarUser user) {
+ Leaderboard lb = Leaderboard.getPlayerTime(user, configKey);
+ if(lb != null) return lb.getTime();
+ return 0;
}
private int getPlayerPlacement(SteamwarUser user) {
- return PLAYER_PLACEMENT.select(resultSet -> {
- if (!resultSet.next()) {
- return Integer.MAX_VALUE;
- }
- return resultSet.getInt("Placement");
- }, configKey, configKey, user.getId());
+ return Leaderboard.getPlayerPlacement(user, configKey);
}
public static String renderTime(long time) {
@@ -178,13 +165,6 @@ public class Leaderboard implements Listener {
time % 1000);
}
- @AllArgsConstructor
- private class LeaderboardEntry {
-
- private final int user;
- private final long time;
- }
-
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
SteamwarUser steamwarUser = SteamwarUser.get(event.getPlayer().getUniqueId());