From 4697f0616338cd46720589948c682c9c079bee20 Mon Sep 17 00:00:00 2001 From: R00tB33rMan <36140389+R00tB33rMan@users.noreply.github.com> Date: Mon, 6 Jul 2026 20:00:51 -0400 Subject: [PATCH] Various fixes & improvements (#246) * HuskClaims Support * Bump Lombok for compilation and fix other obscure issues * Resolve database locking * Have the executor service perform in multiple places * Utilize a ConcurrentHashMap instead of a HashMap for player data management to mitigate fast connections and thread switching * Reapply modifications with UUID checking for this particular instance * Apply additional null checks to mitigate player reading exceptions once again * Fix RTP on death on custom worlds and add it to debug print * Migrate to newer FoliaLib module and fix compilation again * Fix Min-Max Radius Co-authored-by: ZepsiZola * Implement labeled HuskClaims support since it's internally implemented * Rebase * Likely make thread-safe * Resolve obscure and rare ArrayIndexOutOfBoundsException --------- Co-authored-by: JMaleta <13309090+JMeta0@users.noreply.github.com> Co-authored-by: ZepsiZola --- pom.xml | 52 ++--- .../BetterRTP/player/events/Join.java | 9 +- .../player/rtp/packets/AbstractPacket.java | 14 +- .../references/database/DatabasePlayers.java | 78 ++++--- .../references/database/DatabaseQueue.java | 196 +++++++----------- .../references/database/SQLiteExecutor.java | 8 + .../depends/regionPlugins/RTP_WorldGuard.java | 3 - .../player/playerdata/PlayerData.java | 5 +- .../player/playerdata/PlayerDataManager.java | 16 +- .../references/rtpinfo/CooldownHandler.java | 98 +++------ .../references/rtpinfo/RandomLocation.java | 38 ++-- .../BetterRTP/versions/AsyncHandler.java | 5 - src/main/resources/plugin.yml | 2 +- 13 files changed, 206 insertions(+), 318 deletions(-) create mode 100644 src/main/java/me/SuperRonanCraft/BetterRTP/references/database/SQLiteExecutor.java diff --git a/pom.xml b/pom.xml index dda80d1..9e58583 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.2.2 + 3.4.2 ../../Java/plugins @@ -47,13 +47,13 @@ org.apache.maven.plugins maven-install-plugin - 3.1.0 + 3.1.4 org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.6.0 ${project.build.directory}/dependency-reduced-pom.xml @@ -66,10 +66,6 @@ com.tcoded.folialib me.SuperRonanCraft.BetterRTP.lib.folialib - @@ -84,7 +80,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.10.1 + 3.14.0 1.8 1.8 @@ -105,6 +101,11 @@ jitpack.io https://jitpack.io + + + tcoded-releases + https://repo.tcoded.com/releases + spigot-repo @@ -120,7 +121,7 @@ vault-repo https://nexus.hc.to/content/repositories/pub_releases - + sk89q-repo https://maven.enginehub.org/repo/ @@ -191,7 +192,7 @@ 1.0.8 compile - + com.sk89q.worldguard worldguard-bukkit @@ -229,7 +230,7 @@ com.comphenix.protocol ProtocolLib - 4.8.0 + 5.3.0 provided @@ -243,10 +244,10 @@ com.github.TechFortress GriefPrevention - 16.18 + 17.0.0 provided - + com.github.cryptomorin kingdoms @@ -286,14 +287,14 @@ org.projectlombok lombok - 1.18.26 + 1.18.38 provided net.essentialsx EssentialsX - 2.20.1 + 2.21.0 provided @@ -319,14 +320,14 @@ me.clip placeholderapi - 2.11.2 + 2.11.6 provided net.william278.huskclaims huskclaims-bukkit - 1.5.2 + 1.5.10 provided @@ -345,9 +346,9 @@ - com.github.TechnicallyCoded + com.tcoded FoliaLib - 0.4.3 + 0.5.1 compile @@ -364,19 +365,6 @@ c697d3e9ef provided - - - - - - - com.bekvon.bukkit.residence Residence diff --git a/src/main/java/me/SuperRonanCraft/BetterRTP/player/events/Join.java b/src/main/java/me/SuperRonanCraft/BetterRTP/player/events/Join.java index 0d60084..fc8ed9e 100644 --- a/src/main/java/me/SuperRonanCraft/BetterRTP/player/events/Join.java +++ b/src/main/java/me/SuperRonanCraft/BetterRTP/player/events/Join.java @@ -20,9 +20,7 @@ public class Join { static void event(PlayerJoinEvent e) { Player p = e.getPlayer(); updater(p); - AsyncHandler.async(() -> { - getPl().getCooldowns().loadPlayer(p); - }); + AsyncHandler.async(() -> getPl().getCooldowns().loadPlayer(p)); rtpOnFirstJoin(p); } @@ -42,10 +40,7 @@ public class Join { //RTP on first join private static void rtpOnFirstJoin(Player p) { if (getPl().getSettings().isRtpOnFirstJoin_Enabled() && !p.hasPlayedBefore()) - HelperRTP.tp(p, Bukkit.getConsoleSender(), - Bukkit.getWorld(getPl().getSettings().getRtpOnFirstJoin_World()), - null, RTP_TYPE.JOIN, true, true); - //Fixed via @kazigk on Github + HelperRTP.tp(p, Bukkit.getConsoleSender(), Bukkit.getWorld(getPl().getSettings().getRtpOnFirstJoin_World()), null, RTP_TYPE.JOIN, true, true); } private static BetterRTP getPl() { diff --git a/src/main/java/me/SuperRonanCraft/BetterRTP/player/rtp/packets/AbstractPacket.java b/src/main/java/me/SuperRonanCraft/BetterRTP/player/rtp/packets/AbstractPacket.java index 50e2076..aa85309 100644 --- a/src/main/java/me/SuperRonanCraft/BetterRTP/player/rtp/packets/AbstractPacket.java +++ b/src/main/java/me/SuperRonanCraft/BetterRTP/player/rtp/packets/AbstractPacket.java @@ -6,8 +6,6 @@ import com.comphenix.protocol.events.PacketContainer; import com.google.common.base.Objects; import org.bukkit.entity.Player; -import java.lang.reflect.InvocationTargetException; - public abstract class AbstractPacket { // The packet we will be modifying protected PacketContainer handle; @@ -42,15 +40,9 @@ public abstract class AbstractPacket { * Send the current packet to the given receiver. * * @param receiver - the receiver. - * @throws RuntimeException If the packet cannot be sent. */ public void sendPacket(Player receiver) { - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(receiver, - getHandle()); - } catch (InvocationTargetException e) { - throw new RuntimeException("Cannot send packet.", e); - } + ProtocolLibrary.getProtocolManager().sendServerPacket(receiver, getHandle()); } /** @@ -71,7 +63,7 @@ public abstract class AbstractPacket { @Deprecated public void recievePacket(Player sender) { try { - ProtocolLibrary.getProtocolManager().recieveClientPacket(sender, + ProtocolLibrary.getProtocolManager().receiveClientPacket(sender, getHandle()); } catch (Exception e) { throw new RuntimeException("Cannot recieve packet.", e); @@ -86,7 +78,7 @@ public abstract class AbstractPacket { */ public void receivePacket(Player sender) { try { - ProtocolLibrary.getProtocolManager().recieveClientPacket(sender, + ProtocolLibrary.getProtocolManager().receiveClientPacket(sender, getHandle()); } catch (Exception e) { throw new RuntimeException("Cannot receive packet.", e); diff --git a/src/main/java/me/SuperRonanCraft/BetterRTP/references/database/DatabasePlayers.java b/src/main/java/me/SuperRonanCraft/BetterRTP/references/database/DatabasePlayers.java index 47141fe..6cf43d1 100644 --- a/src/main/java/me/SuperRonanCraft/BetterRTP/references/database/DatabasePlayers.java +++ b/src/main/java/me/SuperRonanCraft/BetterRTP/references/database/DatabasePlayers.java @@ -6,6 +6,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Future; import java.util.logging.Level; import me.SuperRonanCraft.BetterRTP.BetterRTP; @@ -29,7 +30,6 @@ public class DatabasePlayers extends SQLite { //COOLDOWN DATA COUNT("count", "long"), LAST_COOLDOWN_DATE("last_rtp_date", "long"), - //USES("uses", "integer"), ; public final String name; @@ -42,43 +42,55 @@ public class DatabasePlayers extends SQLite { } public void setupData(PlayerData data) { - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; + if (data == null || data.player == null) { + return; + } try { - conn = getSQLConnection(); - ps = conn.prepareStatement("SELECT * FROM " + tables.get(0) + " WHERE " + COLUMNS.UUID.name + " = ?"); - ps.setString(1, data.player.getUniqueId().toString()); + Future task = SQLiteExecutor.EXECUTOR.submit(() -> { + Connection conn = null; + PreparedStatement ps = null; + ResultSet rs = null; + try { + conn = getSQLConnection(); + ps = conn.prepareStatement("SELECT * FROM " + tables.get(0) + " WHERE " + COLUMNS.UUID.name + " = ?"); + ps.setString(1, data.player.getUniqueId().toString()); - rs = ps.executeQuery(); - if (rs.next()) { - long count = rs.getLong(COLUMNS.COUNT.name); - long time = rs.getLong(COLUMNS.LAST_COOLDOWN_DATE.name); - data.setRtpCount(Math.toIntExact(count)); - data.setGlobalCooldown(time); - } - } catch (SQLException ex) { - BetterRTP.getInstance().getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex); - } finally { - close(ps, rs, conn); + rs = ps.executeQuery(); + if (rs.next()) { + long count = rs.getLong(COLUMNS.COUNT.name); + long time = rs.getLong(COLUMNS.LAST_COOLDOWN_DATE.name); + data.setRtpCount(Math.toIntExact(count)); + data.setGlobalCooldown(time); + } + } catch (SQLException ex) { + BetterRTP.getInstance().getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex); + } finally { + close(ps, rs, conn); + } + }); + task.get(); + } catch (Exception ex) { + ex.printStackTrace(); } } //Set a player Cooldown public void setData(PlayerData data) { - String pre = "INSERT OR REPLACE INTO "; - String sql = pre + tables.get(0) + " (" - + COLUMNS.UUID.name + ", " - + COLUMNS.COUNT.name + ", " - + COLUMNS.LAST_COOLDOWN_DATE.name + " " - //+ COLUMNS.USES.name + " " - + ") VALUES(?, ?, ?)"; - List params = new ArrayList() {{ - add(data.player.getUniqueId().toString()); - add(data.getRtpCount()); - add(data.getGlobalCooldown()); - //add(data.getUses()); - }}; - sqlUpdate(sql, params); + try { + SQLiteExecutor.EXECUTOR.submit(() -> { + String sql = "INSERT OR REPLACE INTO " + tables.get(0) + " (" + + COLUMNS.UUID.name + ", " + + COLUMNS.COUNT.name + ", " + + COLUMNS.LAST_COOLDOWN_DATE.name + ") VALUES(?, ?, ?)"; + List params = new ArrayList() {{ + add(data.player.getUniqueId().toString()); + add(data.getRtpCount()); + add(data.getGlobalCooldown()); + }}; + sqlUpdate(sql, params); + }); + } catch (Exception ex) { + ex.printStackTrace(); + } } -} \ No newline at end of file +} diff --git a/src/main/java/me/SuperRonanCraft/BetterRTP/references/database/DatabaseQueue.java b/src/main/java/me/SuperRonanCraft/BetterRTP/references/database/DatabaseQueue.java index c04e8ec..ccb9839 100644 --- a/src/main/java/me/SuperRonanCraft/BetterRTP/references/database/DatabaseQueue.java +++ b/src/main/java/me/SuperRonanCraft/BetterRTP/references/database/DatabaseQueue.java @@ -11,7 +11,11 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; -import java.sql.*; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -48,124 +52,72 @@ public class DatabaseQueue extends SQLite { } } - /*public List getAll() { - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - List queueDataList = new ArrayList<>(); - try { - conn = getSQLConnection(); - ps = conn.prepareStatement("SELECT * FROM " + tables.get(0)); - - rs = ps.executeQuery(); - while (rs.next()) { - long x = rs.getLong(COLUMNS.X.name); - long z = rs.getLong(COLUMNS.Z.name); - String worldName = rs.getString(COLUMNS.WORLD.name); - int id = rs.getInt(COLUMNS.ID.name); - long generated = rs.getLong(COLUMNS.GENERATED.name); - World world = Bukkit.getWorld(worldName); - if (world != null) { - queueDataList.add(new QueueData(new Location(world, x, 69, z), generated, id)); - } - } - } catch (SQLException ex) { - BetterRTP.getInstance().getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex); - } finally { - close(ps, rs, conn); - } - return queueDataList; - }*/ - @Override public void load() { if (QueueHandler.isEnabled()) super.load(); } public List getInRange(QueueRangeData range) { - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - List queueDataList = new ArrayList<>(); + final List queueDataList = new ArrayList<>(); try { - conn = getSQLConnection(); - //ps = conn.prepareStatement("SELECT * FROM " + tables.get(0) + " WHERE ? BETWEEN ? AND ? AND ? BETWEEN ? AND ?"); - ps = conn.prepareStatement("SELECT * FROM " + tables.get(0) + " WHERE " - + COLUMNS.WORLD.name + " = '" + range.getWorld().getName() + "' AND " - + COLUMNS.X.name + " BETWEEN " + range.getXLow() + " AND " + range.getXHigh() - + " AND " + COLUMNS.Z.name + " BETWEEN " + range.getZLow() + " AND " + range.getZHigh() - + " ORDER BY RANDOM() LIMIT " + (QueueGenerator.queueMax + 1) - ); - /*ps.setString(1, COLUMNS.X.name); - ps.setInt(2, range.getXLow()); - ps.setInt(3, range.getXHigh()); - ps.setString(4, COLUMNS.Z.name); - ps.setInt(5, range.getZLow()); - ps.setInt(6, range.getZHigh());*/ - - //BetterRTP.getInstance().getLogger().info(ps.toString()); - rs = ps.executeQuery(); - while (rs.next()) { - long x = rs.getLong(COLUMNS.X.name); - long z = rs.getLong(COLUMNS.Z.name); - String worldName = rs.getString(COLUMNS.WORLD.name); - int id = rs.getInt(COLUMNS.ID.name); - long generated = rs.getLong(COLUMNS.GENERATED.name); - World world = Bukkit.getWorld(worldName); - if (world != null) { - queueDataList.add(new QueueData(new Location(world, x, 69 /*giggity*/, z), generated, id)); - //queueDataList.add(data); + SQLiteExecutor.EXECUTOR.submit(() -> { + Connection conn = null; + PreparedStatement ps = null; + ResultSet rs = null; + try { + conn = getSQLConnection(); + ps = conn.prepareStatement("SELECT * FROM " + tables.get(0) + " WHERE " + + COLUMNS.WORLD.name + " = '" + range.getWorld().getName() + "' AND " + + COLUMNS.X.name + " BETWEEN " + range.getXLow() + " AND " + range.getXHigh() + + " AND " + COLUMNS.Z.name + " BETWEEN " + range.getZLow() + " AND " + range.getZHigh() + + " ORDER BY RANDOM() LIMIT " + (QueueGenerator.queueMax + 1) + ); + rs = ps.executeQuery(); + while (rs.next()) { + long x = rs.getLong(COLUMNS.X.name); + long z = rs.getLong(COLUMNS.Z.name); + String worldName = rs.getString(COLUMNS.WORLD.name); + int id = rs.getInt(COLUMNS.ID.name); + long generated = rs.getLong(COLUMNS.GENERATED.name); + World world = Bukkit.getWorld(worldName); + if (world != null) { + queueDataList.add(new QueueData(new Location(world, x, 69, z), generated, id)); + } + } + } catch (SQLException ex) { + BetterRTP.getInstance().getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex); + } finally { + close(ps, rs, conn); } - } - } catch (SQLException ex) { - BetterRTP.getInstance().getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex); - } finally { - close(ps, rs, conn); + }).get(); + } catch (Exception ex) { + ex.printStackTrace(); } return queueDataList; } //Set a queue to save public QueueData addQueue(Location loc) { - String pre = "INSERT INTO "; - String sql = pre + tables.get(0) + " (" - + COLUMNS.X.name + ", " - + COLUMNS.Z.name + ", " - + COLUMNS.WORLD.name + ", " - + COLUMNS.GENERATED.name + " " - //+ COLUMNS.USES.name + " " - + ") VALUES(?, ?, ?, ?)"; - List params = new ArrayList() {{ - add(loc.getBlockX()); - add(loc.getBlockZ()); - add(loc.getWorld().getName()); - add(System.currentTimeMillis()); - //add(data.getUses()); - }}; - //return sqlUpdate(sql, params); - int database_id = createQueue(sql, params); - if (database_id >= 0) - return new QueueData(loc, System.currentTimeMillis(), database_id); - return null; - } - - public int getCount() { - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - int count = 0; try { - conn = getSQLConnection(); - ps = conn.prepareStatement("SELECT * FROM " + tables.get(0)); - - rs = ps.executeQuery(); - count = rs.getFetchSize(); - } catch (SQLException ex) { - BetterRTP.getInstance().getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex); - } finally { - close(ps, rs, conn); + return SQLiteExecutor.EXECUTOR.submit(() -> { + String sql = "INSERT INTO " + tables.get(0) + " (" + + COLUMNS.X.name + ", " + + COLUMNS.Z.name + ", " + + COLUMNS.WORLD.name + ", " + + COLUMNS.GENERATED.name + ") VALUES(?, ?, ?, ?)"; + List params = new ArrayList() {{ + add(loc.getBlockX()); + add(loc.getBlockZ()); + add(loc.getWorld().getName()); + add(System.currentTimeMillis()); + }}; + int database_id = createQueue(sql, params); + return database_id >= 0 ? new QueueData(loc, System.currentTimeMillis(), database_id) : null; + }).get(); + } catch (Exception ex) { + ex.printStackTrace(); + return null; } - return count; } private int createQueue(String statement, @NonNull List params) { @@ -195,24 +147,31 @@ public class DatabaseQueue extends SQLite { } public boolean removeLocation(Location loc) { - String sql = "DELETE FROM " + tables.get(0) + " WHERE " - + COLUMNS.X.name + " = ? AND " - + COLUMNS.Z.name + " = ? AND " - + COLUMNS.WORLD.name + " = ?" - ; - List params = new ArrayList() {{ - add(loc.getBlockX()); - add(loc.getBlockZ()); - add(loc.getWorld().getName()); - }}; - return sqlUpdate(sql, params); + try { + return SQLiteExecutor.EXECUTOR.submit(() -> { + String sql = "DELETE FROM " + tables.get(0) + " WHERE " + + COLUMNS.X.name + " = ? AND " + + COLUMNS.Z.name + " = ? AND " + + COLUMNS.WORLD.name + " = ?"; + List params = new ArrayList() {{ + add(loc.getBlockX()); + add(loc.getBlockZ()); + add(loc.getWorld().getName()); + }}; + return sqlUpdate(sql, params); + }).get(); + } catch (Exception ex) { + ex.printStackTrace(); + return false; + } } + @Getter public static class QueueRangeData { - @Getter int xLow, xHigh; - @Getter int zLow, zHigh; - @Getter World world; + int xLow, xHigh; + int zLow, zHigh; + World world; public QueueRangeData(RTPWorld rtpWorld) { this.xLow = rtpWorld.getCenterX() - rtpWorld.getMaxRadius(); @@ -221,6 +180,5 @@ public class DatabaseQueue extends SQLite { this.zHigh = rtpWorld.getCenterZ() + rtpWorld.getMaxRadius(); this.world = rtpWorld.getWorld(); } - } -} \ No newline at end of file +} diff --git a/src/main/java/me/SuperRonanCraft/BetterRTP/references/database/SQLiteExecutor.java b/src/main/java/me/SuperRonanCraft/BetterRTP/references/database/SQLiteExecutor.java new file mode 100644 index 0000000..aa3ad40 --- /dev/null +++ b/src/main/java/me/SuperRonanCraft/BetterRTP/references/database/SQLiteExecutor.java @@ -0,0 +1,8 @@ +package me.SuperRonanCraft.BetterRTP.references.database; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class SQLiteExecutor { + public static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor(); +} diff --git a/src/main/java/me/SuperRonanCraft/BetterRTP/references/depends/regionPlugins/RTP_WorldGuard.java b/src/main/java/me/SuperRonanCraft/BetterRTP/references/depends/regionPlugins/RTP_WorldGuard.java index 6c96139..bdf4345 100644 --- a/src/main/java/me/SuperRonanCraft/BetterRTP/references/depends/regionPlugins/RTP_WorldGuard.java +++ b/src/main/java/me/SuperRonanCraft/BetterRTP/references/depends/regionPlugins/RTP_WorldGuard.java @@ -19,9 +19,6 @@ public class RTP_WorldGuard implements RegionPluginCheck { RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer(); RegionQuery query = container.createQuery(); ApplicableRegionSet set = query.getApplicableRegions(BukkitAdapter.adapt(loc)); - //for (ProtectedRegion region : set.getRegions()) { - // region.getId() - //} result = set.size() == 0; } catch (Exception e) { e.printStackTrace(); diff --git a/src/main/java/me/SuperRonanCraft/BetterRTP/references/player/playerdata/PlayerData.java b/src/main/java/me/SuperRonanCraft/BetterRTP/references/player/playerdata/PlayerData.java index 49753e6..49aab58 100644 --- a/src/main/java/me/SuperRonanCraft/BetterRTP/references/player/playerdata/PlayerData.java +++ b/src/main/java/me/SuperRonanCraft/BetterRTP/references/player/playerdata/PlayerData.java @@ -1,6 +1,7 @@ package me.SuperRonanCraft.BetterRTP.references.player.playerdata; -import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.bukkit.World; import org.bukkit.entity.Player; @@ -16,7 +17,7 @@ public class PlayerData { //Menus @Getter final PlayerData_Menus menu = new PlayerData_Menus(); //Player Data - @Getter final HashMap cooldowns = new HashMap<>(); + @Getter final Map cooldowns = new ConcurrentHashMap<>(); //@Getter @Setter CooldownData globalCooldown; @Getter @Setter boolean rtping; @Getter @Setter int rtpCount; diff --git a/src/main/java/me/SuperRonanCraft/BetterRTP/references/player/playerdata/PlayerDataManager.java b/src/main/java/me/SuperRonanCraft/BetterRTP/references/player/playerdata/PlayerDataManager.java index 6d9f91d..5728079 100644 --- a/src/main/java/me/SuperRonanCraft/BetterRTP/references/player/playerdata/PlayerDataManager.java +++ b/src/main/java/me/SuperRonanCraft/BetterRTP/references/player/playerdata/PlayerDataManager.java @@ -4,25 +4,21 @@ import lombok.NonNull; import org.bukkit.entity.Player; import org.jetbrains.annotations.Nullable; -import java.util.HashMap; +import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; public class PlayerDataManager { - private final HashMap playerData = new HashMap<>(); + private final Map playerData = new ConcurrentHashMap<>(); public PlayerData getData(@NonNull Player p) { - if (!playerData.containsKey(p)) - playerData.put(p, new PlayerData(p)); - return playerData.get(p); + return playerData.computeIfAbsent(p.getUniqueId(), uuid -> new PlayerData(p)); } @Nullable public PlayerData getData(UUID id) { - for (Player p : playerData.keySet()) - if (p.getUniqueId().equals(id)) - return playerData.get(p); - return null; + return playerData.get(id); } public void clear() { @@ -30,6 +26,6 @@ public class PlayerDataManager { } public void clear(Player p) { - playerData.remove(p); + playerData.remove(p.getUniqueId()); } } diff --git a/src/main/java/me/SuperRonanCraft/BetterRTP/references/rtpinfo/CooldownHandler.java b/src/main/java/me/SuperRonanCraft/BetterRTP/references/rtpinfo/CooldownHandler.java index 1c66e40..33216ae 100644 --- a/src/main/java/me/SuperRonanCraft/BetterRTP/references/rtpinfo/CooldownHandler.java +++ b/src/main/java/me/SuperRonanCraft/BetterRTP/references/rtpinfo/CooldownHandler.java @@ -1,8 +1,8 @@ package me.SuperRonanCraft.BetterRTP.references.rtpinfo; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; import javax.annotation.Nullable; @@ -26,11 +26,9 @@ public class CooldownHandler { @Getter boolean enabled, loaded, cooldownByWorld; @Getter private int defaultCooldownTime; //Global Cooldown timer private int lockedAfter; //Rtp's before being locked - private final List downloading = new ArrayList<>(); - //private final DatabaseCooldownsGlobal globalCooldown = new DatabaseCooldownsGlobal(); + private final List downloading = new CopyOnWriteArrayList<>(); public void load() { - //configfile = new File(BetterRTP.getInstance().getDataFolder(), "data/cooldowns.yml"); FileOther.FILETYPE config = FileOther.FILETYPE.CONFIG; enabled = config.getBoolean("Settings.Cooldown.Enabled"); downloading.clear(); @@ -54,7 +52,6 @@ public class CooldownHandler { queueDownload(); return; } - //OldCooldownConverter.loadOldCooldowns(); //Load any online players cooldowns (mostly after a reload) for (Player p : Bukkit.getOnlinePlayers()) loadPlayer(p); @@ -66,7 +63,7 @@ public class CooldownHandler { if (!enabled) return; PlayerData playerData = getData(player); if (cooldownByWorld) { - HashMap cooldowns = playerData.getCooldowns(); + Map cooldowns = playerData.getCooldowns(); CooldownData data = cooldowns.getOrDefault(world, new CooldownData(player.getUniqueId(), 0L)); playerData.setRtpCount(playerData.getRtpCount() + 1); data.setTime(System.currentTimeMillis()); @@ -89,7 +86,7 @@ public class CooldownHandler { public CooldownData get(Player p, World world) { PlayerData data = getData(p); if (cooldownByWorld) { - HashMap cooldownData = getData(p).getCooldowns(); + Map cooldownData = getData(p).getCooldowns(); if (data != null) return cooldownData.getOrDefault(world, null); } else if (data.getGlobalCooldown() > 0) { @@ -101,8 +98,6 @@ public class CooldownHandler { public long timeLeft(CommandSender sendi, CooldownData data, WorldPlayer pWorld) { long cooldown = data.getTime(); long timeLeft = ((cooldown / 1000) + pWorld.getCooldown()) - (System.currentTimeMillis() / 1000); - //if (BetterRTP.getInstance().getSettings().isDelayEnabled() && !PermissionNode.BYPASS_DELAY.check(sendi)) - // timeLeft = timeLeft + BetterRTP.getInstance().getSettings().getDelayTime(); return timeLeft * 1000L; } @@ -116,7 +111,6 @@ public class CooldownHandler { CooldownData cooldownData = playerData.getCooldowns().getOrDefault(world, null); if (cooldownData != null) { if (lockedAfter > 0) { - //uses.put(id, uses.getOrDefault(id, 1) - 1); if (playerData.getRtpCount() <= 0) { //Remove from file as well savePlayer(player, world, cooldownData, true); getData(player).getCooldowns().put(world, null); @@ -146,19 +140,31 @@ public class CooldownHandler { } public void loadPlayer(Player player) { - if (!isEnabled()) return; - downloading.add(player); + if (!isEnabled()) { + return; + } + PlayerData playerData = getData(player); - if (getDatabaseWorlds() != null) //Per World enabled? - for (World world : Bukkit.getWorlds()) { - //Cooldowns - CooldownData cooldown = getDatabaseWorlds().getCooldown(player.getUniqueId(), world); - if (cooldown != null) - playerData.getCooldowns().put(world, cooldown); + if (playerData == null) { + return; + } + + downloading.add(player); + + try { + if (getDatabaseWorlds() != null) { //Per World enabled? + for (World world : Bukkit.getWorlds()) { + //Cooldowns + CooldownData cooldown = getDatabaseWorlds().getCooldown(player.getUniqueId(), world); + if (cooldown != null) + playerData.getCooldowns().put(world, cooldown); + } } - //Player Data - DatabaseHandler.getPlayers().setupData(playerData); - downloading.remove(player); + //Player Data + DatabaseHandler.getPlayers().setupData(playerData); + } finally { + downloading.remove(player); + } } public boolean loadedPlayer(Player player) { @@ -176,51 +182,3 @@ public class CooldownHandler { return HelperPlayer.getData(p); } } - -//Old yaml file based system, no longer useful as of 3.3.1 -/*@Deprecated - static class OldCooldownConverter { - - static void loadOldCooldowns() { - File file = new File(BetterRTP.getInstance().getDataFolder(), "data/cooldowns.yml"); - YamlConfiguration config = getFile(file); - if (config == null) return; - if (config.getBoolean("Converted")) return; - List cooldownData = new ArrayList<>(); - for (String id : config.getConfigurationSection("").getKeys(false)) { - try { - Long time = config.getLong(id + ".Time"); - UUID uuid = UUID.fromString(id); - int uses = config.getInt(id + ".Attempts"); - cooldownData.add(new CooldownData(uuid, time, uses)); - } catch (IllegalArgumentException e) { - //Invalid UUID - } - } - config.set("Converted", true); - try { - config.save(file); - } catch (IOException e) { - e.printStackTrace(); - } - BetterRTP.getInstance().getLogger().info("Cooldowns converting to new database..."); - Bukkit.getScheduler().runTaskAsynchronously(BetterRTP.getInstance(), () -> { - BetterRTP.getInstance().getDatabaseCooldowns().setCooldown(cooldownData); - BetterRTP.getInstance().getLogger().info("Cooldowns have been converted to the new database!"); - }); - } - - private static YamlConfiguration getFile(File configfile) { - if (!configfile.exists()) { - return null; - } - try { - YamlConfiguration config = new YamlConfiguration(); - config.load(configfile); - return config; - } catch (IOException | InvalidConfigurationException e) { - e.printStackTrace(); - } - return null; - } - }*/ diff --git a/src/main/java/me/SuperRonanCraft/BetterRTP/references/rtpinfo/RandomLocation.java b/src/main/java/me/SuperRonanCraft/BetterRTP/references/rtpinfo/RandomLocation.java index 9bf05db..1bb73f0 100644 --- a/src/main/java/me/SuperRonanCraft/BetterRTP/references/rtpinfo/RandomLocation.java +++ b/src/main/java/me/SuperRonanCraft/BetterRTP/references/rtpinfo/RandomLocation.java @@ -25,44 +25,32 @@ public class RandomLocation { } private static Location generateSquare(RTPWorld rtpWorld) { - //Generate a random X and Z based off the quadrant selected - int min = rtpWorld.getMinRadius(); - int max = rtpWorld.getMaxRadius() - min; - int x, z; - int quadrant = new Random().nextInt(4); + // Return a Location where a random X and Z are within the bounds defined by MinRadius and MaxRadius + int radius_min = rtpWorld.getMinRadius(); + int radius_max = rtpWorld.getMaxRadius(); try { - switch (quadrant) { - case 0: // Positive X and Z - x = new Random().nextInt(max) + min; - z = new Random().nextInt(max) + min; - break; - case 1: // Negative X and Z - x = -new Random().nextInt(max) - min; - z = -(new Random().nextInt(max) + min); - break; - case 2: // Negative X and Positive Z - x = -new Random().nextInt(max) - min; - z = new Random().nextInt(max) + min; - break; - default: // Positive X and Negative Z - x = new Random().nextInt(max) + min; - z = -(new Random().nextInt(max) + min); - break; + if (radius_min < 0 || radius_max < 0 || radius_min >= radius_max) { + throw new IllegalArgumentException(); // If MinRadius or MaxRadius is negative, throw an exception } } catch (IllegalArgumentException e) { e.printStackTrace(); - BetterRTP.getInstance().getLogger().warning("A bounding location was negative! Please check your config only has positive x/z for max/min radius!"); + BetterRTP.getInstance().getLogger().warning("Incorrect configuration! Check your config and confirm that MinRadius is smaller than MaxRadius and that they are both positive numbers!"); BetterRTP.getInstance().getLogger().warning("Max: " + rtpWorld.getMaxRadius() + " Min: " + rtpWorld.getMinRadius()); return null; } + // Generate a random X and Z based off the radius. No quadrants voodoo. + Random random = new Random(); + int x = random.nextInt(radius_max * 2) - radius_max; + int z = (Math.abs(x) >= radius_min) + ? random.nextInt(radius_max * 2) - radius_max + : (random.nextBoolean() ? 1 : -1) * (radius_min + random.nextInt(radius_max - radius_min)); x += rtpWorld.getCenterX(); z += rtpWorld.getCenterZ(); - //System.out.println(quadrant); return new Location(rtpWorld.getWorld(), x, 69, z); } private static Location generateRound(RTPWorld rtpWorld) { - //Generate a random X and Z based off location on a spiral curve + // Return a random X and Z based off location on a spiral curve int min = rtpWorld.getMinRadius(); int max = rtpWorld.getMaxRadius() - min; int x, z; diff --git a/src/main/java/me/SuperRonanCraft/BetterRTP/versions/AsyncHandler.java b/src/main/java/me/SuperRonanCraft/BetterRTP/versions/AsyncHandler.java index 992886d..29a3578 100644 --- a/src/main/java/me/SuperRonanCraft/BetterRTP/versions/AsyncHandler.java +++ b/src/main/java/me/SuperRonanCraft/BetterRTP/versions/AsyncHandler.java @@ -9,26 +9,21 @@ public class AsyncHandler { public static void async(Runnable runnable) { getFolia().runAsync(task -> runnable.run()); - //Bukkit.getScheduler().runTaskAsynchronously(BetterRTP.getInstance(), runnable); } public static void sync(Runnable runnable) { getFolia().runNextTick(task -> runnable.run()); - //Bukkit.getScheduler().runTask(BetterRTP.getInstance(), runnable); } public static void syncAtEntity(Entity entity, Runnable runnable) { getFolia().runAtEntity(entity, task -> runnable.run()); - //Bukkit.getScheduler().runTask(BetterRTP.getInstance(), runnable); } public static WrappedTask asyncLater(Runnable runnable, long ticks) { return getFolia().runLaterAsync(runnable, ticks); - //return Bukkit.getScheduler().runTaskLaterAsynchronously(BetterRTP.getInstance(), runnable, ticks); } public static WrappedTask syncLater(Runnable runnable, long ticks) { return getFolia().runLater(runnable, ticks); - //return Bukkit.getScheduler().runTaskLater(BetterRTP.getInstance(), runnable, ticks); } private static ServerImplementation getFolia() { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 6927a6f..5a35cd0 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -25,7 +25,7 @@ softdepend: - Multiverse-Core #Forcing Multiverse to load BEFORE BetterRTP - Essentials #adds `/back` support - PlaceholderAPI - - HuskClaims #fixed condition race which breaks hooking + - HuskClaims #Respect HuskClaims areas (https://www.spigotmc.org/resources/huskclaims-1-17-1-21-modern-golden-shovel-land-claiming-fully-cross-server-compatible.114467/) (fixes race condition that breaks hooking) api-version: '1.13' commands: