From 1d4561e70af67fda207e59a35f27c88c2297a2ac Mon Sep 17 00:00:00 2001 From: TurboJax Date: Sat, 7 Feb 2026 08:53:23 -0500 Subject: [PATCH 01/37] Adding the DataManager interface and removing the old DataManager --- .../java/com/catadmirer/infuseSMP/Infuse.java | 4 +- .../infuseSMP/playerdata/DataManager.java | 121 ++++++++++++++ .../YamlDataManager.java} | 151 +++++++++++++----- 3 files changed, 238 insertions(+), 38 deletions(-) create mode 100644 src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java rename src/main/java/com/catadmirer/infuseSMP/{managers/DataManager.java => playerdata/YamlDataManager.java} (50%) diff --git a/src/main/java/com/catadmirer/infuseSMP/Infuse.java b/src/main/java/com/catadmirer/infuseSMP/Infuse.java index 10a9109b..6073d1bc 100644 --- a/src/main/java/com/catadmirer/infuseSMP/Infuse.java +++ b/src/main/java/com/catadmirer/infuseSMP/Infuse.java @@ -7,6 +7,8 @@ import com.catadmirer.infuseSMP.managers.*; import com.catadmirer.infuseSMP.particles.Particles; import com.catadmirer.infuseSMP.placeholders.InfusePlaceholders; +import com.catadmirer.infuseSMP.playerdata.DataManager; +import com.catadmirer.infuseSMP.playerdata.YamlDataManager; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @@ -49,7 +51,7 @@ public class Infuse extends JavaPlugin implements Listener { public Infuse() { this.apophisManager = new ApophisManager(this); this.mainConfig = new MainConfig(this); - this.dataManager = new DataManager(this); + this.dataManager = new YamlDataManager(this); } public void onEnable() { diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java new file mode 100644 index 00000000..69dc6978 --- /dev/null +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java @@ -0,0 +1,121 @@ +package com.catadmirer.infuseSMP.playerdata; + +import com.catadmirer.infuseSMP.managers.EffectMapping; +import java.util.List; +import java.util.UUID; +import org.bukkit.OfflinePlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface DataManager { + /** + * Reloads the player data. + * + * @return True if the data was loaded successfully, false otherwise. + */ + public boolean load(); + + /** + * Writes the player data to disk. + * + * @return Whether or not the data was successfully written. + */ + public boolean save(); + + /** + * Creating the data file. If it doesn't exist, it just makes an empty file. + * + * @return True if the file was created successfully, false otherwise. + */ + public boolean createFile(); + + /** + * Gets a list of the players that the truster trusts. + * + * @param truster + * + * @return The list of players trusted by the truster. + */ + @NotNull + public List getTrusted(@NotNull OfflinePlayer truster); + + /** + * Sets the players that the truster trusts. + * + * @param truster The player to modify + * @param trusted The list of players the truster now trusts + */ + public void setTrusted(@NotNull OfflinePlayer truster, @NotNull List trusted); + + /** + * Adds a player to the list of trusted people. + * + * @param truster The person whose trusted list to modify. + * @param toTrust The person the truster now trusts. + */ + public void addTrust(@NotNull OfflinePlayer truster, @NotNull OfflinePlayer toTrust); + + /** + * Removes a player from another player's list of trusted people. + * + * @param truster The player whose trusted list to modify. + * @param toRemove The person to remove from the truster's trust. + */ + public void removeTrust(@NotNull OfflinePlayer truster, @NotNull OfflinePlayer toRemove); + + /** + * Checks if a player is trusted by another player. + * + * @param truster The player whose trusted list to check. + * @param toCheck The player to check if truster trusts. + * + * @return True if the truster trusts the toCheck player, false otherwise + */ + public boolean isTrusted(@NotNull OfflinePlayer truster, @NotNull OfflinePlayer toCheck); + + /** + * Sets the infuse effect in a specific slot for a player. + * + * @param playerUUID The UUID of the player. + * @param slot The slot to equip the effect in. + * @param effect The {@link EffectMapping} for the infuse effect. + */ + public void setEffect(@NotNull UUID playerUUID, @NotNull String slot, @NotNull EffectMapping effect); + + /** + * Gets the infuse effect a player has in a specific slot. + * + * @param playerUUID The UUID of the player. + * @param slot The slot to get the effect from. + * + * @return null if there is not an effect equipped there or if the EffectMapping could not be deserialized. Otherwise, it returns the deserialized EffectMapping. + */ + @Nullable + public EffectMapping getEffect(@NotNull UUID playerUUID, @NotNull String slot); + + /** + * Removes an infuse effect from a specific slot for a player. + * + * @param playerUUID The UUID of the player. + * @param slot The slot to remove an effect from. + */ + public void removeEffect(@NotNull UUID playerUUID, @NotNull String slot); + + /** + * Sets the control mode for a player. + * + * @param playerUUID The UUID of the player. + * @param defaultMode The new control mode to use. + */ + public void setControlMode(@NotNull UUID playerUUID, @NotNull String defaultMode); + + /** + * Gets the control mode of a player. + * + * @param playerUUID The UUID of the player. + * + * @return Either "command" or "offhand". Defaults to "offhand" + */ + @NotNull + public String getControlMode(@NotNull UUID playerUUID); +} \ No newline at end of file diff --git a/src/main/java/com/catadmirer/infuseSMP/managers/DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java similarity index 50% rename from src/main/java/com/catadmirer/infuseSMP/managers/DataManager.java rename to src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java index 6272d6b7..c11eb92e 100644 --- a/src/main/java/com/catadmirer/infuseSMP/managers/DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java @@ -1,33 +1,38 @@ -package com.catadmirer.infuseSMP.managers; +package com.catadmirer.infuseSMP.playerdata; -import com.catadmirer.infuseSMP.Infuse; import java.io.File; import java.io.IOException; import java.util.List; import java.util.UUID; import java.util.logging.Level; + import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class DataManager { +import com.catadmirer.infuseSMP.Infuse; +import com.catadmirer.infuseSMP.managers.EffectMapping; + +public class YamlDataManager implements DataManager { private final Infuse plugin; private final File dataFile; private final YamlConfiguration config; - public DataManager(Infuse plugin) { + public YamlDataManager(Infuse plugin) { this.plugin = plugin; this.dataFile = new File(plugin.getDataFolder(), "data/playerdata.yml"); this.config = YamlConfiguration.loadConfiguration(dataFile); } /** - * Reloads the configuration. + * Reloads the player data. * - * @return Whether the configuration was loaded successfully. + * @return True if the data was loaded successfully, false otherwise. */ + @Override public boolean load() { if (plugin == null) { Bukkit.getLogger().log(Level.SEVERE, "{0} not loaded, cannot load {1}.", new String[]{plugin.getName(), dataFile.getName()}); @@ -35,10 +40,7 @@ public boolean load() { } // Creating the file if it doesn't exist. - // If the function returns false, the load function fails too. - if (!createFile(false)) { - return false; - } + createFile(); // Loading the config try { @@ -55,10 +57,11 @@ public boolean load() { } /** - * Writes the config to the file. + * Writes the player data to disk. * - * @return Whether or not the config was successfully written. + * @return Whether or not the data was successfully written. */ + @Override public boolean save() { // Getting a plugin instance to use if (plugin == null) { @@ -67,10 +70,7 @@ public boolean save() { } // Creating the file if it doesn't exist. - // If the function returns false, the load function fails too. - if (!createFile(false)) { - return false; - } + createFile(); // Saving the config try { @@ -85,13 +85,12 @@ public boolean save() { } /** - * Creating the config file. If it doesn't exist, it loads the default config. If the file does - * exist, it will only replace it if the parameter is true. + * Creating the data file. If it doesn't exist, it just makes an empty file. * - * @param replace Whether or not to replace the config file with the default configs. - * @return Whether or not the file was created successfully. + * @return True if the file was created successfully, false otherwise. */ - public boolean createFile(boolean replace) { + @Override + public boolean createFile() { // Getting a plugin instance to use if (plugin == null) { Bukkit.getLogger().log(Level.SEVERE, "{0} not loaded, cannot create default {1}.", new String[]{plugin.getName(), dataFile.getName()}); @@ -112,38 +111,85 @@ public boolean createFile(boolean replace) { return true; } - public List getTrusted(Player truster) { - return config.getStringList(truster.getUniqueId() + ".trust").stream().map(UUID::fromString).map(Bukkit::getPlayer).toList(); + /** + * Gets a list of the players that the truster trusts. + * + * @param truster + * + * @return The list of players trusted by the truster. + */ + @Override + @NotNull + public List getTrusted(@NotNull OfflinePlayer truster) { + return config.getStringList(truster.getUniqueId() + ".trust").stream().map(UUID::fromString).map(Bukkit::getOfflinePlayer).toList(); } - public void setTrusted(Player truster, List trusted) { - config.set(truster.getUniqueId() + ".trust", trusted.stream().map(Player::getUniqueId).toList()); + /** + * Sets the players that the truster trusts. + * + * @param truster The player to modify + * @param trusted The list of players the truster now trusts + */ + @Override + public void setTrusted(@NotNull OfflinePlayer truster, @NotNull List trusted) { + config.set(truster.getUniqueId() + ".trust", trusted.stream().map(OfflinePlayer::getUniqueId).toList()); save(); } - public void addTrust(Player caster, Player toTrust) { - List trustedPlayers = getTrusted(caster); + /** + * Adds a player to the list of trusted people. + * + * @param truster The person whose trusted list to modify. + * @param toTrust The person the truster now trusts. + */ + @Override + public void addTrust(@NotNull OfflinePlayer caster, @NotNull OfflinePlayer toTrust) { + List trustedPlayers = getTrusted(caster); trustedPlayers.add(toTrust); setTrusted(caster, trustedPlayers); } - public void removeTrust(Player caster, Player trusted) { - List trustedSet = getTrusted(caster); + /** + * Removes a player from another player's list of trusted people. + * + * @param truster The player whose trusted list to modify. + * @param toRemove The person to remove from the truster's trust. + */ + @Override + public void removeTrust(@NotNull OfflinePlayer caster, @NotNull OfflinePlayer trusted) { + List trustedSet = getTrusted(caster); trustedSet.remove(trusted); setTrusted(caster, trustedSet); } - public boolean isTrusted(Player caster, Player trusted) { + /** + * Checks if a player is trusted by another player. + * + * @param truster The player whose trusted list to check. + * @param toCheck The player to check if truster trusts. + * + * @return True if the truster trusts the toCheck player, false otherwise + */ + @Override + public boolean isTrusted(@NotNull OfflinePlayer caster, @NotNull OfflinePlayer trusted) { if (caster == null || trusted == null) return false; if (caster.getUniqueId().equals(trusted.getUniqueId())) return true; return getTrusted(caster).contains(trusted); } - public void setEffect(UUID playerUUID, String slot, @Nullable EffectMapping effect) { + /** + * Sets the infuse effect in a specific slot for a player. + * + * @param playerUUID The UUID of the player. + * @param slot The slot to equip the effect in. + * @param effect The {@link EffectMapping} for the infuse effect. + */ + @Override + public void setEffect(@NotNull UUID playerUUID, @NotNull String slot, @NotNull EffectMapping effect) { if (effect == null) { config.set(playerUUID.toString() + "." + slot, null); } else { @@ -152,9 +198,17 @@ public void setEffect(UUID playerUUID, String slot, @Nullable EffectMapping effe save(); } - + /** + * Gets the infuse effect a player has in a specific slot. + * + * @param playerUUID The UUID of the player. + * @param slot The slot to get the effect from. + * + * @return null if there is not an effect equipped there or if the EffectMapping could not be deserialized. Otherwise, it returns the deserialized EffectMapping. + */ + @Override @Nullable - public EffectMapping getEffect(UUID playerUUID, String slot) { + public EffectMapping getEffect(@NotNull UUID playerUUID, @NotNull String slot) { String effectKey = config.getString(playerUUID.toString() + "." + slot, null); EffectMapping effect = EffectMapping.fromEffectKey(effectKey); if (effectKey != null && effect == null) { @@ -163,17 +217,40 @@ public EffectMapping getEffect(UUID playerUUID, String slot) { return effect; } - public void removeEffect(UUID playerUUID, String slot) { + /** + * Removes an infuse effect from a specific slot for a player. + * + * @param playerUUID The UUID of the player. + * @param slot The slot to remove an effect from. + */ + @Override + public void removeEffect(@NotNull UUID playerUUID, @NotNull String slot) { config.set(playerUUID.toString() + "." + slot, null); save(); } - public void setControlMode(UUID playerUUID, String defaultMode) { + /** + * Sets the control mode for a player. + * + * @param playerUUID The UUID of the player. + * @param defaultMode The new control mode to use. + */ + @Override + public void setControlMode(@NotNull UUID playerUUID, @NotNull String defaultMode) { config.set(playerUUID.toString() + ".controls", defaultMode); save(); } - public String getControlMode(UUID playerUUID) { + /** + * Gets the control mode of a player. + * + * @param playerUUID The UUID of the player. + * + * @return Either "command" or "offhand". Defaults to "offhand" + */ + @Override + @NotNull + public String getControlMode(@NotNull UUID playerUUID) { return config.getString(playerUUID.toString() + ".controls", "offhand"); } } \ No newline at end of file From 2cbb4c929264354a1b593f2ba1b55f180121cff4 Mon Sep 17 00:00:00 2001 From: duff_mans_jnr Date: Sun, 8 Feb 2026 20:42:22 +0000 Subject: [PATCH 02/37] More database implementation stuff... --- .../java/com/catadmirer/infuseSMP/playerdata/PlayerData.java | 4 ++++ .../catadmirer/infuseSMP/playerdata/databases/H2Database.java | 4 ++++ .../infuseSMP/playerdata/{ => databases}/YamlDataManager.java | 0 3 files changed, 8 insertions(+) create mode 100644 src/main/java/com/catadmirer/infuseSMP/playerdata/PlayerData.java create mode 100644 src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java rename src/main/java/com/catadmirer/infuseSMP/playerdata/{ => databases}/YamlDataManager.java (100%) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/PlayerData.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/PlayerData.java new file mode 100644 index 00000000..7c04408d --- /dev/null +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/PlayerData.java @@ -0,0 +1,4 @@ +package com.catadmirer.infuseSMP.playerdata; + +public class PlayerData { +} diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java new file mode 100644 index 00000000..554b4e28 --- /dev/null +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java @@ -0,0 +1,4 @@ +package com.catadmirer.infuseSMP.playerdata.databases; + +public class H2Database { +} diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java similarity index 100% rename from src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java rename to src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java From 06f37c340c72babf8e8e7ed65c95a1254a0eaa14 Mon Sep 17 00:00:00 2001 From: turbojax07 Date: Sun, 8 Feb 2026 23:30:27 -0500 Subject: [PATCH 03/37] Fixing compilation errors regarding the locations of classes --- src/main/java/com/catadmirer/infuseSMP/Infuse.java | 2 +- .../com/catadmirer/infuseSMP/PlayerSwapHandItemsListener.java | 2 +- .../java/com/catadmirer/infuseSMP/commands/ClearEffect.java | 2 +- .../java/com/catadmirer/infuseSMP/commands/TrustCommand.java | 2 +- src/main/java/com/catadmirer/infuseSMP/effects/Ender.java | 2 +- src/main/java/com/catadmirer/infuseSMP/effects/Feather.java | 2 +- src/main/java/com/catadmirer/infuseSMP/effects/Frost.java | 2 +- src/main/java/com/catadmirer/infuseSMP/effects/Ocean.java | 2 +- .../java/com/catadmirer/infuseSMP/managers/EffectMapping.java | 1 + .../infuseSMP/playerdata/databases/YamlDataManager.java | 3 ++- 10 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/Infuse.java b/src/main/java/com/catadmirer/infuseSMP/Infuse.java index 6073d1bc..1fa6d657 100644 --- a/src/main/java/com/catadmirer/infuseSMP/Infuse.java +++ b/src/main/java/com/catadmirer/infuseSMP/Infuse.java @@ -8,7 +8,7 @@ import com.catadmirer.infuseSMP.particles.Particles; import com.catadmirer.infuseSMP.placeholders.InfusePlaceholders; import com.catadmirer.infuseSMP.playerdata.DataManager; -import com.catadmirer.infuseSMP.playerdata.YamlDataManager; +import com.catadmirer.infuseSMP.playerdata.databases.YamlDataManager; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; diff --git a/src/main/java/com/catadmirer/infuseSMP/PlayerSwapHandItemsListener.java b/src/main/java/com/catadmirer/infuseSMP/PlayerSwapHandItemsListener.java index 89b801d3..66822326 100644 --- a/src/main/java/com/catadmirer/infuseSMP/PlayerSwapHandItemsListener.java +++ b/src/main/java/com/catadmirer/infuseSMP/PlayerSwapHandItemsListener.java @@ -1,7 +1,7 @@ package com.catadmirer.infuseSMP; import com.catadmirer.infuseSMP.managers.CooldownManager; -import com.catadmirer.infuseSMP.managers.DataManager; +import com.catadmirer.infuseSMP.playerdata.DataManager; import com.catadmirer.infuseSMP.managers.EffectMapping; import java.util.UUID; import org.bukkit.entity.Player; diff --git a/src/main/java/com/catadmirer/infuseSMP/commands/ClearEffect.java b/src/main/java/com/catadmirer/infuseSMP/commands/ClearEffect.java index 167fe1ab..90c6764f 100644 --- a/src/main/java/com/catadmirer/infuseSMP/commands/ClearEffect.java +++ b/src/main/java/com/catadmirer/infuseSMP/commands/ClearEffect.java @@ -1,7 +1,7 @@ package com.catadmirer.infuseSMP.commands; import com.catadmirer.infuseSMP.Messages; -import com.catadmirer.infuseSMP.managers.DataManager; +import com.catadmirer.infuseSMP.playerdata.DataManager; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; diff --git a/src/main/java/com/catadmirer/infuseSMP/commands/TrustCommand.java b/src/main/java/com/catadmirer/infuseSMP/commands/TrustCommand.java index 2f336ae9..d9f8d89f 100644 --- a/src/main/java/com/catadmirer/infuseSMP/commands/TrustCommand.java +++ b/src/main/java/com/catadmirer/infuseSMP/commands/TrustCommand.java @@ -1,7 +1,7 @@ package com.catadmirer.infuseSMP.commands; import com.catadmirer.infuseSMP.Messages; -import com.catadmirer.infuseSMP.managers.DataManager; +import com.catadmirer.infuseSMP.playerdata.DataManager; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; diff --git a/src/main/java/com/catadmirer/infuseSMP/effects/Ender.java b/src/main/java/com/catadmirer/infuseSMP/effects/Ender.java index eeba3ded..621999fd 100644 --- a/src/main/java/com/catadmirer/infuseSMP/effects/Ender.java +++ b/src/main/java/com/catadmirer/infuseSMP/effects/Ender.java @@ -2,7 +2,7 @@ import com.catadmirer.infuseSMP.Infuse; import com.catadmirer.infuseSMP.managers.CooldownManager; -import com.catadmirer.infuseSMP.managers.DataManager; +import com.catadmirer.infuseSMP.playerdata.DataManager; import com.catadmirer.infuseSMP.managers.EffectMapping; import net.kyori.adventure.text.Component; import java.util.Collection; diff --git a/src/main/java/com/catadmirer/infuseSMP/effects/Feather.java b/src/main/java/com/catadmirer/infuseSMP/effects/Feather.java index fc2f712b..625f5818 100644 --- a/src/main/java/com/catadmirer/infuseSMP/effects/Feather.java +++ b/src/main/java/com/catadmirer/infuseSMP/effects/Feather.java @@ -2,7 +2,7 @@ import com.catadmirer.infuseSMP.Infuse; import com.catadmirer.infuseSMP.managers.CooldownManager; -import com.catadmirer.infuseSMP.managers.DataManager; +import com.catadmirer.infuseSMP.playerdata.DataManager; import com.catadmirer.infuseSMP.managers.EffectMapping; import com.catadmirer.infuseSMP.particles.Particles; import java.util.HashMap; diff --git a/src/main/java/com/catadmirer/infuseSMP/effects/Frost.java b/src/main/java/com/catadmirer/infuseSMP/effects/Frost.java index e324deae..fbfcdedc 100644 --- a/src/main/java/com/catadmirer/infuseSMP/effects/Frost.java +++ b/src/main/java/com/catadmirer/infuseSMP/effects/Frost.java @@ -2,7 +2,7 @@ import com.catadmirer.infuseSMP.Infuse; import com.catadmirer.infuseSMP.managers.CooldownManager; -import com.catadmirer.infuseSMP.managers.DataManager; +import com.catadmirer.infuseSMP.playerdata.DataManager; import com.catadmirer.infuseSMP.managers.EffectMapping; import java.util.EnumSet; import java.util.HashMap; diff --git a/src/main/java/com/catadmirer/infuseSMP/effects/Ocean.java b/src/main/java/com/catadmirer/infuseSMP/effects/Ocean.java index 36490f9c..24ff977c 100644 --- a/src/main/java/com/catadmirer/infuseSMP/effects/Ocean.java +++ b/src/main/java/com/catadmirer/infuseSMP/effects/Ocean.java @@ -3,7 +3,7 @@ import com.catadmirer.infuseSMP.Infuse; import com.catadmirer.infuseSMP.Messages; import com.catadmirer.infuseSMP.managers.CooldownManager; -import com.catadmirer.infuseSMP.managers.DataManager; +import com.catadmirer.infuseSMP.playerdata.DataManager; import java.util.UUID; import org.bukkit.Bukkit; import com.catadmirer.infuseSMP.managers.EffectMapping; diff --git a/src/main/java/com/catadmirer/infuseSMP/managers/EffectMapping.java b/src/main/java/com/catadmirer/infuseSMP/managers/EffectMapping.java index 0c904b63..60b2b8e1 100644 --- a/src/main/java/com/catadmirer/infuseSMP/managers/EffectMapping.java +++ b/src/main/java/com/catadmirer/infuseSMP/managers/EffectMapping.java @@ -2,6 +2,7 @@ import com.catadmirer.infuseSMP.effects.*; import com.catadmirer.infuseSMP.extraeffects.*; +import com.catadmirer.infuseSMP.playerdata.DataManager; import com.catadmirer.infuseSMP.Infuse; import com.catadmirer.infuseSMP.Messages; import java.awt.Color; diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java index c11eb92e..f1abef1f 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java @@ -1,4 +1,4 @@ -package com.catadmirer.infuseSMP.playerdata; +package com.catadmirer.infuseSMP.playerdata.databases; import java.io.File; import java.io.IOException; @@ -15,6 +15,7 @@ import com.catadmirer.infuseSMP.Infuse; import com.catadmirer.infuseSMP.managers.EffectMapping; +import com.catadmirer.infuseSMP.playerdata.DataManager; public class YamlDataManager implements DataManager { private final Infuse plugin; From b8461523eb9c17728e09c65969ed5494213cd135 Mon Sep 17 00:00:00 2001 From: turbojax07 Date: Mon, 16 Feb 2026 18:58:56 -0500 Subject: [PATCH 04/37] renaming DataManager#createFile to runSetup --- .../com/catadmirer/infuseSMP/playerdata/DataManager.java | 2 +- .../infuseSMP/playerdata/databases/YamlDataManager.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java index 16b7ef18..a1f32134 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java @@ -27,7 +27,7 @@ public interface DataManager { * * @return True if the file was created successfully, false otherwise. */ - public boolean createFile(); + public boolean runSetup(); /** * Gets a list of the players that the truster trusts. diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java index 176886fc..1f043faa 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java @@ -41,7 +41,7 @@ public boolean load() { } // Creating the file if it doesn't exist. - createFile(); + runSetup(); // Loading the config try { @@ -71,7 +71,7 @@ public boolean save() { } // Creating the file if it doesn't exist. - createFile(); + runSetup(); // Saving the config try { @@ -91,7 +91,7 @@ public boolean save() { * @return True if the file was created successfully, false otherwise. */ @Override - public boolean createFile() { + public boolean runSetup() { // Getting a plugin instance to use if (plugin == null) { Bukkit.getLogger().log(Level.SEVERE, "{0} not loaded, cannot create default {1}.", new String[]{plugin.getName(), dataFile.getName()}); From aff8730b9a667dc94e80d8183b0058ec4f9fd272 Mon Sep 17 00:00:00 2001 From: turbojax07 Date: Mon, 16 Feb 2026 19:03:39 -0500 Subject: [PATCH 05/37] Removing runSetup and save from DataManager because they aren't needed for sql. They will stay as members of YamlDataManager --- .../infuseSMP/playerdata/DataManager.java | 14 -------------- .../playerdata/databases/YamlDataManager.java | 8 +++----- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java index a1f32134..7fdefb22 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java @@ -15,20 +15,6 @@ public interface DataManager { */ public boolean load(); - /** - * Writes the player data to disk. - * - * @return Whether or not the data was successfully written. - */ - public boolean save(); - - /** - * Creating the data file. If it doesn't exist, it just makes an empty file. - * - * @return True if the file was created successfully, false otherwise. - */ - public boolean runSetup(); - /** * Gets a list of the players that the truster trusts. * diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java index 1f043faa..74550836 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java @@ -41,7 +41,7 @@ public boolean load() { } // Creating the file if it doesn't exist. - runSetup(); + createFile(); // Loading the config try { @@ -62,7 +62,6 @@ public boolean load() { * * @return Whether or not the data was successfully written. */ - @Override public boolean save() { // Getting a plugin instance to use if (plugin == null) { @@ -71,7 +70,7 @@ public boolean save() { } // Creating the file if it doesn't exist. - runSetup(); + createFile(); // Saving the config try { @@ -90,8 +89,7 @@ public boolean save() { * * @return True if the file was created successfully, false otherwise. */ - @Override - public boolean runSetup() { + public boolean createFile() { // Getting a plugin instance to use if (plugin == null) { Bukkit.getLogger().log(Level.SEVERE, "{0} not loaded, cannot create default {1}.", new String[]{plugin.getName(), dataFile.getName()}); From ff3efc144b968f4042d705a339c5dc27bf173725 Mon Sep 17 00:00:00 2001 From: turbojax07 Date: Mon, 16 Feb 2026 19:05:07 -0500 Subject: [PATCH 06/37] Making H2Database implement DataManager and implementing DataManager#load --- .../playerdata/databases/H2Database.java | 138 +++++++++++++++++- 1 file changed, 137 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java index 554b4e28..00f2cc1a 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java @@ -1,4 +1,140 @@ package com.catadmirer.infuseSMP.playerdata.databases; -public class H2Database { +import com.catadmirer.infuseSMP.Infuse; +import com.catadmirer.infuseSMP.managers.EffectMapping; +import com.catadmirer.infuseSMP.playerdata.DataManager; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; +import java.util.UUID; +import java.util.logging.Level; +import javax.sql.DataSource; +import org.bukkit.OfflinePlayer; +import org.h2.jdbcx.JdbcDataSource; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class H2Database implements DataManager { + private final Infuse plugin; + private final DataSource dataSource; + + public H2Database(Infuse plugin) { + this.plugin = plugin; + + try { + Class.forName("org.h2.Driver"); + } catch (ClassNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + // Creating the JDBC DataSource object + JdbcDataSource dataSource = new JdbcDataSource(); + dataSource.setUrl("jdbc:h2:./" + plugin.getDataFolder().getPath() + "/data/playerdata"); + dataSource.setUser("infuse"); + dataSource.setPassword(""); + dataSource.setDescription("Infuse Playerdata Storage"); + + this.dataSource = dataSource; + } + + @Override + public boolean load() { + final String createPlayerDataDb = "CREATE TABLE IF NOT EXISTS player_data(player UUID PRIMARY KEY, slot_1 INTEGER NOT NULL, slot_2 INTEGER NOT NULL, offhand_control BOOLEAN NOT NULL);"; + final String createTrustDb = "CREATE TABLE IF NOT EXISTS trusts(truster UUID NOT NULL, trusted UUID NOT NULL);"; + + try(Connection conn = dataSource.getConnection()) { + // Creating the tables if they dont exist + try (PreparedStatement stmt = conn.prepareStatement(createPlayerDataDb)) { + stmt.execute(); + } catch (SQLException err) { + plugin.getLogger().log(Level.WARNING, "Could not create the player_data table.", err); + } + + try (PreparedStatement stmt = conn.prepareStatement(createTrustDb)) { + stmt.execute(); + } catch (SQLException err) { + plugin.getLogger().log(Level.WARNING, "Could not create the trusts table.", err); + } + + conn.commit(); + return true; + } catch (SQLException err) { + plugin.getLogger().log(Level.SEVERE, "Could not open connection to H2 database", err); + } + + return false; + } + + public boolean save() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'save'"); + } + + @Override + public @NotNull List getTrusted(@NotNull OfflinePlayer truster) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getTrusted'"); + } + + @Override + public void setTrusted(@NotNull OfflinePlayer truster, @NotNull List trusted) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'setTrusted'"); + } + + @Override + public void addTrust(@NotNull OfflinePlayer truster, @NotNull OfflinePlayer toTrust) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'addTrust'"); + } + + @Override + public void removeTrust(@NotNull OfflinePlayer truster, @NotNull OfflinePlayer toRemove) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'removeTrust'"); + } + + @Override + public boolean isTrusted(@NotNull OfflinePlayer truster, @NotNull OfflinePlayer toCheck) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'isTrusted'"); + } + + @Override + public void setEffect(@NotNull UUID playerUUID, @NotNull String slot, @NotNull EffectMapping effect) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'setEffect'"); + } + + @Override + public @Nullable EffectMapping getEffect(@NotNull UUID playerUUID, @NotNull String slot) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getEffect'"); + } + + @Override + public boolean hasEffect(OfflinePlayer player, EffectMapping effect, boolean differentiateAugmented, String slot) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'hasEffect'"); + } + + @Override + public void removeEffect(@NotNull UUID playerUUID, @NotNull String slot) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'removeEffect'"); + } + + @Override + public void setControlMode(@NotNull UUID playerUUID, @NotNull String defaultMode) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'setControlMode'"); + } + + @Override + public @NotNull String getControlMode(@NotNull UUID playerUUID) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getControlMode'"); + } } From 7dc4f57c4c4b6a27e017c09c53c3a66dd1f5a1fc Mon Sep 17 00:00:00 2001 From: turbojax07 Date: Mon, 16 Feb 2026 19:05:39 -0500 Subject: [PATCH 07/37] Adding H2 as a dependency for the project --- build.gradle | 3 ++- gradle.properties | 3 ++- src/main/resources/plugin.yml | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 0d355677..3c6c198f 100644 --- a/build.gradle +++ b/build.gradle @@ -19,6 +19,7 @@ repositories { dependencies { compileOnly "io.papermc.paper:paper-api:${minecraftVersion}-R0.1-SNAPSHOT" compileOnly "me.clip:placeholderapi:${placeholderAPIVersion}" + compileOnly "com.h2database:h2:${h2Version}" } tasks { @@ -46,7 +47,7 @@ tasks.withType(JavaCompile).configureEach { } processResources { - def props = [version: version, mcVersion: minecraftVersion] + def props = [version: version, h2Version: h2Version, mcVersion: minecraftVersion] inputs.properties props filteringCharset = 'UTF-8' filesMatching('plugin.yml') { diff --git a/gradle.properties b/gradle.properties index c1817c4a..d58a84cb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,3 @@ minecraftVersion=1.21.4 -placeholderAPIVersion=2.11.6 \ No newline at end of file +placeholderAPIVersion=2.11.6 +h2Version=2.1.214 \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c7622a77..e99c8ebb 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -4,6 +4,9 @@ main: com.catadmirer.infuseSMP.Infuse api-version: '1.21.4' authors: [CatAdmirer, TurboJax] softdepend: [PlaceholderAPI] +libraries: +- com.h2database:h2:$h2Version + commands: infuse: description: Base command for Infuse From 8b146a1e085645bd9393f229efd142f974137412 Mon Sep 17 00:00:00 2001 From: turbojax07 Date: Mon, 16 Feb 2026 19:06:01 -0500 Subject: [PATCH 08/37] Removing save from H2Database --- .../infuseSMP/playerdata/databases/H2Database.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java index 00f2cc1a..71d03be5 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java @@ -57,7 +57,7 @@ public boolean load() { } catch (SQLException err) { plugin.getLogger().log(Level.WARNING, "Could not create the trusts table.", err); } - + conn.commit(); return true; } catch (SQLException err) { @@ -67,11 +67,6 @@ public boolean load() { return false; } - public boolean save() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'save'"); - } - @Override public @NotNull List getTrusted(@NotNull OfflinePlayer truster) { // TODO Auto-generated method stub From 5f1ea5b9a088cf9be127406e6e111f53efece840 Mon Sep 17 00:00:00 2001 From: turbojax07 Date: Tue, 17 Feb 2026 23:03:00 -0500 Subject: [PATCH 09/37] Making the trust getters and setters use Sets instead of Lists. --- .../infuseSMP/playerdata/DataManager.java | 8 +++---- .../playerdata/databases/H2Database.java | 5 +++-- .../playerdata/databases/YamlDataManager.java | 21 +++++++++---------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java index 7fdefb22..4ba2f4ab 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java @@ -1,7 +1,7 @@ package com.catadmirer.infuseSMP.playerdata; import com.catadmirer.infuseSMP.managers.EffectMapping; -import java.util.List; +import java.util.Set; import java.util.UUID; import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; @@ -23,15 +23,15 @@ public interface DataManager { * @return The list of players trusted by the truster. */ @NotNull - public List getTrusted(@NotNull OfflinePlayer truster); + public Set getTrusted(@NotNull OfflinePlayer truster); /** * Sets the players that the truster trusts. * * @param truster The player to modify - * @param trusted The list of players the truster now trusts + * @param trusted The set of players the truster now trusts */ - public void setTrusted(@NotNull OfflinePlayer truster, @NotNull List trusted); + public void setTrusted(@NotNull OfflinePlayer truster, @NotNull Set trusted); /** * Adds a player to the list of trusted people. diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java index 71d03be5..b8bc2ead 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java @@ -7,6 +7,7 @@ import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; +import java.util.HashSet; import java.util.UUID; import java.util.logging.Level; import javax.sql.DataSource; @@ -68,13 +69,13 @@ public boolean load() { } @Override - public @NotNull List getTrusted(@NotNull OfflinePlayer truster) { + public @NotNull Set getTrusted(@NotNull OfflinePlayer truster) { // TODO Auto-generated method stub throw new UnsupportedOperationException("Unimplemented method 'getTrusted'"); } @Override - public void setTrusted(@NotNull OfflinePlayer truster, @NotNull List trusted) { + public void setTrusted(@NotNull OfflinePlayer truster, @NotNull Set trusted) { // TODO Auto-generated method stub throw new UnsupportedOperationException("Unimplemented method 'setTrusted'"); } diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java index 74550836..5cd1d437 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java @@ -1,11 +1,14 @@ package com.catadmirer.infuseSMP.playerdata.databases; +import com.catadmirer.infuseSMP.Infuse; +import com.catadmirer.infuseSMP.managers.EffectMapping; +import com.catadmirer.infuseSMP.playerdata.DataManager; import java.io.File; import java.io.IOException; -import java.util.List; +import java.util.Set; import java.util.UUID; import java.util.logging.Level; - +import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.configuration.InvalidConfigurationException; @@ -13,10 +16,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.catadmirer.infuseSMP.Infuse; -import com.catadmirer.infuseSMP.managers.EffectMapping; -import com.catadmirer.infuseSMP.playerdata.DataManager; - public class YamlDataManager implements DataManager { private final Infuse plugin; private final File dataFile; @@ -119,8 +118,8 @@ public boolean createFile() { */ @Override @NotNull - public List getTrusted(@NotNull OfflinePlayer truster) { - return config.getStringList(truster.getUniqueId() + ".trust").stream().map(UUID::fromString).map(Bukkit::getOfflinePlayer).toList(); + public Set getTrusted(@NotNull OfflinePlayer truster) { + return config.getStringList(truster.getUniqueId() + ".trust").stream().map(UUID::fromString).map(Bukkit::getOfflinePlayer).collect(Collectors.toSet()); } /** @@ -130,7 +129,7 @@ public List getTrusted(@NotNull OfflinePlayer truster) { * @param trusted The list of players the truster now trusts */ @Override - public void setTrusted(@NotNull OfflinePlayer truster, @NotNull List trusted) { + public void setTrusted(@NotNull OfflinePlayer truster, @NotNull Set trusted) { config.set(truster.getUniqueId() + ".trust", trusted.stream().map(OfflinePlayer::getUniqueId).toList()); save(); @@ -144,7 +143,7 @@ public void setTrusted(@NotNull OfflinePlayer truster, @NotNull List trustedPlayers = getTrusted(caster); + Set trustedPlayers = getTrusted(caster); trustedPlayers.add(toTrust); setTrusted(caster, trustedPlayers); @@ -158,7 +157,7 @@ public void addTrust(@NotNull OfflinePlayer caster, @NotNull OfflinePlayer toTru */ @Override public void removeTrust(@NotNull OfflinePlayer caster, @NotNull OfflinePlayer trusted) { - List trustedSet = getTrusted(caster); + Set trustedSet = getTrusted(caster); trustedSet.remove(trusted); setTrusted(caster, trustedSet); From ad0b831512f0690202d86b0d63bacd73b1e97a65 Mon Sep 17 00:00:00 2001 From: turbojax07 Date: Tue, 17 Feb 2026 23:09:37 -0500 Subject: [PATCH 10/37] Using a SLF4J logger specific to the H2Database instance. Also removing some redundant try catch statements --- .../playerdata/databases/H2Database.java | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java index b8bc2ead..3d1992eb 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java @@ -6,8 +6,8 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.util.List; import java.util.HashSet; +import java.util.Set; import java.util.UUID; import java.util.logging.Level; import javax.sql.DataSource; @@ -15,22 +15,21 @@ import org.h2.jdbcx.JdbcDataSource; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class H2Database implements DataManager { - private final Infuse plugin; + private static final Logger LOGGER = LoggerFactory.getLogger("Infuse_Storage"); private final DataSource dataSource; public H2Database(Infuse plugin) { - this.plugin = plugin; - try { Class.forName("org.h2.Driver"); - } catch (ClassNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + } catch (ClassNotFoundException err) { + LOGGER.error("Could not load the H2 driver", err); } - // Creating the JDBC DataSource object + // Creating the JDBC DataSource JdbcDataSource dataSource = new JdbcDataSource(); dataSource.setUrl("jdbc:h2:./" + plugin.getDataFolder().getPath() + "/data/playerdata"); dataSource.setUser("infuse"); @@ -45,24 +44,21 @@ public boolean load() { final String createPlayerDataDb = "CREATE TABLE IF NOT EXISTS player_data(player UUID PRIMARY KEY, slot_1 INTEGER NOT NULL, slot_2 INTEGER NOT NULL, offhand_control BOOLEAN NOT NULL);"; final String createTrustDb = "CREATE TABLE IF NOT EXISTS trusts(truster UUID NOT NULL, trusted UUID NOT NULL);"; - try(Connection conn = dataSource.getConnection()) { + try (Connection conn = dataSource.getConnection()) { // Creating the tables if they dont exist - try (PreparedStatement stmt = conn.prepareStatement(createPlayerDataDb)) { - stmt.execute(); - } catch (SQLException err) { - plugin.getLogger().log(Level.WARNING, "Could not create the player_data table.", err); - } - - try (PreparedStatement stmt = conn.prepareStatement(createTrustDb)) { - stmt.execute(); - } catch (SQLException err) { - plugin.getLogger().log(Level.WARNING, "Could not create the trusts table.", err); - } + PreparedStatement stmt = conn.prepareStatement(createPlayerDataDb); + stmt.execute(); + stmt.close(); + + stmt = conn.prepareStatement(createTrustDb); + stmt.execute(); + stmt.close(); + // Commiting any changes conn.commit(); return true; } catch (SQLException err) { - plugin.getLogger().log(Level.SEVERE, "Could not open connection to H2 database", err); + LOGGER.error("Could not open connection to H2 database", err); } return false; From 7d30a1467441a81d0d3b0a80487ea1f3936a751f Mon Sep 17 00:00:00 2001 From: turbojax07 Date: Tue, 17 Feb 2026 23:10:05 -0500 Subject: [PATCH 11/37] Implementing H2Database#getTrusted --- .../playerdata/databases/H2Database.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java index 3d1992eb..2ef66be7 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java @@ -5,12 +5,14 @@ import com.catadmirer.infuseSMP.playerdata.DataManager; import java.sql.Connection; import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashSet; import java.util.Set; import java.util.UUID; -import java.util.logging.Level; +import java.util.stream.Collectors; import javax.sql.DataSource; +import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.h2.jdbcx.JdbcDataSource; import org.jetbrains.annotations.NotNull; @@ -66,8 +68,27 @@ public boolean load() { @Override public @NotNull Set getTrusted(@NotNull OfflinePlayer truster) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getTrusted'"); + UUID trusterUUID = truster.getUniqueId(); + + try (Connection conn = dataSource.getConnection()) { + PreparedStatement stmt = conn.prepareStatement("SELECT trusted FROM trusts WHERE truster = ?"); + stmt.setObject(1, trusterUUID); + + Set trustedUUIDs = new HashSet<>(); + ResultSet result = stmt.executeQuery(); + while (result.next()) { + try { + trustedUUIDs.add(result.getObject(1, UUID.class)); + } catch (SQLException err) { + LOGGER.warn("Invalid UUID in SQL results. Skipping value."); + } + } + + return trustedUUIDs.stream().map(Bukkit::getOfflinePlayer).collect(Collectors.toSet()); + } catch (SQLException err) { + + } + return null; } @Override From 7f24dcca9543b42cbbb165781655c721946dc7f4 Mon Sep 17 00:00:00 2001 From: turbojax07 Date: Wed, 18 Feb 2026 10:33:47 -0500 Subject: [PATCH 12/37] Moving the DataManager implementations out of that database folder --- src/main/java/com/catadmirer/infuseSMP/Infuse.java | 2 +- .../{databases/H2Database.java => H2DataManager.java} | 8 ++++---- .../playerdata/{databases => }/YamlDataManager.java | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) rename src/main/java/com/catadmirer/infuseSMP/playerdata/{databases/H2Database.java => H2DataManager.java} (96%) rename src/main/java/com/catadmirer/infuseSMP/playerdata/{databases => }/YamlDataManager.java (98%) diff --git a/src/main/java/com/catadmirer/infuseSMP/Infuse.java b/src/main/java/com/catadmirer/infuseSMP/Infuse.java index eb784c7e..e641b523 100644 --- a/src/main/java/com/catadmirer/infuseSMP/Infuse.java +++ b/src/main/java/com/catadmirer/infuseSMP/Infuse.java @@ -8,7 +8,7 @@ import com.catadmirer.infuseSMP.particles.Particles; import com.catadmirer.infuseSMP.placeholders.InfusePlaceholders; import com.catadmirer.infuseSMP.playerdata.DataManager; -import com.catadmirer.infuseSMP.playerdata.databases.YamlDataManager; +import com.catadmirer.infuseSMP.playerdata.YamlDataManager; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java similarity index 96% rename from src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java rename to src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java index 5b9a0bf5..5eda8bd5 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/H2Database.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java @@ -1,8 +1,8 @@ -package com.catadmirer.infuseSMP.playerdata.databases; +package com.catadmirer.infuseSMP.playerdata; import com.catadmirer.infuseSMP.Infuse; import com.catadmirer.infuseSMP.managers.EffectMapping; -import com.catadmirer.infuseSMP.playerdata.DataManager; + import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -21,11 +21,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class H2Database implements DataManager { +public class H2DataManager implements DataManager { private static final Logger LOGGER = LoggerFactory.getLogger("Infuse_Storage"); private final DataSource dataSource; - public H2Database(Infuse plugin) { + public H2DataManager(Infuse plugin) { try { Class.forName("org.h2.Driver"); } catch (ClassNotFoundException err) { diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java similarity index 98% rename from src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java rename to src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java index 0f19f48d..165f1c03 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/databases/YamlDataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java @@ -1,8 +1,8 @@ -package com.catadmirer.infuseSMP.playerdata.databases; +package com.catadmirer.infuseSMP.playerdata; import com.catadmirer.infuseSMP.Infuse; import com.catadmirer.infuseSMP.managers.EffectMapping; -import com.catadmirer.infuseSMP.playerdata.DataManager; + import java.io.File; import java.io.IOException; import java.util.Set; From b3e0f5baac6c496ae15dfc22bdc40142e8ff36c9 Mon Sep 17 00:00:00 2001 From: turbojax07 Date: Wed, 18 Feb 2026 10:50:46 -0500 Subject: [PATCH 13/37] Adding default implementations for DataManager#addTrust and DataManager#removeTrust. --- .../infuseSMP/playerdata/DataManager.java | 12 ++++++-- .../infuseSMP/playerdata/YamlDataManager.java | 28 ------------------- 2 files changed, 10 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java index 0597d7ca..590bac03 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java @@ -54,7 +54,11 @@ public interface DataManager { * @param truster The person whose trusted list to modify. * @param toTrust The person the truster now trusts. */ - public void addTrust(@NotNull OfflinePlayer truster, @NotNull OfflinePlayer toTrust); + public default void addTrust(@NotNull OfflinePlayer truster, @NotNull OfflinePlayer toTrust) { + Set trusted = getTrusted(truster); + trusted.add(toTrust); + setTrusted(truster, trusted); + } /** * Removes a player from another player's list of trusted people. @@ -62,7 +66,11 @@ public interface DataManager { * @param truster The player whose trusted list to modify. * @param toRemove The person to remove from the truster's trust. */ - public void removeTrust(@NotNull OfflinePlayer truster, @NotNull OfflinePlayer toRemove); + public default void removeTrust(@NotNull OfflinePlayer truster, @NotNull OfflinePlayer toRemove) { + Set trusted = getTrusted(truster); + trusted.remove(toRemove); + setTrusted(truster, trusted); + } /** * Checks if a player is trusted by another player. diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java index 165f1c03..969d609a 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java @@ -145,34 +145,6 @@ public void setTrusted(@NotNull OfflinePlayer truster, @NotNull Set trustedPlayers = getTrusted(caster); - trustedPlayers.add(toTrust); - - setTrusted(caster, trustedPlayers); - } - - /** - * Removes a player from another player's list of trusted people. - * - * @param truster The player whose trusted list to modify. - * @param toRemove The person to remove from the truster's trust. - */ - @Override - public void removeTrust(@NotNull OfflinePlayer caster, @NotNull OfflinePlayer trusted) { - Set trustedSet = getTrusted(caster); - trustedSet.remove(trusted); - - setTrusted(caster, trustedSet); - } - /** * Checks if a player is trusted by another player. * From 8954b122cf20d614a38eabbca4c64300f6844776 Mon Sep 17 00:00:00 2001 From: turbojax07 Date: Wed, 18 Feb 2026 13:29:57 -0500 Subject: [PATCH 14/37] Implementing more trust-related sql queries --- .../infuseSMP/playerdata/H2DataManager.java | 68 ++++++++++++++++--- 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java index 5eda8bd5..02e41715 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java @@ -69,6 +69,7 @@ public boolean load() { @Override public int getCrafted(EffectMapping effect) { + return 0; } @@ -77,10 +78,11 @@ public void setCrafted(EffectMapping effect, int crafted) {} @Override public @NotNull Set getTrusted(@NotNull OfflinePlayer truster) { + String selectStr = "SELECT trusted FROM trusts WHERE truster = ?"; UUID trusterUUID = truster.getUniqueId(); try (Connection conn = dataSource.getConnection()) { - PreparedStatement stmt = conn.prepareStatement("SELECT trusted FROM trusts WHERE truster = ?"); + PreparedStatement stmt = conn.prepareStatement(selectStr); stmt.setObject(1, trusterUUID); Set trustedUUIDs = new HashSet<>(); @@ -95,33 +97,81 @@ public void setCrafted(EffectMapping effect, int crafted) {} return trustedUUIDs.stream().map(Bukkit::getOfflinePlayer).collect(Collectors.toSet()); } catch (SQLException err) { - + LOGGER.info("Failed to connect to database.", err); } return null; } @Override public void setTrusted(@NotNull OfflinePlayer truster, @NotNull Set trusted) { - // TODO Auto-generated method stub throw new UnsupportedOperationException("Unimplemented method 'setTrusted'"); } @Override public void addTrust(@NotNull OfflinePlayer truster, @NotNull OfflinePlayer toTrust) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'addTrust'"); + String insertElem = """ + INSERT INTO trusts (truster, trusted) + SELECT ?, ? + WHERE NOT EXISTS ( + SELECT * FROM trusts WHERE truster = ? AND trusted = ? + );"""; + + UUID trusterUUID = truster.getUniqueId(); + UUID toTrustUUID = toTrust.getUniqueId(); + + try (Connection conn = dataSource.getConnection()) { + try (PreparedStatement stmt = conn.prepareStatement(insertElem)) { + stmt.setObject(1, trusterUUID); + stmt.setObject(2, toTrustUUID); + stmt.setObject(3, trusterUUID); + stmt.setObject(4, toTrustUUID); + stmt.execute(); + } catch (SQLException err) { + LOGGER.error("Failed to insert data into database", err); + } + } catch (SQLException err) { + LOGGER.info("Failed to connect to database.", err); + } } @Override public void removeTrust(@NotNull OfflinePlayer truster, @NotNull OfflinePlayer toRemove) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'removeTrust'"); + String deleteElem = "DELETE FROM trusts WHERE truster = ? AND trusted = ?"; + + UUID trusterUUID = truster.getUniqueId(); + UUID trustedUUID = toRemove.getUniqueId(); + + try (Connection conn = dataSource.getConnection()) { + try (PreparedStatement stmt = conn.prepareStatement(deleteElem)) { + stmt.setObject(1, trusterUUID); + stmt.setObject(2, trustedUUID); + stmt.execute(); + } catch (SQLException err) { + LOGGER.error("Failed to remove data from the database", err); + } + } catch (SQLException err) { + LOGGER.info("Failed to connect to database.", err); + } } @Override public boolean isTrusted(@NotNull OfflinePlayer truster, @NotNull OfflinePlayer toCheck) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'isTrusted'"); + String selectStr = "SELECT trusted FROM trusts WHERE truster = ? AND trusted = ?"; + + UUID trusterUUID = truster.getUniqueId(); + UUID trustedUUID = toCheck.getUniqueId(); + + try (Connection conn = dataSource.getConnection()) { + PreparedStatement stmt = conn.prepareStatement(selectStr); + stmt.setObject(1, trusterUUID); + stmt.setObject(2, trustedUUID); + + return stmt.executeQuery().next(); + } catch (SQLException err) { + LOGGER.info("Failed to connect to database.", err); + } + + return false; } @Override From c1c6a87c73e0fd7981d27e685231b1c7da40d65c Mon Sep 17 00:00:00 2001 From: turbojax07 Date: Wed, 18 Feb 2026 13:39:03 -0500 Subject: [PATCH 15/37] Adding integer serialization methods to EffectMapping --- .../infuseSMP/managers/EffectMapping.java | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/managers/EffectMapping.java b/src/main/java/com/catadmirer/infuseSMP/managers/EffectMapping.java index 9719d843..126d5b73 100644 --- a/src/main/java/com/catadmirer/infuseSMP/managers/EffectMapping.java +++ b/src/main/java/com/catadmirer/infuseSMP/managers/EffectMapping.java @@ -2,7 +2,6 @@ import com.catadmirer.infuseSMP.effects.*; import com.catadmirer.infuseSMP.extraeffects.*; -import com.catadmirer.infuseSMP.playerdata.DataManager; import com.catadmirer.infuseSMP.Infuse; import com.catadmirer.infuseSMP.Messages; import java.awt.Color; @@ -229,6 +228,46 @@ public char getActiveIcon() { return (char) Integer.parseInt("E" + (isAugmented() ? 3 : 1) + String.format("%02d", getId()), 16); } + public int serialize() { + return (isAugmented() ? 100 : 0) + getId(); + } + + public EffectMapping deserialize(int serialized) { + return switch (serialized) { + case 1 -> EMERALD; + case 101 -> AUG_EMERALD; + case 2 -> ENDER; + case 102 -> AUG_ENDER; + case 3 -> FEATHER; + case 103 -> AUG_FEATHER; + case 4 -> FIRE; + case 104 -> AUG_FIRE; + case 5 -> FROST; + case 105 -> AUG_FROST; + case 6 -> HASTE; + case 106 -> AUG_HASTE; + case 7 -> HEART; + case 107 -> AUG_HEART; + case 8 -> INVIS; + case 108 -> AUG_INVIS; + case 9 -> OCEAN; + case 109 -> AUG_OCEAN; + case 10 -> REGEN; + case 110 -> AUG_REGEN; + case 11 -> SPEED; + case 111 -> AUG_SPEED; + case 12 -> STRENGTH; + case 112 -> AUG_STRENGTH; + case 13 -> THUNDER; + case 113 -> AUG_THUNDER; + case 14 -> APOPHIS; + case 114 -> AUG_APOPHIS; + case 15 -> THIEF; + case 115 -> AUG_THIEF; + default -> null; + }; + } + /** * Getting the effect in its regular form. * If the enum is already the regular form, it returns itself. From 9d23ed4664c7f10e8d598eed777aeef97fd52bb4 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 02:09:43 -0400 Subject: [PATCH 16/37] Using OfflinePlayers instead of UUIDs for getters/setters and updating some param names/javadocs --- .../infuseSMP/playerdata/DataManager.java | 91 +++++++++---------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java index 528e7f81..d067cac9 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java @@ -6,7 +6,6 @@ import org.jspecify.annotations.Nullable; import java.util.Set; -import java.util.UUID; @NullMarked public interface DataManager { @@ -45,63 +44,64 @@ public interface DataManager { /** * Sets the players that the truster trusts. * - * @param truster The player to modify - * @param trusted The set of players the truster now trusts + * @param player The player to modify + * @param trusted The set of players the truster should now trust */ - void setTrusted(OfflinePlayer truster, Set trusted); + void setTrusted(OfflinePlayer player, Set trusted); /** * Adds a player to the list of trusted people. * - * @param truster The person whose trusted list to modify. - * @param toTrust The person the truster now trusts. - */ - default void addTrust(OfflinePlayer truster, OfflinePlayer toTrust) { - Set trusted = getTrusted(truster); - trusted.add(toTrust); - setTrusted(truster, trusted); + * @param player The person whose trusted list to modify. + * @param trusted The person the truster now trusts. + */ + default void addTrust(OfflinePlayer player, OfflinePlayer trusted) { + // TODO: Override in SQL-based data managers + Set allTrusted = getTrusted(player); + allTrusted.add(trusted); + setTrusted(player, allTrusted); } /** * Removes a player from another player's list of trusted people. * - * @param truster The player whose trusted list to modify. - * @param toRemove The person to remove from the truster's trust. - */ - default void removeTrust(OfflinePlayer truster, OfflinePlayer toRemove) { - Set trusted = getTrusted(truster); - trusted.remove(toRemove); - setTrusted(truster, trusted); + * @param player The player whose trusted list to modify. + * @param untrusted The person to remove from the truster's trust. + */ + default void removeTrust(OfflinePlayer player, OfflinePlayer untrusted) { + // TODO: Override in SQL-based data managers + Set trusted = getTrusted(player); + trusted.remove(untrusted); + setTrusted(player, trusted); } /** * Checks if a player is trusted by another player. * - * @param caster The player whose trusted list to check. + * @param player The player whose trusted list to check. * @param trusted The player to check if truster trusts. * * @return True if the truster trusts the toCheck player, false otherwise */ - boolean isTrusted(OfflinePlayer caster, OfflinePlayer trusted); + default boolean isTrusted(OfflinePlayer player, OfflinePlayer trusted) { + // TODO: Override in SQL-based data managers + return getTrusted(player).contains(trusted); + } /** * Sets the infuse effect in a specific slot for a player. * - * @param owner The UUID of the player. * @param slot The slot to equip the effect in. * @param effect The {@link InfuseEffect} for the infuse effect. */ - void setEffect(UUID owner, String slot, @Nullable InfuseEffect effect); + void setEffect(OfflinePlayer player, String slot, @Nullable InfuseEffect effect); /** * Gets the infuse effect a player has in a specific slot. - * - * @param owner The UUID of the player. - * @param slot The slot to get the effect from. - * + * * @return null if there is not an effect equipped there or if the InfuseEffect could not be deserialized. Otherwise, it returns the deserialized InfuseEffect. */ - @Nullable InfuseEffect getEffect(UUID owner, String slot); + @Nullable InfuseEffect getEffect(OfflinePlayer player, String slot); /** * Checks if the player has the infuse effect. @@ -140,32 +140,31 @@ default boolean hasEffect(OfflinePlayer player, InfuseEffect effect, String slot * * @return True if the player has the effect equipped, false otherwise. */ - boolean hasEffect(OfflinePlayer player, InfuseEffect effect, boolean differentiateAugmented, String slot); + default boolean hasEffect(OfflinePlayer player, InfuseEffect effect, boolean differentiateAugmented, String slot) { + InfuseEffect equipped = getEffect(player, slot); + if (equipped == null) return false; - /** - * Removes an infuse effect from a specific slot for a player. - * - * @param playerUUID The UUID of the player. - * @param slot The slot to remove an effect from. - */ - void removeEffect(UUID playerUUID, String slot); + if (differentiateAugmented) { + return effect.equals(equipped); + } - /** - * Sets the control mode for a player. - * - * @param playerUUID The UUID of the player. - * @param defaultMode The new control mode to use. - */ - void setControlMode(UUID playerUUID, String defaultMode); + return effect.getId() == equipped.getId(); + } + + /** Removes an infuse effect from a specific slot for a player. */ + default void removeEffect(OfflinePlayer player, String slot) { + setEffect(player, slot, null); + } + + /** Sets the control mode for a player. */ + void setControlMode(OfflinePlayer player, String controlMode); /** * Gets the control mode of a player. - * - * @param playerUUID The UUID of the player. - * + * * @return Either "command" or "offhand". Defaults to "offhand" */ - String getControlMode(UUID playerUUID); + String getControlMode(OfflinePlayer player); /** * Modifies the config to make any necessary changes to make old versions compatible with this new one. From 2624ca37627f64c7e51099891ed9e10f05e93fd0 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 02:23:55 -0400 Subject: [PATCH 17/37] Updating the PlayerData class with getters and setters for each bit of data --- .../infuseSMP/playerdata/PlayerData.java | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/PlayerData.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/PlayerData.java index 7c04408d..4e3a3761 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/PlayerData.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/PlayerData.java @@ -1,4 +1,170 @@ package com.catadmirer.infuseSMP.playerdata; +import com.catadmirer.infuseSMP.Infuse; +import com.catadmirer.infuseSMP.effects.InfuseEffect; +import org.bukkit.OfflinePlayer; +import org.jetbrains.annotations.Unmodifiable; +import org.jspecify.annotations.Nullable; + +import java.util.HashSet; +import java.util.Set; + public class PlayerData { + private InfuseEffect lSlot; + private InfuseEffect rSlot; + private Set trusted; + private boolean offhandControls; + + /** + * Gets the set of the players that the player trusts. + * + * @return The set of players trusted by the player. + */ + @Unmodifiable + public Set getTrusted() { + return Set.copyOf(trusted); + } + + /** + * Sets the players that the player trusts. + * + * @param trusted The set of players the truster should now trust + */ + public void setTrusted(Set trusted) { + this.trusted = new HashSet<>(trusted); + } + + /** + * Adds a player to the list of trusted people. + * + * @param trustedPlayer The person the truster now trusts. + */ + public void addTrust(OfflinePlayer trustedPlayer) { + this.trusted.add(trustedPlayer); + } + + /** + * Removes a player from this player's list of trusted people. + * + * @param untrusted The person to remove from the truster's trust. + */ + public void removeTrust(OfflinePlayer untrusted) { + trusted.remove(untrusted); + } + + /** + * Checks if a player is trusted by this player. + * + * @param trustedPlayer The player to check if the player trusts. + * + * @return True if the player trusts the other player, false otherwise + */ + public boolean isTrusted(OfflinePlayer trustedPlayer) { + return this.trusted.contains(trustedPlayer); + } + + /** + * Sets the infuse effect in a specific slot for the player. + * + * @param slot The slot to equip the effect in. + * @param effect The {@link InfuseEffect} for the infuse effect. + */ + public void setEffect(String slot, @Nullable InfuseEffect effect) { + if (slot.equals("1")) { + lSlot = effect; + } else if (slot.equals("2")) { + rSlot = effect; + } else { + Infuse.LOGGER.warn("Invalid slot id \"{}\"", slot); + } + } + + /** + * Gets the infuse effect the player has in a specific slot. + * + * @return null if there is not an effect equipped there or if the InfuseEffect could not be deserialized. Otherwise, it returns the deserialized InfuseEffect. + */ + public @Nullable InfuseEffect getEffect(String slot) { + if (slot.equals("1")) { + return lSlot; + } else if (slot.equals("2")) { + return rSlot; + } else { + Infuse.LOGGER.warn("Invalid slot id \"{}\"", slot); + return null; + } + } + + /** + * Checks if the player has the infuse effect. + * It checks both slots and doesn't differentiate between regular and augmented effects. + * + * @return True if the player has the effect equipped, false otherwise. + */ + public boolean hasEffect(InfuseEffect effect) { + return hasEffect(effect, false); + } + + /** + * Checks if the player has the infuse effect. + * It checks both slots and doesn't differentiate between regular and augmented effects. + * + * @return True if the player has the effect equipped, false otherwise. + */ + public boolean hasEffect(InfuseEffect effect, boolean differentiateAugmented) { + return hasEffect(effect, differentiateAugmented, "1") || hasEffect(effect, differentiateAugmented, "2"); + } + + /** + * Checks if the player has the infuse effect. + * It checks both slots and doesn't differentiate between regular and augmented effects. + * + * @return True if the player has the effect equipped, false otherwise. + */ + public boolean hasEffect(InfuseEffect effect, String slot) { + return hasEffect(effect, false, slot); + } + + /** + * Checks if the player has the infuse effect equipped in a specific slot. + * + * @param differentiateAugmented Whether the search should differentiate between regular and augmented effects. + * + * @return True if the player has the effect equipped, false otherwise. + */ + public boolean hasEffect(InfuseEffect effect, boolean differentiateAugmented, String slot) { + InfuseEffect equipped = getEffect(slot); + if (equipped == null) return false; + + if (differentiateAugmented) { + return effect.equals(equipped); + } + + return effect.getId() == equipped.getId(); + } + + /** Removes an infuse effect from a specific slot for the player. */ + public void removeEffect(String slot) { + setEffect(slot, null); + } + + /** Sets the control mode for the player. */ + void setControlMode(String controlMode) { + if (controlMode.equals("offhand")) { + offhandControls = true; + } else if (controlMode.equals("command")) { + offhandControls = false; + } else { + Infuse.LOGGER.warn("Invalid control mode \"{}\"", controlMode); + } + } + + /** + * Gets the control mode of the player. + * + * @return Either "command" or "offhand". Defaults to "offhand" + */ + public String getControlMode() { + return offhandControls ? "offhand" : "command"; + } } From 4404d629e03d4fddbee3e8f93f2b7fc52098668a Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 10:48:25 -0400 Subject: [PATCH 18/37] Removing PlayerData due to worries about desync. --- .../infuseSMP/playerdata/PlayerData.java | 170 ------------------ 1 file changed, 170 deletions(-) delete mode 100644 src/main/java/com/catadmirer/infuseSMP/playerdata/PlayerData.java diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/PlayerData.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/PlayerData.java deleted file mode 100644 index 4e3a3761..00000000 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/PlayerData.java +++ /dev/null @@ -1,170 +0,0 @@ -package com.catadmirer.infuseSMP.playerdata; - -import com.catadmirer.infuseSMP.Infuse; -import com.catadmirer.infuseSMP.effects.InfuseEffect; -import org.bukkit.OfflinePlayer; -import org.jetbrains.annotations.Unmodifiable; -import org.jspecify.annotations.Nullable; - -import java.util.HashSet; -import java.util.Set; - -public class PlayerData { - private InfuseEffect lSlot; - private InfuseEffect rSlot; - private Set trusted; - private boolean offhandControls; - - /** - * Gets the set of the players that the player trusts. - * - * @return The set of players trusted by the player. - */ - @Unmodifiable - public Set getTrusted() { - return Set.copyOf(trusted); - } - - /** - * Sets the players that the player trusts. - * - * @param trusted The set of players the truster should now trust - */ - public void setTrusted(Set trusted) { - this.trusted = new HashSet<>(trusted); - } - - /** - * Adds a player to the list of trusted people. - * - * @param trustedPlayer The person the truster now trusts. - */ - public void addTrust(OfflinePlayer trustedPlayer) { - this.trusted.add(trustedPlayer); - } - - /** - * Removes a player from this player's list of trusted people. - * - * @param untrusted The person to remove from the truster's trust. - */ - public void removeTrust(OfflinePlayer untrusted) { - trusted.remove(untrusted); - } - - /** - * Checks if a player is trusted by this player. - * - * @param trustedPlayer The player to check if the player trusts. - * - * @return True if the player trusts the other player, false otherwise - */ - public boolean isTrusted(OfflinePlayer trustedPlayer) { - return this.trusted.contains(trustedPlayer); - } - - /** - * Sets the infuse effect in a specific slot for the player. - * - * @param slot The slot to equip the effect in. - * @param effect The {@link InfuseEffect} for the infuse effect. - */ - public void setEffect(String slot, @Nullable InfuseEffect effect) { - if (slot.equals("1")) { - lSlot = effect; - } else if (slot.equals("2")) { - rSlot = effect; - } else { - Infuse.LOGGER.warn("Invalid slot id \"{}\"", slot); - } - } - - /** - * Gets the infuse effect the player has in a specific slot. - * - * @return null if there is not an effect equipped there or if the InfuseEffect could not be deserialized. Otherwise, it returns the deserialized InfuseEffect. - */ - public @Nullable InfuseEffect getEffect(String slot) { - if (slot.equals("1")) { - return lSlot; - } else if (slot.equals("2")) { - return rSlot; - } else { - Infuse.LOGGER.warn("Invalid slot id \"{}\"", slot); - return null; - } - } - - /** - * Checks if the player has the infuse effect. - * It checks both slots and doesn't differentiate between regular and augmented effects. - * - * @return True if the player has the effect equipped, false otherwise. - */ - public boolean hasEffect(InfuseEffect effect) { - return hasEffect(effect, false); - } - - /** - * Checks if the player has the infuse effect. - * It checks both slots and doesn't differentiate between regular and augmented effects. - * - * @return True if the player has the effect equipped, false otherwise. - */ - public boolean hasEffect(InfuseEffect effect, boolean differentiateAugmented) { - return hasEffect(effect, differentiateAugmented, "1") || hasEffect(effect, differentiateAugmented, "2"); - } - - /** - * Checks if the player has the infuse effect. - * It checks both slots and doesn't differentiate between regular and augmented effects. - * - * @return True if the player has the effect equipped, false otherwise. - */ - public boolean hasEffect(InfuseEffect effect, String slot) { - return hasEffect(effect, false, slot); - } - - /** - * Checks if the player has the infuse effect equipped in a specific slot. - * - * @param differentiateAugmented Whether the search should differentiate between regular and augmented effects. - * - * @return True if the player has the effect equipped, false otherwise. - */ - public boolean hasEffect(InfuseEffect effect, boolean differentiateAugmented, String slot) { - InfuseEffect equipped = getEffect(slot); - if (equipped == null) return false; - - if (differentiateAugmented) { - return effect.equals(equipped); - } - - return effect.getId() == equipped.getId(); - } - - /** Removes an infuse effect from a specific slot for the player. */ - public void removeEffect(String slot) { - setEffect(slot, null); - } - - /** Sets the control mode for the player. */ - void setControlMode(String controlMode) { - if (controlMode.equals("offhand")) { - offhandControls = true; - } else if (controlMode.equals("command")) { - offhandControls = false; - } else { - Infuse.LOGGER.warn("Invalid control mode \"{}\"", controlMode); - } - } - - /** - * Gets the control mode of the player. - * - * @return Either "command" or "offhand". Defaults to "offhand" - */ - public String getControlMode() { - return offhandControls ? "offhand" : "command"; - } -} From 30a38ce0221537560491c676621f6a58fee7b22a Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 10:51:30 -0400 Subject: [PATCH 19/37] Removing add/set trust overrides from YamlDataManager --- .../infuseSMP/playerdata/YamlDataManager.java | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java index 208dd43e..4fc91ce4 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java @@ -114,29 +114,7 @@ public void setTrusted(OfflinePlayer truster, Set trusted) { } @Override - public void addTrust(OfflinePlayer caster, OfflinePlayer toTrust) { - Set trustedPlayers = getTrusted(caster); - trustedPlayers.add(toTrust); - setTrusted(caster, trustedPlayers); - } - - @Override - public void removeTrust(OfflinePlayer caster, OfflinePlayer trusted) { - Set trustedSet = getTrusted(caster); - trustedSet.remove(trusted); - - setTrusted(caster, trustedSet); - } - - @Override - public boolean isTrusted(OfflinePlayer caster, OfflinePlayer trusted) { - if (caster.getUniqueId().equals(trusted.getUniqueId())) return true; - - return getTrusted(caster).contains(trusted); - } - - @Override public void setEffect(UUID owner, String slot, @Nullable InfuseEffect effect) { if (effect == null) { config.set(owner + "." + slot, null); From 0ef0dc591a5b8bf9d9190fb7438ae74196c34ef0 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 10:52:12 -0400 Subject: [PATCH 20/37] Validating slot in setEffect --- .../infuseSMP/playerdata/YamlDataManager.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java index 4fc91ce4..51c4558c 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java @@ -114,12 +114,17 @@ public void setTrusted(OfflinePlayer truster, Set trusted) { } @Override + public void setEffect(OfflinePlayer player, String slot, @Nullable InfuseEffect effect) { + // Making sure slot is "1" or "2" + if (!slot.equals("1") && !slot.equals("2")) { + Infuse.LOGGER.warn("Slot '{}' is not a valid slot. Please use \"1\" or \"2\"", slot); + return; + } - public void setEffect(UUID owner, String slot, @Nullable InfuseEffect effect) { if (effect == null) { - config.set(owner + "." + slot, null); + config.set(player.getUniqueId() + "." + slot, null); } else { - config.set(owner + "." + slot, effect.toString()); + config.set(player.getUniqueId() + "." + slot, effect.toString()); } save(); } From ec9312579c51fbb7cc9e4bbd1b4189bbe9b4978b Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 10:52:49 -0400 Subject: [PATCH 21/37] removing hasEffect override in YamlDataManager --- .../infuseSMP/playerdata/YamlDataManager.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java index 51c4558c..50b475a1 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java @@ -141,19 +141,6 @@ public InfuseEffect getEffect(UUID owner, String slot) { return effect; } - @Override - public boolean hasEffect(OfflinePlayer player, InfuseEffect effect, boolean differentiateAugmented, String slot) { - InfuseEffect equippedEffect = getEffect(player.getUniqueId(), slot); - - if (equippedEffect == null) return false; - - if (differentiateAugmented) { - return effect.equals(equippedEffect); - } - - return effect.getId() == equippedEffect.getId(); - } - @Override public void removeEffect(UUID playerUUID, String slot) { config.set(playerUUID.toString() + "." + slot, null); From e31cb7a2d7952800e648a7936aa4cdcb33fc3bc6 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 10:53:33 -0400 Subject: [PATCH 22/37] updating the params in YamlDataManager --- .../infuseSMP/playerdata/YamlDataManager.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java index 50b475a1..01a97b9a 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java @@ -107,8 +107,8 @@ public Set getTrusted(OfflinePlayer player) { } @Override - public void setTrusted(OfflinePlayer truster, Set trusted) { - config.set(truster.getUniqueId() + ".trust", trusted.stream().map(OfflinePlayer::getUniqueId).toList()); + public void setTrusted(OfflinePlayer player, Set allTrusted) { + config.set(player.getUniqueId() + ".trust", allTrusted.stream().map(OfflinePlayer::getUniqueId).toList()); save(); } @@ -131,8 +131,8 @@ public void setEffect(OfflinePlayer player, String slot, @Nullable InfuseEffect @Nullable @Override - public InfuseEffect getEffect(UUID owner, String slot) { - String effectKey = config.getString(owner.toString() + "." + slot, null); + public InfuseEffect getEffect(OfflinePlayer player, String slot) { + String effectKey = config.getString(player.getUniqueId() + "." + slot, null); InfuseEffect effect = InfuseEffect.fromString(effectKey); if (effectKey != null && effect == null) { Infuse.LOGGER.warn("No valid ability found for the equipped effect."); @@ -142,20 +142,20 @@ public InfuseEffect getEffect(UUID owner, String slot) { } @Override - public void removeEffect(UUID playerUUID, String slot) { - config.set(playerUUID.toString() + "." + slot, null); + public void removeEffect(OfflinePlayer player, String slot) { + config.set(player.getUniqueId() + "." + slot, null); save(); } @Override - public void setControlMode(UUID playerUUID, String defaultMode) { - config.set(playerUUID.toString() + ".controls", defaultMode); + public void setControlMode(OfflinePlayer player, String defaultMode) { + config.set(player.getUniqueId() + ".controls", defaultMode); save(); } @Override - public String getControlMode(UUID playerUUID) { - return config.getString(playerUUID.toString() + ".controls", "offhand"); + public String getControlMode(OfflinePlayer player) { + return config.getString(player.getUniqueId() + ".controls", "offhand"); } @Override From 4c32a33d1bb16b26d22b7721d7e6d49e48a1a222 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 12:05:24 -0400 Subject: [PATCH 23/37] using default removeEffect in YamlDataManager --- .../catadmirer/infuseSMP/playerdata/YamlDataManager.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java index 01a97b9a..72f985f3 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java @@ -141,12 +141,6 @@ public InfuseEffect getEffect(OfflinePlayer player, String slot) { return effect; } - @Override - public void removeEffect(OfflinePlayer player, String slot) { - config.set(player.getUniqueId() + "." + slot, null); - save(); - } - @Override public void setControlMode(OfflinePlayer player, String defaultMode) { config.set(player.getUniqueId() + ".controls", defaultMode); From 7996b6035032f6e6f3a68a95b4c61eed00f0c2f1 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 12:36:58 -0400 Subject: [PATCH 24/37] changing the default control mode to "command" --- .../java/com/catadmirer/infuseSMP/playerdata/DataManager.java | 2 +- .../com/catadmirer/infuseSMP/playerdata/YamlDataManager.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java index d067cac9..a95f9f2c 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java @@ -162,7 +162,7 @@ default void removeEffect(OfflinePlayer player, String slot) { /** * Gets the control mode of a player. * - * @return Either "command" or "offhand". Defaults to "offhand" + * @return Either "command" or "offhand". Defaults to "command" */ String getControlMode(OfflinePlayer player); diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java index 72f985f3..e1909b86 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java @@ -149,7 +149,7 @@ public void setControlMode(OfflinePlayer player, String defaultMode) { @Override public String getControlMode(OfflinePlayer player) { - return config.getString(player.getUniqueId() + ".controls", "offhand"); + return config.getString(player.getUniqueId() + ".controls", "command"); } @Override From dea86b797e93d2a5187ad1d0b78e9f6027e432d9 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 12:45:14 -0400 Subject: [PATCH 25/37] Finishing the first version of the h2 database implementation --- .../infuseSMP/playerdata/H2DataManager.java | 241 +++++++++++++++--- 1 file changed, 204 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java index 862dbbaa..6320f90d 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java @@ -45,9 +45,11 @@ public H2DataManager(Infuse plugin) { @Override public void load() { - final String createPlayerDataTable = "CREATE TABLE IF NOT EXISTS player_data(player UUID PRIMARY KEY, slot_1 INTEGER NOT NULL, slot_2 INTEGER NOT NULL, offhand_control BOOLEAN NOT NULL);"; + // CREATE TABLE IF NOT EXISTS player_data(player UUID PRIMARY KEY NOT NULL, slot_1 INTEGER, slot_2 INTEGER, offhand_control BOOLEAN NOT NULL); + // INSERT INTO player_data (player, slot_1, slot_2, offhand_control) VALUES ('4f8d5501-de90-4d92-a927-17f2c4ff0cb1', NULL, NULL, FALSE) + final String createPlayerDataTable = "CREATE TABLE IF NOT EXISTS player_data(player UUID PRIMARY KEY NOT NULL, slot_1 INTEGER, slot_2 INTEGER, offhand_control BOOLEAN NOT NULL);"; final String createTrustTable = "CREATE TABLE IF NOT EXISTS trusts(truster UUID NOT NULL, trusted UUID NOT NULL);"; - final String createCraftedTable = "CREATE TABLE IF NOT EXISTS crafted_effects(effect INTEGER NOT NULL, count INTEGER NOT NULL);"; + final String createCraftedTable = "CREATE TABLE IF NOT EXISTS crafted_effects(effect INTEGER PRIMARY KEY NOT NULL, crafted INTEGER NOT NULL);"; try (Connection conn = dataSource.getConnection()) { // Creating the tables if they don't exist @@ -69,11 +71,55 @@ public void save() {} @Override public int getExistingCount(InfuseEffect effect) { + String sql = "SELECT crafted FROM crafted_effects WHERE effect = ?;"; + + try (Connection conn = dataSource.getConnection(); + PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, effect.serialize()); + + ResultSet results = stmt.executeQuery(); + if (!results.next()) return 0; + + return results.getInt(1); + } catch (SQLException e) { + Infuse.LOGGER.error("Database error!", e); + } + return 0; } @Override - public void setExistingCount(InfuseEffect effect, int count) {} + public void setExistingCount(InfuseEffect effect, int count) { + String sql = "INSERT OR REPLACE INTO crafted_effects(effect, crafted) VALUES (?, ?);"; + + try (Connection conn = dataSource.getConnection(); + PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, effect.serialize()); + stmt.setInt(2, count); + + stmt.executeUpdate(); + } catch (SQLException e) { + Infuse.LOGGER.error("Database error!", e); + } + } + + /** + * Creates a new player object in the database. + * Both effects default to null, and the offhand_control defaults to false. + * If a row for the player already exists, nothing happens. + * + * @param player The player to create an entry for. + */ + public void createNewPlayer(OfflinePlayer player) { + String newPlayer = "INSERT OR IGNORE INTO player_data (player, offhand_control) VALUES (?, FALSE);"; + try (Connection conn = dataSource.getConnection(); + PreparedStatement stmt = conn.prepareStatement(newPlayer)) { + stmt.setObject(1, player.getUniqueId()); + stmt.executeUpdate(); + } catch (SQLException e) { + Infuse.LOGGER.error("Database error!", e); + } + } @Override public Set getTrusted(OfflinePlayer player) { @@ -102,12 +148,67 @@ public Set getTrusted(OfflinePlayer player) { } @Override - public void setTrusted(OfflinePlayer truster, Set trusted) { + public void setTrusted(OfflinePlayer player, Set allTrusted) { + Set trustedCopy = new HashSet<>(allTrusted); + + String findUnused = "SELECT * FROM trusts WHERE truster = ?;"; + String deleteExtra = "DELETE FROM trusts WHERE truster = ? AND trusted = ?;"; + + String insertTrusted = "INSERT INTO trusts (truster, trusted) VALUES (?, ?);"; + + try (Connection conn = dataSource.getConnection()) { + // Removing players who are no longer trusted and filtering out players who are already trusted from the copy of the set + try (PreparedStatement stmt = conn.prepareStatement(findUnused); + PreparedStatement delStmt = conn.prepareStatement(deleteExtra)) { + stmt.setObject(1, player.getUniqueId()); + stmt.execute(); + ResultSet results = stmt.getResultSet(); + + delStmt.setObject(1, player.getUniqueId()); + + // Looping through the trusted players + while (results.next()) { + OfflinePlayer trusted = Bukkit.getOfflinePlayer(results.getObject(1, UUID.class)); + + // Skipping already trusted players + if (trustedCopy.contains(trusted)) { + trustedCopy.remove(trusted); + continue; + } + + // Removing players who are no longer trusted + delStmt.setObject(2, trusted.getUniqueId()); + delStmt.addBatch(); + } + + // Executing the delete statement + delStmt.executeBatch(); + } catch (SQLException e) { + Infuse.LOGGER.error("Database error!", e); + } + + // Adding the rest of the players to trust + try (PreparedStatement stmt = conn.prepareStatement(insertTrusted)) { + stmt.setObject(1, player.getUniqueId()); + + for (OfflinePlayer trusted : trustedCopy) { + stmt.setObject(2, trusted.getUniqueId()); + stmt.addBatch(); + } + + stmt.executeBatch(); + } catch (SQLException err) { + LOGGER.error("Failed to insert players back into the database", err); + } + } catch (SQLException err) { + LOGGER.info("Failed to connect to database.", err); + } + throw new UnsupportedOperationException("Unimplemented method 'setTrusted'"); } @Override - public void addTrust(OfflinePlayer truster, OfflinePlayer toTrust) { + public void addTrust(OfflinePlayer player, OfflinePlayer toTrust) { String insertElem = """ INSERT INTO trusts (truster, trusted) SELECT ?, ? @@ -115,7 +216,7 @@ WHERE NOT EXISTS ( SELECT * FROM trusts WHERE truster = ? AND trusted = ? );"""; - UUID trusterUUID = truster.getUniqueId(); + UUID trusterUUID = player.getUniqueId(); UUID toTrustUUID = toTrust.getUniqueId(); try (Connection conn = dataSource.getConnection()) { @@ -134,11 +235,11 @@ WHERE NOT EXISTS ( } @Override - public void removeTrust(OfflinePlayer truster, OfflinePlayer toRemove) { + public void removeTrust(OfflinePlayer player, OfflinePlayer untrusted) { String deleteElem = "DELETE FROM trusts WHERE truster = ? AND trusted = ?"; - UUID trusterUUID = truster.getUniqueId(); - UUID trustedUUID = toRemove.getUniqueId(); + UUID trusterUUID = player.getUniqueId(); + UUID trustedUUID = untrusted.getUniqueId(); try (Connection conn = dataSource.getConnection()) { try (PreparedStatement stmt = conn.prepareStatement(deleteElem)) { @@ -154,18 +255,21 @@ public void removeTrust(OfflinePlayer truster, OfflinePlayer toRemove) { } @Override - public boolean isTrusted(OfflinePlayer caster, OfflinePlayer trusted) { + public boolean isTrusted(OfflinePlayer player, OfflinePlayer trusted) { String selectStr = "SELECT trusted FROM trusts WHERE truster = ? AND trusted = ?"; - UUID trusterUUID = caster.getUniqueId(); + UUID trusterUUID = player.getUniqueId(); UUID trustedUUID = trusted.getUniqueId(); try (Connection conn = dataSource.getConnection()) { - PreparedStatement stmt = conn.prepareStatement(selectStr); - stmt.setObject(1, trusterUUID); - stmt.setObject(2, trustedUUID); + try (PreparedStatement stmt = conn.prepareStatement(selectStr)) { + stmt.setObject(1, trusterUUID); + stmt.setObject(2, trustedUUID); - return stmt.executeQuery().next(); + return stmt.executeQuery().next(); + } catch (SQLException e) { + Infuse.LOGGER.error("Failed to execute SQL \"{}\"", selectStr, e); + } } catch (SQLException err) { LOGGER.info("Failed to connect to database.", err); } @@ -174,40 +278,103 @@ public boolean isTrusted(OfflinePlayer caster, OfflinePlayer trusted) { } @Override - public void setEffect(UUID owner, String slot, @Nullable InfuseEffect effect) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'setEffect'"); + public void setEffect(OfflinePlayer player, String slot, @Nullable InfuseEffect effect) { + createNewPlayer(player); + + // Making sure slot is "1" or "2" + if (!slot.equals("1") && !slot.equals("2")) { + Infuse.LOGGER.warn("Slot '{}' is not a valid slot. Please use \"1\" or \"2\"", slot); + return; + } + + // Constructing sql based on specified slot + final String setEffectSQL = "UPDATE player_data SET slot_1 = ? WHERE player = ?;"; + + try (Connection conn = dataSource.getConnection()) { + PreparedStatement stmt = conn.prepareStatement(setEffectSQL); + stmt.setObject(1, effect == null ? null : effect.serialize()); + stmt.setObject(2, player.getUniqueId()); + + stmt.executeUpdate(); + } catch (SQLException err) { + Infuse.LOGGER.error("Could not open connection to H2 database", err); + } } @Nullable @Override - public InfuseEffect getEffect(UUID owner, String slot) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getEffect'"); - } + public InfuseEffect getEffect(OfflinePlayer player, String slot) { + // Making sure slot is "1" or "2" + if (!slot.equals("1") && !slot.equals("2")) { + Infuse.LOGGER.warn("Slot '{}' is not a valid slot. Please use \"1\" or \"2\"", slot); + return null; + } - @Override - public boolean hasEffect(OfflinePlayer player, InfuseEffect effect, boolean differentiateAugmented, String slot) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'hasEffect'"); - } + // Constructing sql based on specified slot + final String getEffectSQL = "SELECT (slot_" + slot + ") FROM player_data WHERE player = ?;"; - @Override - public void removeEffect(UUID playerUUID, String slot) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'removeEffect'"); + try (Connection conn = dataSource.getConnection()) { + try (PreparedStatement stmt = conn.prepareStatement(getEffectSQL)) { + stmt.setObject(1, player.getUniqueId()); + + ResultSet results = stmt.executeQuery(); + + // Triggers when no effect is equipped or the effect is null + if (!results.next() || results.wasNull()) { + return null; + } + + return InfuseEffect.deserialize(results.getInt(1)); + } catch (SQLException e) { + Infuse.LOGGER.error("Failed to read effects from the database", e); + } + } catch (SQLException err) { + Infuse.LOGGER.error("Could not open connection to H2 database", err); + } + + return null; } @Override - public void setControlMode(UUID playerUUID, String defaultMode) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'setControlMode'"); + public void setControlMode(OfflinePlayer player, String controlMode) { + createNewPlayer(player); + + boolean offhandControls; + if (controlMode.equals("offhand")) { + offhandControls = true; + } else if (controlMode.equals("command")) { + offhandControls = false; + } else { + Infuse.LOGGER.error("Invalid control mode \"{}\". Please use \"offhand\" or \"command\"", controlMode); + return; + } + + String sql = "UPDATE player_data SET offhand_control = ? WHERE player = ?;"; + try (Connection conn = dataSource.getConnection(); + PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setObject(1, offhandControls); + stmt.setObject(2, player.getUniqueId()); + + stmt.executeUpdate(); + } catch (SQLException e) { + Infuse.LOGGER.error("Database error!", e); + } } @Override - public String getControlMode(UUID playerUUID) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getControlMode'"); + public String getControlMode(OfflinePlayer player) { + String sql = "SELECT offhand_control FROM player_data WHERE player = ?;"; + try (Connection conn = dataSource.getConnection(); + PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setObject(1, player.getUniqueId()); + + ResultSet results = stmt.executeQuery(); + return results.getBoolean(1) ? "offhand" : "command"; + } catch (SQLException e) { + Infuse.LOGGER.error("Database error!", e); + } + + return "command"; } @Override From fef4f500d409103f27ce4dc184329919f870655e Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 13:10:31 -0400 Subject: [PATCH 26/37] removing some extra comments and updating logging --- .../infuseSMP/playerdata/H2DataManager.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java index 6320f90d..e6c7946a 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java @@ -7,8 +7,6 @@ import org.h2.jdbcx.JdbcDataSource; import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.sql.Connection; import java.sql.PreparedStatement; @@ -23,14 +21,13 @@ @NullMarked public class H2DataManager implements DataManager { - private static final Logger LOGGER = LoggerFactory.getLogger("Infuse_Storage"); private final DataSource dataSource; public H2DataManager(Infuse plugin) { try { Class.forName("org.h2.Driver"); } catch (ClassNotFoundException err) { - LOGGER.error("Could not load the H2 driver", err); + Infuse.LOGGER.error("Could not load the H2 driver", err); } // Creating the JDBC DataSource @@ -45,8 +42,6 @@ public H2DataManager(Infuse plugin) { @Override public void load() { - // CREATE TABLE IF NOT EXISTS player_data(player UUID PRIMARY KEY NOT NULL, slot_1 INTEGER, slot_2 INTEGER, offhand_control BOOLEAN NOT NULL); - // INSERT INTO player_data (player, slot_1, slot_2, offhand_control) VALUES ('4f8d5501-de90-4d92-a927-17f2c4ff0cb1', NULL, NULL, FALSE) final String createPlayerDataTable = "CREATE TABLE IF NOT EXISTS player_data(player UUID PRIMARY KEY NOT NULL, slot_1 INTEGER, slot_2 INTEGER, offhand_control BOOLEAN NOT NULL);"; final String createTrustTable = "CREATE TABLE IF NOT EXISTS trusts(truster UUID NOT NULL, trusted UUID NOT NULL);"; final String createCraftedTable = "CREATE TABLE IF NOT EXISTS crafted_effects(effect INTEGER PRIMARY KEY NOT NULL, crafted INTEGER NOT NULL);"; @@ -61,8 +56,10 @@ public void load() { // Commiting any changes conn.commit(); + + Infuse.LOGGER.info("Successfully loaded H2 database!"); } catch (SQLException err) { - LOGGER.error("Could not open connection to H2 database", err); + Infuse.LOGGER.error("Could not open connection to H2 database", err); } } @@ -136,13 +133,13 @@ public Set getTrusted(OfflinePlayer player) { try { trustedUUIDs.add(result.getObject(1, UUID.class)); } catch (SQLException err) { - LOGGER.warn("Invalid UUID in SQL results. Skipping value."); + Infuse.LOGGER.warn("Invalid UUID in SQL results. Skipping value."); } } return trustedUUIDs.stream().map(Bukkit::getOfflinePlayer).collect(Collectors.toSet()); } catch (SQLException err) { - LOGGER.info("Failed to connect to database.", err); + Infuse.LOGGER.info("Failed to connect to database.", err); } return Set.of(); } @@ -198,10 +195,10 @@ public void setTrusted(OfflinePlayer player, Set allTrusted) { stmt.executeBatch(); } catch (SQLException err) { - LOGGER.error("Failed to insert players back into the database", err); + Infuse.LOGGER.error("Failed to insert players back into the database", err); } } catch (SQLException err) { - LOGGER.info("Failed to connect to database.", err); + Infuse.LOGGER.info("Failed to connect to database.", err); } throw new UnsupportedOperationException("Unimplemented method 'setTrusted'"); @@ -227,10 +224,10 @@ WHERE NOT EXISTS ( stmt.setObject(4, toTrustUUID); stmt.execute(); } catch (SQLException err) { - LOGGER.error("Failed to insert data into database", err); + Infuse.LOGGER.error("Failed to insert data into database", err); } } catch (SQLException err) { - LOGGER.info("Failed to connect to database.", err); + Infuse.LOGGER.info("Failed to connect to database.", err); } } @@ -247,10 +244,10 @@ public void removeTrust(OfflinePlayer player, OfflinePlayer untrusted) { stmt.setObject(2, trustedUUID); stmt.execute(); } catch (SQLException err) { - LOGGER.error("Failed to remove data from the database", err); + Infuse.LOGGER.error("Failed to remove data from the database", err); } } catch (SQLException err) { - LOGGER.info("Failed to connect to database.", err); + Infuse.LOGGER.info("Failed to connect to database.", err); } } @@ -271,7 +268,7 @@ public boolean isTrusted(OfflinePlayer player, OfflinePlayer trusted) { Infuse.LOGGER.error("Failed to execute SQL \"{}\"", selectStr, e); } } catch (SQLException err) { - LOGGER.info("Failed to connect to database.", err); + Infuse.LOGGER.info("Failed to connect to database.", err); } return false; From 1325497396511024c1ac9f128625c6a49066b7d1 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 13:11:03 -0400 Subject: [PATCH 27/37] Removing plugin enabled checks and fixing YamlDataManager#createFile --- .../infuseSMP/playerdata/YamlDataManager.java | 32 ++----------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java index e1909b86..e55c9d68 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java @@ -24,25 +24,20 @@ public class YamlDataManager implements DataManager { private final YamlConfiguration config; public YamlDataManager(Infuse plugin) { - this.plugin = plugin; + this.plugin = plugin; this.dataFile = new File(plugin.getDataFolder(), "data/playerdata.yml"); this.config = YamlConfiguration.loadConfiguration(dataFile); } @Override public void load() { - if (!plugin.isEnabled()) { - Infuse.LOGGER.error("Infuse not loaded, cannot load {}.", dataFile.getName()); - return; - } - // Creating the file if it doesn't exist. createFile(); // Loading the config try { config.load(dataFile); - Infuse.LOGGER.info("Successfully loaded {}", dataFile.getName()); + Infuse.LOGGER.info("Successfully loaded YAML data!"); } catch (InvalidConfigurationException err) { Infuse.LOGGER.warn("{} contains an invalid YAML configuration. Verify the contents of the file.", dataFile.getName()); } catch (IOException err) { @@ -52,12 +47,6 @@ public void load() { } public void save() { - // Getting a plugin instance to use - if (!plugin.isEnabled()) { - Infuse.LOGGER.error("Infuse not loaded, cannot save the {}.", dataFile.getName()); - return; - } - // Creating the file if it doesn't exist. createFile(); @@ -73,22 +62,7 @@ public void save() { /** Creates the config file. If it doesn't exist, it loads the default config. */ public void createFile() { - // Getting a plugin instance to use - if (!plugin.isEnabled()) { - Infuse.LOGGER.error("Infuse not loaded, cannot create default {}.", dataFile.getName()); - return; - } - - // Creating the file if it doesn't exist. - if (!dataFile.exists()) { - try { - dataFile.getParentFile().mkdirs(); - dataFile.createNewFile(); - } catch (IOException e) { - Infuse.LOGGER.error("Could not create {}. Make sure the user has the right permissions.", dataFile.getName()); - } - } - + plugin.saveResource("config.yml", false); } @Override From 6fc7b1f7872b603df2bf91aac7259916fab063f9 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 13:11:17 -0400 Subject: [PATCH 28/37] Adding a config for the storage mode --- src/main/resources/config.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index e3492e76..bafd6475 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -27,6 +27,15 @@ player_head_drops: true enable_discord_broadcasts: false +# Sets where the data will be stored. +# IMPORTANT: Data is not transferred between nodes. To move data to different storage types, export it to YAML then import it. +# (Exported data is the same format as the YAML storage mode, so no exporting is needed if you already use the YAML config.) +# This config IS NOT UPDATED when you use `/infuse reload`. You need to RESTART THE SERVER to change this config +# Supported values: +# - "H2" +# - "YAML" +storage_mode: YAML + discord_webhook_url: "" brewing_gui: true From e02286ed02ee654f2219761a05446da890d62be5 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 13:21:26 -0400 Subject: [PATCH 29/37] Adding the storage_mode config to the MainConfig class and parsing it in Infuse#onEnable --- .../java/com/catadmirer/infuseSMP/Infuse.java | 30 +++++++---- .../com/catadmirer/infuseSMP/MainConfig.java | 51 ++++++++++++------- 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/Infuse.java b/src/main/java/com/catadmirer/infuseSMP/Infuse.java index 93f0bdb0..fb542934 100644 --- a/src/main/java/com/catadmirer/infuseSMP/Infuse.java +++ b/src/main/java/com/catadmirer/infuseSMP/Infuse.java @@ -7,6 +7,7 @@ import com.catadmirer.infuseSMP.managers.*; import com.catadmirer.infuseSMP.placeholders.InfusePlaceholders; import com.catadmirer.infuseSMP.playerdata.DataManager; +import com.catadmirer.infuseSMP.playerdata.H2DataManager; import com.catadmirer.infuseSMP.playerdata.YamlDataManager; import com.google.gson.Gson; import com.google.gson.JsonArray; @@ -43,7 +44,7 @@ public class Infuse extends JavaPlugin implements Listener { public static final Logger LOGGER = LoggerFactory.getLogger("Infuse"); public static final NamespacedKey EFFECT_KEY = new NamespacedKey("infuse", "effect_key"); - private final DataManager dataManager; + private DataManager dataManager; private final MainConfig mainConfig; private final GlobalLoop loop; private final RecipeManager recipeManager; @@ -56,7 +57,6 @@ public static Infuse getInstance() { public Infuse() { new ApophisManager(this); this.mainConfig = new MainConfig(this); - this.dataManager = new YamlDataManager(this); this.loop = new GlobalLoop(this); this.recipeManager = new RecipeManager(this); this.particleManager = new ParticleManager(this); @@ -76,13 +76,26 @@ public void onEnable() { // Loading the config mainConfig.load(); - - // Loading the data manager - dataManager.load(); // Applying config updates MessageConfig.applyUpdates(); mainConfig.applyUpdates(); + + // Loading the data manager + // If no valid data manager is found, disable the plugin + dataManager = switch (mainConfig.storageMode().toLowerCase()) { + case "h2" -> new H2DataManager(this); + case "yaml" -> new YamlDataManager(this); + default -> null; + }; + + if (dataManager == null) { + LOGGER.error("Could not read a valid storage type from the config! Disabling Infuse."); + Bukkit.getPluginManager().disablePlugin(this); + return; + } + + dataManager.load(); dataManager.applyUpdates(); // Initializing the recipe manager @@ -164,7 +177,7 @@ private void registerCommands() { } // Setting the control mode for the player - dataManager.setControlMode(player.getUniqueId(), choice); + dataManager.setControlMode(player, choice); player.addAttachment(this, "ability.use", choice.equals("command")); return true; }); @@ -305,9 +318,8 @@ private void onJoin(PlayerJoinEvent event) { InfuseEffect.getRegisteredEffects().values().stream().map(recipeManager::getRecipeKey).forEach(player::discoverRecipe); // Telling the player their current control mode - String controlMode = dataManager.getControlMode(player.getUniqueId()); - if (controlMode == null) controlMode = "Offhand"; - boolean offhandEnabled = controlMode.equalsIgnoreCase("Offhand"); + String controlMode = dataManager.getControlMode(player); + boolean offhandEnabled = controlMode.equalsIgnoreCase("offhand"); player.addAttachment(this, "ability.use", !offhandEnabled); Message msg = new Message(MessageType.JOIN_ABILITY_NOTIFY); diff --git a/src/main/java/com/catadmirer/infuseSMP/MainConfig.java b/src/main/java/com/catadmirer/infuseSMP/MainConfig.java index 8a97e541..7e980444 100644 --- a/src/main/java/com/catadmirer/infuseSMP/MainConfig.java +++ b/src/main/java/com/catadmirer/infuseSMP/MainConfig.java @@ -57,7 +57,7 @@ public boolean load() { /** * Writes the config to the file. - * + * * @return Whether or not the config was successfully written. */ public boolean save() { @@ -150,9 +150,8 @@ public boolean enableThief() { /** * Gets the amount of each effect that can be crafted - * + * * @param effect The effect to check - * * @return The number of effects that can be crafted of the specified {@link InfuseEffect}. */ public int getCraftLimit(InfuseEffect effect) { @@ -224,22 +223,6 @@ public float emeraldPercentExpToShare() { return Math.clamp((float) config.getDouble("emerald.percent_xp_to_share"), 0, 1); } - public void applyUpdates() { - if (!config.contains("invis_deaths")) config.set("invis_deaths", null); - if (!config.contains("invis.hide_kills")) config.set("invis.hide_kills", false); - if (!config.contains("invis.hide_deaths")) config.set("invis.hide_deaths", false); - if (!config.contains("haste.enchantment.looting_level")) config.set("haste.enchantment.looting_level", 5); - if (!config.contains("haste.enchantment.fortune_level")) config.set("haste.enchantment.fortune_level", 5); - if (!config.contains("haste.enchantment.efficiency_level")) config.set("haste.enchantment.efficiency_level", 10); - if (!config.contains("haste.enchantment.unbreaking_level")) config.set("haste.enchantment.unbreaking_level", 5); - if (!config.contains("hit_counter_decay_seconds")) config.set("hit_counter_decay_seconds", 15); - if (!config.contains("emerald.xp_stolen_per_hit")) config.set("emerald.xp_stolen_per_hit", 15); - if (!config.contains("emerald.xp_stolen_percent")) config.set("emerald.xp_stolen_percent", 1); - if (!config.contains("emerald.percent_xp_to_share")) config.set("emerald.percent_xp_to_share", 0.5); - - save(); - } - public int emeraldLootingLevel() { return config.getInt("emerald.enchantment.looting_level"); } @@ -255,4 +238,34 @@ public int hasteEfficiencyLevel() { public int hasteUnbreakingLevel() { return config.getInt("haste.enchantment.unbreaking_level"); } + + public String storageMode() { + return config.getString("storage_mode", "yaml"); + } + + public void applyUpdates() { + if (!config.contains("invis_deaths")) config.set("invis_deaths", null); + if (!config.contains("invis.hide_kills")) config.set("invis.hide_kills", false); + if (!config.contains("invis.hide_deaths")) config.set("invis.hide_deaths", false); + if (!config.contains("haste.enchantment.looting_level")) config.set("haste.enchantment.looting_level", 5); + if (!config.contains("haste.enchantment.fortune_level")) config.set("haste.enchantment.fortune_level", 5); + if (!config.contains("haste.enchantment.efficiency_level")) config.set("haste.enchantment.efficiency_level", 10); + if (!config.contains("haste.enchantment.unbreaking_level")) config.set("haste.enchantment.unbreaking_level", 5); + if (!config.contains("hit_counter_decay_seconds")) config.set("hit_counter_decay_seconds", 15); + if (!config.contains("emerald.xp_stolen_per_hit")) config.set("emerald.xp_stolen_per_hit", 15); + if (!config.contains("emerald.xp_stolen_percent")) config.set("emerald.xp_stolen_percent", 1); + if (!config.contains("emerald.percent_xp_to_share")) config.set("emerald.percent_xp_to_share", 0.5); + if (!config.contains("storage_mode")) { + config.set("storage_mode", "YAML"); + config.setComments("storage_mode", List.of("# Sets where the data will be stored.", + "# IMPORTANT: Data is not transferred between nodes. To move data to different storage types, export it to YAML then import it.", + "# (Exported data is the same format as the YAML storage mode, so no exporting is needed if you already use the YAML config.)", + "# This config IS NOT UPDATED when you use `/infuse reload`. You need to RESTART THE SERVER to change this config", + "# Supported values:", + "# - \"H2\"", + "# - \"YAML\"")); + } + + save(); + } } From 1294fbc50114247c91e955e702354f03538a63a2 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 13:52:00 -0400 Subject: [PATCH 30/37] Resolving various ide warnings and fixing some DataManager usage errors --- build.gradle.kts | 1 + gradle/libs.versions.toml | 2 +- .../catadmirer/infuseSMP/EffectConstants.java | 40 ++++++------- .../com/catadmirer/infuseSMP/EquipEffect.java | 16 ++--- .../com/catadmirer/infuseSMP/GlobalLoop.java | 4 +- .../com/catadmirer/infuseSMP/HitTracker.java | 4 +- .../java/com/catadmirer/infuseSMP/Infuse.java | 12 ++-- .../com/catadmirer/infuseSMP/MainConfig.java | 8 +-- .../com/catadmirer/infuseSMP/Message.java | 6 +- .../catadmirer/infuseSMP/MessageConfig.java | 4 +- .../PlayerSwapHandItemsListener.java | 8 +-- .../infuseSMP/commands/Abilities.java | 8 +-- .../infuseSMP/commands/ClearEffects.java | 4 +- .../infuseSMP/commands/DrainCommand.java | 4 +- .../infuseSMP/commands/InfuseCommand.java | 8 +-- .../infuseSMP/commands/Recipes.java | 2 + .../infuseSMP/commands/SwapEffects.java | 10 ++-- .../infuseSMP/commands/TrustCommand.java | 4 +- .../catadmirer/infuseSMP/effects/Emerald.java | 7 ++- .../catadmirer/infuseSMP/effects/Ender.java | 5 ++ .../catadmirer/infuseSMP/effects/Feather.java | 12 +--- .../catadmirer/infuseSMP/effects/Frost.java | 1 + .../catadmirer/infuseSMP/effects/Heart.java | 2 +- .../infuseSMP/effects/InfuseEffect.java | 4 +- .../catadmirer/infuseSMP/effects/Regen.java | 4 +- .../infuseSMP/effects/Strength.java | 4 +- .../catadmirer/infuseSMP/effects/Thunder.java | 8 +-- .../infuseSMP/managers/ActionBarUpdater.java | 10 ++-- .../infuseSMP/managers/ApophisManager.java | 13 +++-- .../infuseSMP/managers/CooldownManager.java | 3 +- .../managers/EffectCraftManager.java | 19 +++--- .../infuseSMP/managers/ParticleManager.java | 2 +- .../infuseSMP/managers/RecipeManager.java | 7 ++- .../placeholders/InfusePlaceholders.java | 58 +++++++++---------- .../infuseSMP/playerdata/DataManager.java | 5 -- .../infuseSMP/playerdata/H2DataManager.java | 3 - .../infuseSMP/playerdata/YamlDataManager.java | 2 +- .../infuseSMP/util/InventoryUtils.java | 4 +- 38 files changed, 147 insertions(+), 171 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 5a1f5533..0e34b925 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -49,4 +49,5 @@ tasks.processResources { tasks.register("resetAndRun") { delete("run/plugins/$rootProject.name") finalizedBy("runServer") + description = "Resets the plugin's data directory and then runs a server" } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 945b8c6e..2f6f2070 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ minecraft = "26.1.2" placeholderapi = "2.11.6" run-paper = "3.0.2" paperweight = "2.0.0-beta.21" -h2 = "2.1.214" +h2 = "2.4.240" [plugins] paperweight = { id = "io.papermc.paperweight.userdev", version.ref = "paperweight" } diff --git a/src/main/java/com/catadmirer/infuseSMP/EffectConstants.java b/src/main/java/com/catadmirer/infuseSMP/EffectConstants.java index b05cc881..d2d99cc3 100644 --- a/src/main/java/com/catadmirer/infuseSMP/EffectConstants.java +++ b/src/main/java/com/catadmirer/infuseSMP/EffectConstants.java @@ -19,16 +19,16 @@ public static Material menuBackgroundColor(int effectId) { case EffectIds.EMERALD -> Material.LIME_STAINED_GLASS_PANE; case EffectIds.ENDER -> Material.PURPLE_STAINED_GLASS_PANE; case EffectIds.FEATHER -> Material.WHITE_STAINED_GLASS_PANE; - case EffectIds.FIRE -> Material.ORANGE_STAINED_GLASS_PANE; - case EffectIds.FROST -> Material.LIGHT_BLUE_STAINED_GLASS_PANE; - case EffectIds.HASTE -> Material.ORANGE_STAINED_GLASS_PANE; - case EffectIds.HEART -> Material.RED_STAINED_GLASS_PANE; + case EffectIds.FIRE, + EffectIds.HASTE -> Material.ORANGE_STAINED_GLASS_PANE; + case EffectIds.FROST, + EffectIds.SPEED -> Material.LIGHT_BLUE_STAINED_GLASS_PANE; + case EffectIds.HEART, + EffectIds.REGEN, + EffectIds.STRENGTH, + EffectIds.THIEF -> Material.RED_STAINED_GLASS_PANE; case EffectIds.INVIS -> Material.LIGHT_GRAY_STAINED_GLASS_PANE; case EffectIds.OCEAN -> Material.BLUE_STAINED_GLASS_PANE; - case EffectIds.REGEN -> Material.RED_STAINED_GLASS_PANE; - case EffectIds.SPEED -> Material.LIGHT_BLUE_STAINED_GLASS_PANE; - case EffectIds.STRENGTH -> Material.RED_STAINED_GLASS_PANE; - case EffectIds.THIEF -> Material.RED_STAINED_GLASS_PANE; case EffectIds.THUNDER -> Material.YELLOW_STAINED_GLASS_PANE; default -> null; }; @@ -88,21 +88,21 @@ public static Color potionColor(int effectId) { */ public static BossBar.Color ritualColor(int effectId) { return switch (effectId) { - case EffectIds.APOPHIS -> BossBar.Color.PURPLE; + case EffectIds.APOPHIS, + EffectIds.ENDER, + EffectIds.INVIS -> BossBar.Color.PURPLE; case EffectIds.EMERALD -> BossBar.Color.GREEN; - case EffectIds.ENDER -> BossBar.Color.PURPLE; case EffectIds.FEATHER -> BossBar.Color.WHITE; - case EffectIds.FIRE -> BossBar.Color.RED; - case EffectIds.FROST -> BossBar.Color.BLUE; - case EffectIds.HASTE -> BossBar.Color.YELLOW; - case EffectIds.HEART -> BossBar.Color.RED; - case EffectIds.INVIS -> BossBar.Color.PURPLE; - case EffectIds.OCEAN -> BossBar.Color.BLUE; + case EffectIds.FIRE, + EffectIds.HEART, + EffectIds.STRENGTH, + EffectIds.THIEF -> BossBar.Color.RED; + case EffectIds.FROST, + EffectIds.OCEAN -> BossBar.Color.BLUE; + case EffectIds.HASTE, + EffectIds.SPEED, + EffectIds.THUNDER -> BossBar.Color.YELLOW; case EffectIds.REGEN -> BossBar.Color.PINK; - case EffectIds.SPEED -> BossBar.Color.YELLOW; - case EffectIds.STRENGTH -> BossBar.Color.RED; - case EffectIds.THIEF -> BossBar.Color.RED; - case EffectIds.THUNDER -> BossBar.Color.YELLOW; default -> null; }; } diff --git a/src/main/java/com/catadmirer/infuseSMP/EquipEffect.java b/src/main/java/com/catadmirer/infuseSMP/EquipEffect.java index 56174105..d3fdc4bc 100644 --- a/src/main/java/com/catadmirer/infuseSMP/EquipEffect.java +++ b/src/main/java/com/catadmirer/infuseSMP/EquipEffect.java @@ -60,11 +60,11 @@ public void safeEquip(Player player, InfuseEffect effect) { */ private boolean equipEffect(Player player, InfuseEffect effect, String slot) { // Checking for an effect in the slot. - InfuseEffect currentEffect = plugin.getDataManager().getEffect(player.getUniqueId(), slot); + InfuseEffect currentEffect = plugin.getDataManager().getEffect(player, slot); if (currentEffect != null) return false; // Equipping the effect to the slot. - plugin.getDataManager().setEffect(player.getUniqueId(), slot, effect); + plugin.getDataManager().setEffect(player, slot, effect); new EffectEquipEvent(player, effect, slot).callEvent(); Message msg = new Message(MessageType.EFFECT_EQUIPPED); @@ -111,8 +111,8 @@ public void onPlayerConsume(PlayerItemConsumeEvent event) { @EventHandler public void onPlayerDeath(PlayerDeathEvent event) { Player player = event.getEntity(); - InfuseEffect effect1 = plugin.getDataManager().getEffect(player.getUniqueId(), "1"); - InfuseEffect effect2 = plugin.getDataManager().getEffect(player.getUniqueId(), "2"); + InfuseEffect effect1 = plugin.getDataManager().getEffect(player, "1"); + InfuseEffect effect2 = plugin.getDataManager().getEffect(player, "2"); String dropMode = plugin.getMainConfig().effectDrops(); Random rand = new Random(); switch (dropMode.toLowerCase()) { @@ -153,10 +153,10 @@ public void onPlayerDeath(PlayerDeathEvent event) { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); - InfuseEffect effect = plugin.getDataManager().getEffect(player.getUniqueId(), "1"); + InfuseEffect effect = plugin.getDataManager().getEffect(player, "1"); if (effect != null) new EffectEquipEvent(player, effect, "1").callEvent(); - effect = plugin.getDataManager().getEffect(player.getUniqueId(), "2"); + effect = plugin.getDataManager().getEffect(player, "2"); if (effect != null) new EffectEquipEvent(player, effect, "2").callEvent(); } @@ -168,11 +168,11 @@ public void onPlayerJoin(PlayerJoinEvent event) { */ private void dropEffect(Player player, String slot) { // Getting the equipped effect from the data file. - InfuseEffect effect = plugin.getDataManager().getEffect(player.getUniqueId(), slot); + InfuseEffect effect = plugin.getDataManager().getEffect(player, slot); if (effect == null) return; // Removing the effect from the player. - plugin.getDataManager().removeEffect(player.getUniqueId(), slot); + plugin.getDataManager().removeEffect(player, slot); new EffectUnequipEvent(player, effect, slot).callEvent(); // Dropping the effect item at the player's location diff --git a/src/main/java/com/catadmirer/infuseSMP/GlobalLoop.java b/src/main/java/com/catadmirer/infuseSMP/GlobalLoop.java index 8d9c3f3e..788716ce 100644 --- a/src/main/java/com/catadmirer/infuseSMP/GlobalLoop.java +++ b/src/main/java/com/catadmirer/infuseSMP/GlobalLoop.java @@ -30,8 +30,8 @@ public void stop() { public void run() { for (Player player : Bukkit.getOnlinePlayers()) { // Getting the player's equipped effects - InfuseEffect lEffect = plugin.getDataManager().getEffect(player.getUniqueId(), "1"); - InfuseEffect rEffect = plugin.getDataManager().getEffect(player.getUniqueId(), "2"); + InfuseEffect lEffect = plugin.getDataManager().getEffect(player, "1"); + InfuseEffect rEffect = plugin.getDataManager().getEffect(player, "2"); // Applying passive effects to the player if (lEffect != null) { diff --git a/src/main/java/com/catadmirer/infuseSMP/HitTracker.java b/src/main/java/com/catadmirer/infuseSMP/HitTracker.java index 04887ad3..18a4a4e7 100644 --- a/src/main/java/com/catadmirer/infuseSMP/HitTracker.java +++ b/src/main/java/com/catadmirer/infuseSMP/HitTracker.java @@ -16,7 +16,7 @@ public class HitTracker implements Listener { private final Infuse plugin; private final Map hitTracker = new HashMap<>(); - Queue decayQueue = new ConcurrentLinkedQueue<>(); + final Queue decayQueue = new ConcurrentLinkedQueue<>(); public HitTracker(Infuse plugin) { this.plugin = plugin; @@ -89,7 +89,7 @@ public void onPlayerHit(EntityDamageByEntityEvent event) { decayQueue.remove(); decayTask.run(); } - }, hitCounterDecaySeconds * 20); + }, hitCounterDecaySeconds * 20L); } /** diff --git a/src/main/java/com/catadmirer/infuseSMP/Infuse.java b/src/main/java/com/catadmirer/infuseSMP/Infuse.java index fb542934..aadc6e8b 100644 --- a/src/main/java/com/catadmirer/infuseSMP/Infuse.java +++ b/src/main/java/com/catadmirer/infuseSMP/Infuse.java @@ -154,7 +154,7 @@ private void registerCommands() { getCommand("draw").setExecutor(new Draw()); - getCommand("controls").setExecutor((sender, command, label, args) -> { + getCommand("controls").setExecutor((sender, _, _, args) -> { // Making sure only players can run the command if (!(sender instanceof Player player)) { sender.sendMessage(new Message(MessageType.ERROR_NOT_PLAYER).toComponent()); @@ -181,7 +181,7 @@ private void registerCommands() { player.addAttachment(this, "ability.use", choice.equals("command")); return true; }); - getCommand("controls").setTabCompleter((sender, command, label, args) -> { + getCommand("controls").setTabCompleter((_, _, _, args) -> { if (args.length == 1) { return Stream.of("command", "offhand").filter(opt -> opt.startsWith(args[0])).toList(); } @@ -257,9 +257,7 @@ public void onPlayerDeath(PlayerDeathEvent event) { if (dropHead) { ItemStack playerHead = new ItemStack(Material.PLAYER_HEAD); - playerHead.editMeta(SkullMeta.class, meta -> { - meta.setOwningPlayer(player); - }); + playerHead.editMeta(SkullMeta.class, meta -> meta.setOwningPlayer(player)); player.getWorld().dropItem(player.getLocation(), playerHead); } } @@ -276,9 +274,7 @@ private String getLatestVersion() { .uri(URI.create("https://api.modrinth.com/v2/project/infusesmp/version")) .build(); - HttpClient client = HttpClient.newHttpClient(); - - try { + try (HttpClient client = HttpClient.newHttpClient()) { HttpResponse response = client.send(request, BodyHandlers.ofString()); // Handling http error codes diff --git a/src/main/java/com/catadmirer/infuseSMP/MainConfig.java b/src/main/java/com/catadmirer/infuseSMP/MainConfig.java index 7e980444..c93c8775 100644 --- a/src/main/java/com/catadmirer/infuseSMP/MainConfig.java +++ b/src/main/java/com/catadmirer/infuseSMP/MainConfig.java @@ -4,7 +4,6 @@ import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.plugin.Plugin; import java.io.File; import java.io.IOException; @@ -24,8 +23,6 @@ public MainConfig(Infuse plugin) { /** * Reloads the configuration. - * - * @return Whether the configuration was loaded successfully. */ public boolean load() { // Not doing anything if the plugin isn't enabled @@ -48,8 +45,7 @@ public boolean load() { } catch (InvalidConfigurationException e) { Infuse.LOGGER.warn("{} contains an invalid YAML configuration. Verify the contents of the file.", file.getName()); } catch (IOException e) { - Infuse.LOGGER.error("Could not find {}. Check that it exists.", file.getName()); - e.printStackTrace(); + Infuse.LOGGER.error("Could not find {}. Check that it exists.", file.getName(), e); } return false; @@ -57,8 +53,6 @@ public boolean load() { /** * Writes the config to the file. - * - * @return Whether or not the config was successfully written. */ public boolean save() { // Not doing anything if the plugin isn't enabled diff --git a/src/main/java/com/catadmirer/infuseSMP/Message.java b/src/main/java/com/catadmirer/infuseSMP/Message.java index 09585c96..3ae4f075 100644 --- a/src/main/java/com/catadmirer/infuseSMP/Message.java +++ b/src/main/java/com/catadmirer/infuseSMP/Message.java @@ -9,7 +9,7 @@ public class Message { private String message; - private List placeholders; + private final List placeholders; public Message(MessageType messageType) { message = MessageConfig.getMessage(messageType); @@ -53,7 +53,7 @@ public Component toComponent() { throw new IllegalStateException("Not all placeholders have been registered."); } - return MiniMessage.miniMessage().deserialize("" + toString()); + return MiniMessage.miniMessage().deserialize("" + this); } /** @@ -67,7 +67,7 @@ public static Component toComponent(String message) { return MiniMessage.miniMessage().deserialize("" + message); } - public static enum MessageType { + public enum MessageType { EFFECT_BROADCAST(List.of("player", "item", "x", "y", "z", "dimension"), "🧪 %player% is cooking up the %item% at %x%, %y%, %z%... %dimension%"), DISCORD_BROADCAST(List.of("player", "item", "x", "y", "z", "dimension"), "%player% is cooking up the %item% at %x%, %y%, %z% in %dimension% @everyone"), EFFECT_FINISHED(List.of("item"), "%item% has been brewed!"), diff --git a/src/main/java/com/catadmirer/infuseSMP/MessageConfig.java b/src/main/java/com/catadmirer/infuseSMP/MessageConfig.java index 041e75d2..a527f1af 100644 --- a/src/main/java/com/catadmirer/infuseSMP/MessageConfig.java +++ b/src/main/java/com/catadmirer/infuseSMP/MessageConfig.java @@ -52,8 +52,8 @@ public static boolean load(Plugin plugin) { * Creating the config file. If it doesn't exist, it loads the default config. If the file does * exist, it will only replace it if the parameter is true. * - * @param replace Whether or not to replace the config file with the default configs. - * @return Whether or not the file was created successfully. + * @param replace Whether to replace the config file with the default configs. + * @return Whether the file was created successfully. */ public static boolean createFile(Plugin plugin, boolean replace) { // Creating the file if it doesn't exist. diff --git a/src/main/java/com/catadmirer/infuseSMP/PlayerSwapHandItemsListener.java b/src/main/java/com/catadmirer/infuseSMP/PlayerSwapHandItemsListener.java index 6ea69b3c..170edb78 100644 --- a/src/main/java/com/catadmirer/infuseSMP/PlayerSwapHandItemsListener.java +++ b/src/main/java/com/catadmirer/infuseSMP/PlayerSwapHandItemsListener.java @@ -18,7 +18,7 @@ public PlayerSwapHandItemsListener(DataManager dataManager) { /** * Listens for when the player swaps the items in their main and offhand. - * When they do so, it will be used to activate their left or right spark based on whether or not they are crouching. + * When they do so, it will be used to activate their left or right spark based on whether they are crouching. * * @param event The {@link PlayerSwapHandItemsEvent} to process */ @@ -26,11 +26,11 @@ public PlayerSwapHandItemsListener(DataManager dataManager) { public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) { Player player = event.getPlayer(); UUID playerUUID = player.getUniqueId(); - String data = dataManager.getControlMode(playerUUID); + String data = dataManager.getControlMode(player); if (data.equals("offhand")) { // Getting the effect equipped in each slot - InfuseEffect lEffect = dataManager.getEffect(player.getUniqueId(), "1"); - InfuseEffect rEffect = dataManager.getEffect(player.getUniqueId(), "2"); + InfuseEffect lEffect = dataManager.getEffect(player, "1"); + InfuseEffect rEffect = dataManager.getEffect(player, "2"); // Activating the left effect's spark if the player was sneaking and the effect wasn't on cooldown. if (lEffect != null && !player.isSneaking() && !CooldownManager.isOnCooldown(playerUUID, lEffect.getKey())) { diff --git a/src/main/java/com/catadmirer/infuseSMP/commands/Abilities.java b/src/main/java/com/catadmirer/infuseSMP/commands/Abilities.java index fd19ffbf..3fa3a5f8 100644 --- a/src/main/java/com/catadmirer/infuseSMP/commands/Abilities.java +++ b/src/main/java/com/catadmirer/infuseSMP/commands/Abilities.java @@ -8,9 +8,9 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jspecify.annotations.NullMarked; -import java.util.UUID; - +@NullMarked public class Abilities implements CommandExecutor { private final Infuse plugin; @@ -24,8 +24,6 @@ public boolean onCommand(CommandSender sender, Command command, String label, St return true; } - final UUID playerUUID = player.getUniqueId(); - // Finding which slot to activate the spark for. String slot; if (label.contains("lspark")) { @@ -38,7 +36,7 @@ public boolean onCommand(CommandSender sender, Command command, String label, St } // Getting the name of the equipped effect. - InfuseEffect equippedEffect = plugin.getDataManager().getEffect(playerUUID, slot); + InfuseEffect equippedEffect = plugin.getDataManager().getEffect(player, slot); // Handling if the slot is empty. if (equippedEffect == null) { diff --git a/src/main/java/com/catadmirer/infuseSMP/commands/ClearEffects.java b/src/main/java/com/catadmirer/infuseSMP/commands/ClearEffects.java index 0a99d7b5..da462d87 100644 --- a/src/main/java/com/catadmirer/infuseSMP/commands/ClearEffects.java +++ b/src/main/java/com/catadmirer/infuseSMP/commands/ClearEffects.java @@ -28,8 +28,8 @@ public boolean onCommand(@NonNull CommandSender sender, @NonNull Command command Player target = Bukkit.getPlayer(args[0]); if (target != null) { - dataManager.removeEffect(target.getUniqueId(), "1"); - dataManager.removeEffect(target.getUniqueId(), "2"); + dataManager.removeEffect(target, "1"); + dataManager.removeEffect(target, "2"); } return true; diff --git a/src/main/java/com/catadmirer/infuseSMP/commands/DrainCommand.java b/src/main/java/com/catadmirer/infuseSMP/commands/DrainCommand.java index 45c11276..cd798b4f 100644 --- a/src/main/java/com/catadmirer/infuseSMP/commands/DrainCommand.java +++ b/src/main/java/com/catadmirer/infuseSMP/commands/DrainCommand.java @@ -36,7 +36,7 @@ public boolean onCommand(@NonNull CommandSender sender, @NonNull Command command } // Getting the mapping from the slot - InfuseEffect effect = plugin.getDataManager().getEffect(player.getUniqueId(), slot); + InfuseEffect effect = plugin.getDataManager().getEffect(player, slot); // Handling an invalid or empty mapping if (effect == null) { @@ -55,7 +55,7 @@ public boolean onCommand(@NonNull CommandSender sender, @NonNull Command command } // Removing the effect from the player - plugin.getDataManager().removeEffect(player.getUniqueId(), slot); + plugin.getDataManager().removeEffect(player, slot); Message msg = new Message(MessageType.DRAIN_SUCCESS); msg.applyPlaceholder("effect_name", effect.getName()); player.sendMessage(msg.toComponent()); diff --git a/src/main/java/com/catadmirer/infuseSMP/commands/InfuseCommand.java b/src/main/java/com/catadmirer/infuseSMP/commands/InfuseCommand.java index 414bc62c..c3887aec 100644 --- a/src/main/java/com/catadmirer/infuseSMP/commands/InfuseCommand.java +++ b/src/main/java/com/catadmirer/infuseSMP/commands/InfuseCommand.java @@ -135,7 +135,7 @@ public boolean onCommand(@NonNull CommandSender sender, @NonNull Command command } // Setting the effect - plugin.getDataManager().setEffect(target.getUniqueId(), args[3], effect); + plugin.getDataManager().setEffect(target, args[3], effect); msg = new Message(MessageType.INFUSE_SETEFFECT_SUCCESS); msg.applyPlaceholder("slot", slot); msg.applyPlaceholder("player_name", target.getName()); @@ -161,8 +161,8 @@ public boolean onCommand(@NonNull CommandSender sender, @NonNull Command command } // Removing the effects from the player - plugin.getDataManager().removeEffect(target.getUniqueId(), "1"); - plugin.getDataManager().removeEffect(target.getUniqueId(), "2"); + plugin.getDataManager().removeEffect(target, "1"); + plugin.getDataManager().removeEffect(target, "2"); msg = new Message(MessageType.INFUSE_CLEAREFFECTS_SUCCESS); msg.applyPlaceholder("player_name", target.getName()); player.sendMessage(msg.toComponent()); @@ -205,7 +205,7 @@ public boolean onCommand(@NonNull CommandSender sender, @NonNull Command command } // Setting the control mode for the user. - plugin.getDataManager().setControlMode(player.getUniqueId(), choice); + plugin.getDataManager().setControlMode(player, choice); // Assigning the permission for offhand use if the user chose offhand mode boolean offhandEnabled = choice.equalsIgnoreCase("offhand"); diff --git a/src/main/java/com/catadmirer/infuseSMP/commands/Recipes.java b/src/main/java/com/catadmirer/infuseSMP/commands/Recipes.java index ba638a06..5c3b0b7a 100644 --- a/src/main/java/com/catadmirer/infuseSMP/commands/Recipes.java +++ b/src/main/java/com/catadmirer/infuseSMP/commands/Recipes.java @@ -20,6 +20,7 @@ import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jspecify.annotations.NullMarked; public class Recipes implements CommandExecutor, Listener { private static Infuse plugin; @@ -28,6 +29,7 @@ public Recipes(Infuse plugin) { Recipes.plugin = plugin; } + @NullMarked @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { if (sender instanceof Player player) { diff --git a/src/main/java/com/catadmirer/infuseSMP/commands/SwapEffects.java b/src/main/java/com/catadmirer/infuseSMP/commands/SwapEffects.java index e092a272..87405236 100644 --- a/src/main/java/com/catadmirer/infuseSMP/commands/SwapEffects.java +++ b/src/main/java/com/catadmirer/infuseSMP/commands/SwapEffects.java @@ -8,7 +8,9 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jspecify.annotations.NullMarked; +@NullMarked public class SwapEffects implements CommandExecutor { private final Infuse plugin; @@ -24,12 +26,12 @@ public boolean onCommand(CommandSender sender, Command command, String label, St } // Getting the equipped effects - InfuseEffect effect1 = plugin.getDataManager().getEffect(player.getUniqueId(), "1"); - InfuseEffect effect2 = plugin.getDataManager().getEffect(player.getUniqueId(), "2"); + InfuseEffect effect1 = plugin.getDataManager().getEffect(player, "1"); + InfuseEffect effect2 = plugin.getDataManager().getEffect(player, "2"); // Swapping the effects - plugin.getDataManager().setEffect(player.getUniqueId(), "1", effect2); - plugin.getDataManager().setEffect(player.getUniqueId(), "2", effect1); + plugin.getDataManager().setEffect(player, "1", effect2); + plugin.getDataManager().setEffect(player, "2", effect1); player.sendMessage(new Message(MessageType.SWAP_SUCCESS).toComponent()); return true; } diff --git a/src/main/java/com/catadmirer/infuseSMP/commands/TrustCommand.java b/src/main/java/com/catadmirer/infuseSMP/commands/TrustCommand.java index 459bc7b4..637f10eb 100644 --- a/src/main/java/com/catadmirer/infuseSMP/commands/TrustCommand.java +++ b/src/main/java/com/catadmirer/infuseSMP/commands/TrustCommand.java @@ -8,7 +8,9 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jspecify.annotations.NullMarked; +@NullMarked public class TrustCommand implements CommandExecutor { private final DataManager dataManager; @@ -39,7 +41,7 @@ public boolean onCommand(CommandSender sender, Command command, String label, St return true; } - // Preventing the caster from trusting/untrusting themself. + // Preventing the caster from trusting/untrusting themselves. if (caster.getUniqueId().equals(target.getUniqueId())) { caster.sendMessage(new Message(MessageType.TRUST_SELF).toComponent()); return true; diff --git a/src/main/java/com/catadmirer/infuseSMP/effects/Emerald.java b/src/main/java/com/catadmirer/infuseSMP/effects/Emerald.java index 87c1d548..d7c53230 100644 --- a/src/main/java/com/catadmirer/infuseSMP/effects/Emerald.java +++ b/src/main/java/com/catadmirer/infuseSMP/effects/Emerald.java @@ -225,6 +225,7 @@ public void emeraldExpMultiplier(PlayerPickupExperienceEvent event) { orb.setExperience(newAmount); } + @SuppressWarnings("unchecked") @EventHandler public void emeraldEnchantBonus(PrepareItemEnchantEvent event) { ItemStack item = event.getItem(); @@ -278,15 +279,15 @@ public void emeraldEnchantBonus(PrepareItemEnchantEvent event) { if (!list.isEmpty()) { EnchantmentInstance enchantmentinstance = (EnchantmentInstance) list.get(random.nextInt(list.size())); - Holder enchantment = null; + Holder enchantment; int level; Class clazz = EnchantmentInstance.class; if (!clazz.isRecord()) { // Handling pre-1.21.5 - enchantment = (Holder) clazz.getField("enchantment").get(enchantmentinstance); - level = (int) clazz.getField("level").get(enchantmentinstance); + enchantment = (Holder) clazz.getDeclaredField("enchantment").get(enchantmentinstance); + level = (int) clazz.getDeclaredField("level").get(enchantmentinstance); } else { RecordComponent[] components = clazz.getRecordComponents(); enchantment = (Holder) components[0].getAccessor().invoke(enchantmentinstance); diff --git a/src/main/java/com/catadmirer/infuseSMP/effects/Ender.java b/src/main/java/com/catadmirer/infuseSMP/effects/Ender.java index 25a674c0..b964876b 100644 --- a/src/main/java/com/catadmirer/infuseSMP/effects/Ender.java +++ b/src/main/java/com/catadmirer/infuseSMP/effects/Ender.java @@ -181,6 +181,11 @@ public void onEntityDamage(EntityDamageEvent event) { if (cursedUUID == damagedUUID) continue; Player player = Bukkit.getPlayer(cursedUUID); + if (player == null) { + cursedPlayers.remove(cursedUUID); + continue; + } + player.damage(event.getDamage(), fakeSource); } } diff --git a/src/main/java/com/catadmirer/infuseSMP/effects/Feather.java b/src/main/java/com/catadmirer/infuseSMP/effects/Feather.java index 3a1caab9..51396a3a 100644 --- a/src/main/java/com/catadmirer/infuseSMP/effects/Feather.java +++ b/src/main/java/com/catadmirer/infuseSMP/effects/Feather.java @@ -73,9 +73,7 @@ public void activateSpark(Player owner) { CooldownManager.setTimes(playerUUID, "feather", duration, cooldown); - owner.getScheduler().runDelayed(plugin, t -> { - CooldownManager.setDuration(playerUUID, "feathermace", 5L); - }, null, 10); + owner.getScheduler().runDelayed(plugin, _ -> CooldownManager.setDuration(playerUUID, "feathermace", 5L), null, 10); } @Override @@ -121,9 +119,7 @@ public void FeatherLand(PlayerMoveEvent event) { Vector knockback = new Vector(0, 1, 0); target.setVelocity(target.getVelocity().add(knockback)); Location anchor = target.getLocation(); - Bukkit.getRegionScheduler().run(plugin, anchor, (task) -> { - target.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_FALLING, 80, 0, false, false, false)); - }); + Bukkit.getRegionScheduler().run(plugin, anchor, _ -> target.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_FALLING, 80, 0, false, false, false))); } world.spawnParticle(Particle.CLOUD, loc, 50, 0, 0, 0, 2); @@ -176,9 +172,7 @@ public void onPlayerRightClickWindcharge(PlayerInteractEvent event) { if (!event.getAction().isRightClick()) return; Location anchor = player.getLocation(); - Bukkit.getRegionScheduler().runDelayed(plugin, anchor, (task) -> { - player.setCooldown(Material.WIND_CHARGE, 5); - }, 1L); + Bukkit.getRegionScheduler().runDelayed(plugin, anchor, _ -> player.setCooldown(Material.WIND_CHARGE, 5), 1L); } @EventHandler diff --git a/src/main/java/com/catadmirer/infuseSMP/effects/Frost.java b/src/main/java/com/catadmirer/infuseSMP/effects/Frost.java index ab07ec92..9bb5a3d0 100644 --- a/src/main/java/com/catadmirer/infuseSMP/effects/Frost.java +++ b/src/main/java/com/catadmirer/infuseSMP/effects/Frost.java @@ -259,6 +259,7 @@ public void onPlayerAttack(EntityDamageByEntityEvent event) { if (!(event.getDamager() instanceof Player attacker)) return; if (!attacker.hasPotionEffect(PotionEffectType.UNLUCK)) return; PotionEffect effect = attacker.getPotionEffect(PotionEffectType.UNLUCK); + if (effect == null) return; if (effect.getAmplifier() >= 0 && frozenAttackers.contains(attacker.getUniqueId()) && event.getEntity() instanceof Player target) { target.setFreezeTicks(200); } diff --git a/src/main/java/com/catadmirer/infuseSMP/effects/Heart.java b/src/main/java/com/catadmirer/infuseSMP/effects/Heart.java index 7871c9df..fd72df5b 100644 --- a/src/main/java/com/catadmirer/infuseSMP/effects/Heart.java +++ b/src/main/java/com/catadmirer/infuseSMP/effects/Heart.java @@ -105,7 +105,7 @@ public Message getLore() { private void showAndUpdateHealthAboveEntity(Entity player) { Location ploc = player.getLocation().add(0, 2.5, 0); - TextDisplay as = (TextDisplay) ploc.getWorld().spawn(ploc, TextDisplay.class); + TextDisplay as = ploc.getWorld().spawn(ploc, TextDisplay.class); as.setGravity(false); as.setCustomNameVisible(true); diff --git a/src/main/java/com/catadmirer/infuseSMP/effects/InfuseEffect.java b/src/main/java/com/catadmirer/infuseSMP/effects/InfuseEffect.java index 0e2b9c5c..ae977fd2 100644 --- a/src/main/java/com/catadmirer/infuseSMP/effects/InfuseEffect.java +++ b/src/main/java/com/catadmirer/infuseSMP/effects/InfuseEffect.java @@ -159,7 +159,7 @@ public ItemStack createItem() { * * @param item The item to check. * - * @return Whether or not the item was created by this effect. + * @return Whether the item was created by this effect. */ public boolean itemMatches(@Nullable ItemStack item) { if (item == null) return false; @@ -187,7 +187,7 @@ public int serialize() { /** * Deserializes an InfuseEffect from an int - * + *

* The first two digits of an infuse effect are the effect id. IDs 0-12 are taken by the base Effects. * If the number is >= 100, then the effect will be converted to its augmented form. * diff --git a/src/main/java/com/catadmirer/infuseSMP/effects/Regen.java b/src/main/java/com/catadmirer/infuseSMP/effects/Regen.java index 0aa92b5c..e0ade51f 100644 --- a/src/main/java/com/catadmirer/infuseSMP/effects/Regen.java +++ b/src/main/java/com/catadmirer/infuseSMP/effects/Regen.java @@ -132,9 +132,7 @@ public void regenCanAlwaysEat(PlayerInteractEvent event) { meta.setFood(foodComp); }); } else { - event.getItem().editMeta(meta -> { - meta.setFood(null); - }); + event.getItem().editMeta(meta -> meta.setFood(null)); } } diff --git a/src/main/java/com/catadmirer/infuseSMP/effects/Strength.java b/src/main/java/com/catadmirer/infuseSMP/effects/Strength.java index 746e0812..41037eb7 100644 --- a/src/main/java/com/catadmirer/infuseSMP/effects/Strength.java +++ b/src/main/java/com/catadmirer/infuseSMP/effects/Strength.java @@ -169,8 +169,6 @@ public void strengthLengthenShieldCooldown(EntityDamageByEntityEvent event) { player.getWorld().playSound(player.getLocation(), Sound.ITEM_SHIELD_BREAK, 1, 1); // TODO: Test if this can be removed - Bukkit.getScheduler().runTaskLater(plugin, () -> { - player.setCooldown(Material.SHIELD, 200); - }, 20L); + Bukkit.getScheduler().runTaskLater(plugin, () -> player.setCooldown(Material.SHIELD, 200), 20L); } } \ No newline at end of file diff --git a/src/main/java/com/catadmirer/infuseSMP/effects/Thunder.java b/src/main/java/com/catadmirer/infuseSMP/effects/Thunder.java index fb3ac846..60a39019 100644 --- a/src/main/java/com/catadmirer/infuseSMP/effects/Thunder.java +++ b/src/main/java/com/catadmirer/infuseSMP/effects/Thunder.java @@ -146,7 +146,7 @@ public static void strikeLighting(LivingEntity target, LivingEntity attacker) { * This is a recursive function that runs up to 10 times to strike nearby entities with lightning. * The function should be called with a list containing only the attacking entity. * - * @param targets The list of targets that have been hit by the lightning bolt, with the exception of the first entry which is the attacker. + * @param targets The list of targets that have been hit by the lightning bolt, except for the first entry which is the attacker. * * @throws InvalidParameterException If the targets parameter is null or empty. */ @@ -176,8 +176,8 @@ private void chainLightning(List targets) { } } - //// Listeners //// - //// These are only registered once, so they need to be able to handle being used for every player, no matter what effects they actually have + // Listeners // + // These are only registered once, so they need to be able to handle being used for every player, no matter what effects they actually have /** * Tracking the number of hits a player has. @@ -253,7 +253,7 @@ public void onPlayerHit(EntityDamageByEntityEvent event) { decayQueue.remove(); decayTask.run(); } - }, hitCounterDecaySeconds * 20); + }, hitCounterDecaySeconds * 20L); } @EventHandler diff --git a/src/main/java/com/catadmirer/infuseSMP/managers/ActionBarUpdater.java b/src/main/java/com/catadmirer/infuseSMP/managers/ActionBarUpdater.java index 6d1346a2..a37d89e1 100644 --- a/src/main/java/com/catadmirer/infuseSMP/managers/ActionBarUpdater.java +++ b/src/main/java/com/catadmirer/infuseSMP/managers/ActionBarUpdater.java @@ -36,7 +36,7 @@ public void run() { String rightPad = ""; // Loading info for the first effect - effect = plugin.getDataManager().getEffect(uuid, "1"); + effect = plugin.getDataManager().getEffect(player, "1"); if (effect != null) { leftEmoji = effect.getIcon() + "\ue904"; @@ -55,7 +55,7 @@ public void run() { } // Loading info for the second effect - effect = plugin.getDataManager().getEffect(uuid, "2"); + effect = plugin.getDataManager().getEffect(player, "2"); if (effect != null) { rightEmoji = effect.getIcon() + "\ue904"; @@ -92,9 +92,9 @@ public void run2() { String placeholder = plugin.getMainConfig().emptyEffectIcon() ? "\uE901" : ""; - String lSide = ""; + String lSide; // Loading info for the first effect - effect = plugin.getDataManager().getEffect(uuid, "1"); + effect = plugin.getDataManager().getEffect(player, "1"); if (effect == null) { lSide = " " + placeholder + "\ue904"; } else { @@ -113,7 +113,7 @@ public void run2() { // Loading info for the second effect String rSide; - effect = plugin.getDataManager().getEffect(uuid, "2"); + effect = plugin.getDataManager().getEffect(player, "2"); if (effect == null) { rSide = "" + placeholder + "\ue904 "; } else { diff --git a/src/main/java/com/catadmirer/infuseSMP/managers/ApophisManager.java b/src/main/java/com/catadmirer/infuseSMP/managers/ApophisManager.java index d2a208db..464b1904 100644 --- a/src/main/java/com/catadmirer/infuseSMP/managers/ApophisManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/managers/ApophisManager.java @@ -17,8 +17,9 @@ import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; -public class ApophisManager { +public class ApophisManager implements Listener { private static final MiniMessage mm = MiniMessage.miniMessage(); private final Infuse plugin; @@ -46,7 +47,7 @@ public void initDisguise(Player target) { FileWriter writer = new FileWriter(disguiseFile); Optional textures = target.getPlayerProfile().getProperties().stream().filter(property -> "textures".equals(property.getName())).findFirst(); - // Writing the urls to disk + // Writing the URLs to disk writer.write(mm.serialize(target.displayName())); writer.write("\n"); if (textures.isEmpty()) { @@ -87,7 +88,7 @@ public void unequipApophis(EffectUnequipEvent event) { Player target = event.getPlayer(); if (!target.isOnline()) { - Infuse.LOGGER.warn("Could not remove {0}'s disguise as they are not online.", target.getName()); + Infuse.LOGGER.warn("Could not remove {}'s disguise as they are not online.", target.getName()); return; } @@ -124,13 +125,13 @@ public void unequipApophis(EffectUnequipEvent event) { profile.setProperty(new ProfileProperty("textures", value, signature)); target.setPlayerProfile(profile); - } catch (FileNotFoundException err) {} + } catch (FileNotFoundException err) { + Infuse.LOGGER.error("Could not find {}.", disguiseFile.getPath(), err); + } // Deleting the disguise file if (disguiseFile.exists()) { disguiseFile.delete(); } - - return; } } \ No newline at end of file diff --git a/src/main/java/com/catadmirer/infuseSMP/managers/CooldownManager.java b/src/main/java/com/catadmirer/infuseSMP/managers/CooldownManager.java index 11c7ba84..3ab978c9 100644 --- a/src/main/java/com/catadmirer/infuseSMP/managers/CooldownManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/managers/CooldownManager.java @@ -7,7 +7,6 @@ public class CooldownManager { private static final Map> cooldowns = new ConcurrentHashMap<>(); private static final Map> durations = new ConcurrentHashMap<>(); - public static final Map displayNames = new ConcurrentHashMap<>(); public static void setTimes(UUID playerUUID, String key, long durationSeconds, long cooldownSeconds) { setCooldown(playerUUID, key, cooldownSeconds + durationSeconds); @@ -75,7 +74,7 @@ public static void clearSpecificCooldown(UUID playerUUID, String key) { } } - public static void cleanupAllExpiredCooldowns() { + public static void cleanupExpiredCooldowns() { long currentTime = System.currentTimeMillis(); for (UUID playerUUID : cooldowns.keySet()) { diff --git a/src/main/java/com/catadmirer/infuseSMP/managers/EffectCraftManager.java b/src/main/java/com/catadmirer/infuseSMP/managers/EffectCraftManager.java index beba5310..b641d537 100644 --- a/src/main/java/com/catadmirer/infuseSMP/managers/EffectCraftManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/managers/EffectCraftManager.java @@ -71,8 +71,7 @@ private void sendToDiscord(String webhookUrl, String message) { .header("Content-Type", "application/json") .POST(BodyPublishers.ofString(payload)).build(); - HttpClient client = HttpClient.newHttpClient(); - try { + try (HttpClient client = HttpClient.newHttpClient()) { HttpResponse response = client.send(request, BodyHandlers.discarding()); // Checking the response status code @@ -80,7 +79,7 @@ private void sendToDiscord(String webhookUrl, String message) { if (status == 200) { Infuse.LOGGER.info("Message sent to Discord!"); } else { - Infuse.LOGGER.info("Error sending message to Discord: " + status); + Infuse.LOGGER.error("Error sending message to Discord: {}", status); } } catch (IOException err) { Infuse.LOGGER.error("Could not send webhook message to discord.", err); @@ -108,6 +107,10 @@ public void onCraft(CraftItemEvent event) { // Making sure the brewing stand is still placed Location brewerLocation = event.getInventory().getLocation(); + if (brewerLocation == null) { + return; + } + if (brewerLocation.getBlock().getType() != Material.BREWING_STAND) { event.setCancelled(true); return; @@ -158,9 +161,7 @@ public void onCraft(CraftItemEvent event) { } // Removing the ingredients - event.getInventory().forEach(item -> { - item.subtract(1); - }); + event.getInventory().forEach(item -> item.subtract(1)); // Closing the inventory player.closeInventory(); @@ -383,11 +384,7 @@ public void onBrewingStandBreak(BlockBreakEvent event) { @EventHandler public void onBrewingStandExplode(EntityExplodeEvent event) { List blocks = event.blockList(); - for (Block block : blocks) { - if (block.getLocation().equals(brewerLocation)) { - blocks.remove(block); - } - } + blocks.removeIf(block -> block.getLocation().equals(brewerLocation)); } @EventHandler(priority = EventPriority.LOW) diff --git a/src/main/java/com/catadmirer/infuseSMP/managers/ParticleManager.java b/src/main/java/com/catadmirer/infuseSMP/managers/ParticleManager.java index 568ac895..1a2d515b 100644 --- a/src/main/java/com/catadmirer/infuseSMP/managers/ParticleManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/managers/ParticleManager.java @@ -17,7 +17,7 @@ public ParticleManager(Infuse plugin) { } public void spawnEffectParticles(Player player, String slot) { - InfuseEffect effect = plugin.getDataManager().getEffect(player.getUniqueId(), slot); + InfuseEffect effect = plugin.getDataManager().getEffect(player, slot); if (effect == null) return; // Handling special particles for ender effect diff --git a/src/main/java/com/catadmirer/infuseSMP/managers/RecipeManager.java b/src/main/java/com/catadmirer/infuseSMP/managers/RecipeManager.java index 0ce950db..17cd6a32 100644 --- a/src/main/java/com/catadmirer/infuseSMP/managers/RecipeManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/managers/RecipeManager.java @@ -17,13 +17,12 @@ public class RecipeManager { private final Infuse plugin; - private final File recipesFile; private final FileConfiguration recipesConfig; public RecipeManager(Infuse plugin) { this.plugin = plugin; - recipesFile = new File(plugin.getDataFolder(), "recipes.yml"); + File recipesFile = new File(plugin.getDataFolder(), "recipes.yml"); if (!recipesFile.exists()) { plugin.saveResource("recipes.yml", false); } @@ -33,7 +32,7 @@ public RecipeManager(Infuse plugin) { /** * Manager functionality for when the plugin is reloaded. - * + *

* In this case, it unregisters all the recipes then adds them back. */ public void reload() { @@ -67,6 +66,8 @@ public ShapedRecipe getRecipe(InfuseEffect mapping) { effectRecipe.shape(recipesConfig.getStringList(baseKey + ".shape").toArray(String[]::new)); ConfigurationSection ingredientsConfig = recipesConfig.getConfigurationSection(baseKey + ".ingredients"); + if (ingredientsConfig == null) return effectRecipe; + for (String key : ingredientsConfig.getKeys(false)) { char ingredientLabel = key.charAt(0); String materialName = ingredientsConfig.getString(key); diff --git a/src/main/java/com/catadmirer/infuseSMP/placeholders/InfusePlaceholders.java b/src/main/java/com/catadmirer/infuseSMP/placeholders/InfusePlaceholders.java index 8b67c5f7..a525cc01 100644 --- a/src/main/java/com/catadmirer/infuseSMP/placeholders/InfusePlaceholders.java +++ b/src/main/java/com/catadmirer/infuseSMP/placeholders/InfusePlaceholders.java @@ -9,24 +9,28 @@ import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.NonNull; public class InfusePlaceholders extends PlaceholderExpansion { - private Infuse plugin; + private final Infuse plugin; public InfusePlaceholders(Infuse plugin) { this.plugin = plugin; } + @NonNull @Override public String getAuthor() { return "catadmirer"; } + @NonNull @Override public String getIdentifier() { return "infuse"; } + @NonNull @Override public String getVersion() { return plugin.getPluginMeta().getVersion(); @@ -34,32 +38,23 @@ public String getVersion() { @Override public String onRequest(OfflinePlayer player, @NotNull String params) { - UUID uuid = player.getUniqueId(); - - switch (params.toLowerCase()) { - case "first_effect": - return getEffectIcon(uuid, "1"); - case "second_effect": - return getEffectIcon(uuid, "2"); - case "first_time": - return getTime(uuid, "1"); - case "second_time": - return getTime(uuid, "2"); - case "first_effect_raw": - return getEffectRaw(uuid, "1"); - case "second_effect_raw": - return getEffectRaw(uuid, "2"); - case "first_effect_name": - return getEffectName(uuid, "1"); - case "second_effect_name": - return getEffectName(uuid, "2"); - } - - return null; + return switch (params.toLowerCase()) { + case "first_effect" -> getEffectIcon(player, "1"); + case "second_effect" -> getEffectIcon(player, "2"); + case "first_time" -> getTime(player, "1"); + case "second_time" -> getTime(player, "2"); + case "first_effect_raw" -> getEffectRaw(player, "1"); + case "second_effect_raw" -> getEffectRaw(player, "2"); + case "first_effect_name" -> getEffectName(player, "1"); + case "second_effect_name" -> getEffectName(player, "2"); + default -> null; + }; } - public String getEffectIcon(UUID uuid, String slot) { - InfuseEffect effect = plugin.getDataManager().getEffect(uuid, slot); + public String getEffectIcon(OfflinePlayer player, String slot) { + UUID uuid = player.getUniqueId(); + + InfuseEffect effect = plugin.getDataManager().getEffect(player, slot); if (effect == null) { return plugin.getMainConfig().emptyEffectIcon() ? "\uE901" : ""; @@ -68,8 +63,9 @@ public String getEffectIcon(UUID uuid, String slot) { return "" + (CooldownManager.isEffectActive(uuid, effect.getKey()) ? effect.getActiveIcon() : effect.getIcon()); } - public String getTime(UUID uuid, String slot) { - InfuseEffect effect = plugin.getDataManager().getEffect(uuid, slot); + public String getTime(OfflinePlayer player, String slot) { + UUID uuid = player.getUniqueId(); + InfuseEffect effect = plugin.getDataManager().getEffect(player, slot); if (effect == null) return ""; String key = effect.getKey(); if (CooldownManager.isEffectActive(uuid, key)) { @@ -83,15 +79,15 @@ public String getTime(UUID uuid, String slot) { } } - public String getEffectRaw(UUID uuid, String slot) { - InfuseEffect effect = plugin.getDataManager().getEffect(uuid, slot); + public String getEffectRaw(OfflinePlayer player, String slot) { + InfuseEffect effect = plugin.getDataManager().getEffect(player, slot); if (effect== null) return ""; return PlainTextComponentSerializer.plainText().serialize(effect.getName().toComponent()); } - public String getEffectName(UUID uuid, String slot) { - InfuseEffect effect = plugin.getDataManager().getEffect(uuid, slot); + public String getEffectName(OfflinePlayer player, String slot) { + InfuseEffect effect = plugin.getDataManager().getEffect(player, slot); if (effect == null) return ""; return effect.getName().toString(); diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java index a95f9f2c..a8393bc5 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataManager.java @@ -14,11 +14,6 @@ public interface DataManager { */ void load(); - /** - * Writes the config to the file. - */ - void save(); - /** * Gets the number of effects that exist. * diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java index e6c7946a..a4afe575 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java @@ -63,9 +63,6 @@ public void load() { } } - @Override - public void save() {} - @Override public int getExistingCount(InfuseEffect effect) { String sql = "SELECT crafted FROM crafted_effects WHERE effect = ?;"; diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java index e55c9d68..e09c4b33 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/YamlDataManager.java @@ -46,7 +46,7 @@ public void load() { } - public void save() { + private void save() { // Creating the file if it doesn't exist. createFile(); diff --git a/src/main/java/com/catadmirer/infuseSMP/util/InventoryUtils.java b/src/main/java/com/catadmirer/infuseSMP/util/InventoryUtils.java index 74cdb533..d3073f12 100644 --- a/src/main/java/com/catadmirer/infuseSMP/util/InventoryUtils.java +++ b/src/main/java/com/catadmirer/infuseSMP/util/InventoryUtils.java @@ -69,9 +69,7 @@ public static void fillRemainingSlots(Inventory inventory) { public static void lockInventory(Inventory inventory) { for (ItemStack item : inventory.getContents()) { if (item == null) continue; - item.editMeta(meta -> { - meta.setMaxStackSize(1); - }); + item.editMeta(meta -> meta.setMaxStackSize(1)); } } } \ No newline at end of file From 2f67945eeb81ec09cd7dd7185f05e9ec8ca8da84 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 16:44:37 -0400 Subject: [PATCH 31/37] Adding the DataCache class for in-memory storage --- .../infuseSMP/playerdata/DataCache.java | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 src/main/java/com/catadmirer/infuseSMP/playerdata/DataCache.java diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataCache.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataCache.java new file mode 100644 index 00000000..5ab1ea95 --- /dev/null +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataCache.java @@ -0,0 +1,100 @@ +package com.catadmirer.infuseSMP.playerdata; + +import com.catadmirer.infuseSMP.Infuse; +import com.catadmirer.infuseSMP.effects.InfuseEffect; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * This class is a non-persistent implementation of a {@link DataManager}.
+ * It may not reflect the current state of the persistent data.
+ * It should only be used by internal persistent implementations to prevent constant read/write operations. + */ +@ApiStatus.Internal +@NullMarked +public class DataCache implements DataManager { + private final Map> allTrusts = new HashMap<>(); + private final Map leftEffects = new HashMap<>(); + private final Map rightEffects = new HashMap<>(); + private final Map controlModes = new HashMap<>(); + private final Map craftedCounts = new HashMap<>(); + + @Override + public void load() { + Infuse.LOGGER.error("Cannot call 'DataManager#load' on a CachedData object.", new IllegalAccessException()); + } + + @Override + public int getExistingCount(InfuseEffect effect) { + return craftedCounts.getOrDefault(effect.serialize(), 0); + } + + @Override + public void setExistingCount(InfuseEffect effect, int count) { + craftedCounts.put(effect.serialize(), count); + } + + @Override + public Set getTrusted(OfflinePlayer player) { + return allTrusts.getOrDefault(player.getUniqueId(), Set.of()).stream().map(Bukkit::getOfflinePlayer).collect(Collectors.toSet()); + } + + @Override + public void setTrusted(OfflinePlayer player, Set trusted) { + allTrusts.put(player.getUniqueId(), trusted.stream().map(OfflinePlayer::getUniqueId).collect(Collectors.toSet())); + } + + @Override + public void setEffect(OfflinePlayer player, String slot, @Nullable InfuseEffect effect) { + Integer val = effect == null ? null : effect.serialize(); + if (slot.equals("1")) { + leftEffects.put(player.getUniqueId(), val); + } else if (slot.equals("2")) { + rightEffects.put(player.getUniqueId(), val); + } else { + Infuse.LOGGER.warn("Slot '{}' is not a valid slot. Please use \"1\" or \"2\"", slot); + } + } + + @Nullable + @Override + public InfuseEffect getEffect(OfflinePlayer player, String slot) { + if (slot.equals("1")) { + Integer serialized = leftEffects.get(player.getUniqueId()); + if (serialized == null) return null; + return InfuseEffect.deserialize(serialized); + } else if (slot.equals("2")) { + Integer serialized = rightEffects.get(player.getUniqueId()); + if (serialized == null) return null; + return InfuseEffect.deserialize(serialized); + } else { + Infuse.LOGGER.warn("Slot '{}' is not a valid slot. Please use \"1\" or \"2\"", slot); + } + + return null; + } + + @Override + public void setControlMode(OfflinePlayer player, String controlMode) { + controlModes.put(player.getUniqueId(), controlMode.equals("offhand")); + } + + @Override + public String getControlMode(OfflinePlayer player) { + return controlModes.getOrDefault(player.getUniqueId(), false) ? "offhand" : "command"; + } + + @Override + public void applyUpdates() { + + } +} From ee5c672db326281d81aeaa6539f3548115907dfd Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 16:45:08 -0400 Subject: [PATCH 32/37] Implementing the DataCache in the h2 data manager --- .../infuseSMP/playerdata/H2DataManager.java | 129 +++++------------- 1 file changed, 32 insertions(+), 97 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java index a4afe575..c34b0c3d 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java @@ -21,6 +21,7 @@ @NullMarked public class H2DataManager implements DataManager { + private final DataCache cache; private final DataSource dataSource; public H2DataManager(Infuse plugin) { @@ -30,6 +31,8 @@ public H2DataManager(Infuse plugin) { Infuse.LOGGER.error("Could not load the H2 driver", err); } + cache = new DataCache(); + // Creating the JDBC DataSource JdbcDataSource dataSource = new JdbcDataSource(); dataSource.setUrl("jdbc:h2:./" + plugin.getDataFolder().getPath() + "/data/playerdata"); @@ -65,25 +68,15 @@ public void load() { @Override public int getExistingCount(InfuseEffect effect) { - String sql = "SELECT crafted FROM crafted_effects WHERE effect = ?;"; - - try (Connection conn = dataSource.getConnection(); - PreparedStatement stmt = conn.prepareStatement(sql)) { - stmt.setInt(1, effect.serialize()); - - ResultSet results = stmt.executeQuery(); - if (!results.next()) return 0; - - return results.getInt(1); - } catch (SQLException e) { - Infuse.LOGGER.error("Database error!", e); - } - - return 0; + return cache.getExistingCount(effect); } @Override public void setExistingCount(InfuseEffect effect, int count) { + // Updating the cache + cache.setExistingCount(effect, count); + + // Updating the database String sql = "INSERT OR REPLACE INTO crafted_effects(effect, crafted) VALUES (?, ?);"; try (Connection conn = dataSource.getConnection(); @@ -117,32 +110,15 @@ public void createNewPlayer(OfflinePlayer player) { @Override public Set getTrusted(OfflinePlayer player) { - String selectStr = "SELECT trusted FROM trusts WHERE truster = ?"; - UUID trusterUUID = player.getUniqueId(); - - try (Connection conn = dataSource.getConnection()) { - PreparedStatement stmt = conn.prepareStatement(selectStr); - stmt.setObject(1, trusterUUID); - - Set trustedUUIDs = new HashSet<>(); - ResultSet result = stmt.executeQuery(); - while (result.next()) { - try { - trustedUUIDs.add(result.getObject(1, UUID.class)); - } catch (SQLException err) { - Infuse.LOGGER.warn("Invalid UUID in SQL results. Skipping value."); - } - } - - return trustedUUIDs.stream().map(Bukkit::getOfflinePlayer).collect(Collectors.toSet()); - } catch (SQLException err) { - Infuse.LOGGER.info("Failed to connect to database.", err); - } - return Set.of(); + return cache.getTrusted(player); } @Override public void setTrusted(OfflinePlayer player, Set allTrusted) { + // Updating the cache + cache.setTrusted(player, allTrusted); + + // Updating the database Set trustedCopy = new HashSet<>(allTrusted); String findUnused = "SELECT * FROM trusts WHERE truster = ?;"; @@ -203,6 +179,10 @@ public void setTrusted(OfflinePlayer player, Set allTrusted) { @Override public void addTrust(OfflinePlayer player, OfflinePlayer toTrust) { + // Updating the cache + cache.addTrust(player, toTrust); + + // Updating the database String insertElem = """ INSERT INTO trusts (truster, trusted) SELECT ?, ? @@ -230,6 +210,10 @@ WHERE NOT EXISTS ( @Override public void removeTrust(OfflinePlayer player, OfflinePlayer untrusted) { + // Updating the cache + cache.removeTrust(player, untrusted); + + // Updating the database String deleteElem = "DELETE FROM trusts WHERE truster = ? AND trusted = ?"; UUID trusterUUID = player.getUniqueId(); @@ -250,29 +234,15 @@ public void removeTrust(OfflinePlayer player, OfflinePlayer untrusted) { @Override public boolean isTrusted(OfflinePlayer player, OfflinePlayer trusted) { - String selectStr = "SELECT trusted FROM trusts WHERE truster = ? AND trusted = ?"; - - UUID trusterUUID = player.getUniqueId(); - UUID trustedUUID = trusted.getUniqueId(); - - try (Connection conn = dataSource.getConnection()) { - try (PreparedStatement stmt = conn.prepareStatement(selectStr)) { - stmt.setObject(1, trusterUUID); - stmt.setObject(2, trustedUUID); - - return stmt.executeQuery().next(); - } catch (SQLException e) { - Infuse.LOGGER.error("Failed to execute SQL \"{}\"", selectStr, e); - } - } catch (SQLException err) { - Infuse.LOGGER.info("Failed to connect to database.", err); - } - - return false; + return cache.isTrusted(player, trusted); } @Override public void setEffect(OfflinePlayer player, String slot, @Nullable InfuseEffect effect) { + // Updating the cache + cache.setEffect(player, slot, effect); + + // Updating the database createNewPlayer(player); // Making sure slot is "1" or "2" @@ -298,39 +268,15 @@ public void setEffect(OfflinePlayer player, String slot, @Nullable InfuseEffect @Nullable @Override public InfuseEffect getEffect(OfflinePlayer player, String slot) { - // Making sure slot is "1" or "2" - if (!slot.equals("1") && !slot.equals("2")) { - Infuse.LOGGER.warn("Slot '{}' is not a valid slot. Please use \"1\" or \"2\"", slot); - return null; - } - - // Constructing sql based on specified slot - final String getEffectSQL = "SELECT (slot_" + slot + ") FROM player_data WHERE player = ?;"; - - try (Connection conn = dataSource.getConnection()) { - try (PreparedStatement stmt = conn.prepareStatement(getEffectSQL)) { - stmt.setObject(1, player.getUniqueId()); - - ResultSet results = stmt.executeQuery(); - - // Triggers when no effect is equipped or the effect is null - if (!results.next() || results.wasNull()) { - return null; - } - - return InfuseEffect.deserialize(results.getInt(1)); - } catch (SQLException e) { - Infuse.LOGGER.error("Failed to read effects from the database", e); - } - } catch (SQLException err) { - Infuse.LOGGER.error("Could not open connection to H2 database", err); - } - - return null; + return cache.getEffect(player, slot); } @Override public void setControlMode(OfflinePlayer player, String controlMode) { + // Updating the cache + cache.setControlMode(player, controlMode); + + // Updating the database createNewPlayer(player); boolean offhandControls; @@ -357,18 +303,7 @@ public void setControlMode(OfflinePlayer player, String controlMode) { @Override public String getControlMode(OfflinePlayer player) { - String sql = "SELECT offhand_control FROM player_data WHERE player = ?;"; - try (Connection conn = dataSource.getConnection(); - PreparedStatement stmt = conn.prepareStatement(sql)) { - stmt.setObject(1, player.getUniqueId()); - - ResultSet results = stmt.executeQuery(); - return results.getBoolean(1) ? "offhand" : "command"; - } catch (SQLException e) { - Infuse.LOGGER.error("Database error!", e); - } - - return "command"; + return cache.getControlMode(player); } @Override From 4dcdb666ffe9b3f44ee171d10d255efd0d387eeb Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 18:24:17 -0400 Subject: [PATCH 33/37] exposing internal datacache storage objects publicly bc i dont have a better idea rn --- .../com/catadmirer/infuseSMP/playerdata/DataCache.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataCache.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataCache.java index 5ab1ea95..c80cd9bb 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataCache.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataCache.java @@ -22,11 +22,11 @@ @ApiStatus.Internal @NullMarked public class DataCache implements DataManager { - private final Map> allTrusts = new HashMap<>(); - private final Map leftEffects = new HashMap<>(); - private final Map rightEffects = new HashMap<>(); - private final Map controlModes = new HashMap<>(); - private final Map craftedCounts = new HashMap<>(); + public final Map> allTrusts = new HashMap<>(); + public final Map leftEffects = new HashMap<>(); + public final Map rightEffects = new HashMap<>(); + public final Map controlModes = new HashMap<>(); + public final Map craftedCounts = new HashMap<>(); @Override public void load() { From 9ed07170a835764fb4d4756d66c33ca8ff72b6c9 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Fri, 12 Jun 2026 18:27:27 -0400 Subject: [PATCH 34/37] quick todo --- src/main/java/com/catadmirer/infuseSMP/playerdata/DataCache.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataCache.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataCache.java index c80cd9bb..2989516c 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/DataCache.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/DataCache.java @@ -19,6 +19,7 @@ * It may not reflect the current state of the persistent data.
* It should only be used by internal persistent implementations to prevent constant read/write operations. */ +// TODO: Add a DataCacheBuilder @ApiStatus.Internal @NullMarked public class DataCache implements DataManager { From 7a5c5417f3b19cd6d385d7b0c0ce6af88965f9b3 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Sat, 13 Jun 2026 03:17:46 -0400 Subject: [PATCH 35/37] Loading data into the cache on load --- .../infuseSMP/playerdata/H2DataManager.java | 68 +++++++++++++++++-- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java index c34b0c3d..f59aa4f7 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java @@ -21,7 +21,7 @@ @NullMarked public class H2DataManager implements DataManager { - private final DataCache cache; + private DataCache cache; private final DataSource dataSource; public H2DataManager(Infuse plugin) { @@ -31,6 +31,7 @@ public H2DataManager(Infuse plugin) { Infuse.LOGGER.error("Could not load the H2 driver", err); } + // Creating an empty cache cache = new DataCache(); // Creating the JDBC DataSource @@ -49,17 +50,72 @@ public void load() { final String createTrustTable = "CREATE TABLE IF NOT EXISTS trusts(truster UUID NOT NULL, trusted UUID NOT NULL);"; final String createCraftedTable = "CREATE TABLE IF NOT EXISTS crafted_effects(effect INTEGER PRIMARY KEY NOT NULL, crafted INTEGER NOT NULL);"; + final String getAllTrusts = "SELECT * FROM trusts;"; + final String getAllPlayerData = "SELECT * FROM player_data;"; + final String getAllCrafted = "SELECT * FROM crafted_effects;"; + try (Connection conn = dataSource.getConnection()) { // Creating the tables if they don't exist - Statement stmt = conn.createStatement(); - stmt.execute(createPlayerDataTable); - stmt.execute(createTrustTable); - stmt.execute(createCraftedTable); - stmt.close(); + try (Statement stmt = conn.createStatement()) { + stmt.execute(createPlayerDataTable); + stmt.execute(createTrustTable); + stmt.execute(createCraftedTable); + } // Commiting any changes conn.commit(); + // Clearing any cached data + cache = new DataCache(); + + // Loading data into the cache + try (Statement stmt = conn.createStatement()) { + // Mirroring trusts + ResultSet results = stmt.executeQuery(getAllTrusts); + while (results.next()) { + UUID player = results.getObject(1, UUID.class); + UUID trusted = results.getObject(2, UUID.class); + + Set playerTrusts = cache.allTrusts.computeIfAbsent(player, _ -> new HashSet<>()); + playerTrusts.add(trusted); + cache.allTrusts.put(player, playerTrusts); + } + + results.close(); + + // Mirroring player data + results = stmt.executeQuery(getAllPlayerData); + while (results.next()) { + UUID player = results.getObject(1, UUID.class); + + int lEffect = results.getInt(2); + if (!results.wasNull()) { + cache.leftEffects.put(player, lEffect); + } + + int rEffect = results.getInt(3); + if (!results.wasNull()) { + cache.rightEffects.put(player, rEffect); + } + + boolean offhandControl = results.getBoolean(4); + cache.controlModes.put(player, offhandControl); + } + + results.close(); + + // Mirroring crafted effect counts + results = stmt.executeQuery(getAllCrafted); + while (results.next()) { + int effectId = results.getInt(1); + int crafted = results.getInt(2); + + cache.craftedCounts.put(effectId, crafted); + } + + results.close(); + } + Infuse.LOGGER.info("Successfully loaded H2 database!"); } catch (SQLException err) { Infuse.LOGGER.error("Could not open connection to H2 database", err); From e8852020f428c2593ef14315c0e978f4eda075c4 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Sat, 13 Jun 2026 04:12:52 -0400 Subject: [PATCH 36/37] Making a class that helps with async data handling --- .../playerdata/AsyncDataManager.java | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/main/java/com/catadmirer/infuseSMP/playerdata/AsyncDataManager.java diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/AsyncDataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/AsyncDataManager.java new file mode 100644 index 00000000..2f265e05 --- /dev/null +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/AsyncDataManager.java @@ -0,0 +1,107 @@ +package com.catadmirer.infuseSMP.playerdata; + +import com.catadmirer.infuseSMP.Infuse; +import com.catadmirer.infuseSMP.effects.InfuseEffect; +import org.bukkit.OfflinePlayer; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Abstract class that helps with handling data asynchronously. + */ +@NullMarked +public abstract class AsyncDataManager implements DataManager { + protected ExecutorService executorService; + + public AsyncDataManager() { + executorService = Executors.newThreadPerTaskExecutor(Executors.defaultThreadFactory()); + } + + @Override + public void setExistingCount(InfuseEffect effect, int count) { + // Attempts to update the database asynchronously, but falls back to synchronous execution if there is an error or the ExecutorService is closed. + if (!executorService.isShutdown()) { + executorService.execute(() -> reallySetExistingCount(effect, count)); + return; + } + + Infuse.LOGGER.warn("Could not write data to the database asynchronously"); + reallySetExistingCount(effect, count); + } + + protected abstract void reallySetExistingCount(InfuseEffect effect, int count); + + @Override + public void setTrusted(OfflinePlayer player, Set trusted) { + // Attempts to update the database asynchronously, but falls back to synchronous execution if there is an error or the ExecutorService is closed. + if (!executorService.isShutdown()) { + executorService.execute(() -> reallySetTrusted(player, trusted)); + return; + } + + Infuse.LOGGER.warn("Could not write data to the database asynchronously"); + reallySetTrusted(player, trusted); + } + + protected abstract void reallySetTrusted(OfflinePlayer player, Set trusted); + + @Override + public void addTrust(OfflinePlayer player, OfflinePlayer trusted) { + // Attempts to update the database asynchronously, but falls back to synchronous execution if there is an error or the ExecutorService is closed. + if (!executorService.isShutdown()) { + executorService.execute(() -> reallyAddTrust(player, trusted)); + return; + } + + Infuse.LOGGER.warn("Could not write data to the database asynchronously"); + reallyAddTrust(player, trusted); + } + + protected abstract void reallyAddTrust(OfflinePlayer player, OfflinePlayer trusted); + + @Override + public void removeTrust(OfflinePlayer player, OfflinePlayer untrusted) { + // Attempts to update the database asynchronously, but falls back to synchronous execution if there is an error or the ExecutorService is closed. + if (!executorService.isShutdown()) { + executorService.execute(() -> reallyRemoveTrust(player, untrusted)); + return; + } + + Infuse.LOGGER.warn("Could not write data to the database asynchronously"); + reallyRemoveTrust(player, untrusted); + } + + protected abstract void reallyRemoveTrust(OfflinePlayer player, OfflinePlayer untrusted); + + @Override + public void setEffect(OfflinePlayer player, String slot, @Nullable InfuseEffect effect) { + // Attempts to update the database asynchronously, but falls back to synchronous execution if there is an error or the ExecutorService is closed. + if (!executorService.isShutdown()) { + executorService.execute(() -> reallySetEffect(player, slot, effect)); + return; + } + + Infuse.LOGGER.warn("Could not write data to the database asynchronously"); + reallySetEffect(player, slot, effect); + } + + protected abstract void reallySetEffect(OfflinePlayer player, String slot, @Nullable InfuseEffect effect); + + @Override + public void setControlMode(OfflinePlayer player, String controlMode) { + // Attempts to update the database asynchronously, but falls back to synchronous execution if there is an error or the ExecutorService is closed. + if (!executorService.isShutdown()) { + executorService.execute(() -> reallySetControlMode(player, controlMode)); + return; + } + + Infuse.LOGGER.warn("Could not write data to the database asynchronously"); + reallySetControlMode(player, controlMode); + } + + protected abstract void reallySetControlMode(OfflinePlayer player, String controlMode); +} From bfbd8d95241eba30d3e464f2794a2567085f9802 Mon Sep 17 00:00:00 2001 From: TurboJax Date: Sat, 13 Jun 2026 04:13:33 -0400 Subject: [PATCH 37/37] Using the AsyncDataManager in the H2DataManager class --- .../infuseSMP/playerdata/H2DataManager.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java index f59aa4f7..d4f3f1ed 100644 --- a/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java +++ b/src/main/java/com/catadmirer/infuseSMP/playerdata/H2DataManager.java @@ -16,11 +16,10 @@ import java.util.HashSet; import java.util.Set; import java.util.UUID; -import java.util.stream.Collectors; import javax.sql.DataSource; @NullMarked -public class H2DataManager implements DataManager { +public class H2DataManager extends AsyncDataManager { private DataCache cache; private final DataSource dataSource; @@ -128,7 +127,7 @@ public int getExistingCount(InfuseEffect effect) { } @Override - public void setExistingCount(InfuseEffect effect, int count) { + protected void reallySetExistingCount(InfuseEffect effect, int count) { // Updating the cache cache.setExistingCount(effect, count); @@ -153,7 +152,8 @@ public void setExistingCount(InfuseEffect effect, int count) { * * @param player The player to create an entry for. */ - public void createNewPlayer(OfflinePlayer player) { + private void createNewPlayer(OfflinePlayer player) { + // All calls are already async. This does not need to be run through the service. String newPlayer = "INSERT OR IGNORE INTO player_data (player, offhand_control) VALUES (?, FALSE);"; try (Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.prepareStatement(newPlayer)) { @@ -170,7 +170,7 @@ public Set getTrusted(OfflinePlayer player) { } @Override - public void setTrusted(OfflinePlayer player, Set allTrusted) { + protected void reallySetTrusted(OfflinePlayer player, Set allTrusted) { // Updating the cache cache.setTrusted(player, allTrusted); @@ -234,7 +234,7 @@ public void setTrusted(OfflinePlayer player, Set allTrusted) { } @Override - public void addTrust(OfflinePlayer player, OfflinePlayer toTrust) { + protected void reallyAddTrust(OfflinePlayer player, OfflinePlayer toTrust) { // Updating the cache cache.addTrust(player, toTrust); @@ -265,7 +265,7 @@ WHERE NOT EXISTS ( } @Override - public void removeTrust(OfflinePlayer player, OfflinePlayer untrusted) { + protected void reallyRemoveTrust(OfflinePlayer player, OfflinePlayer untrusted) { // Updating the cache cache.removeTrust(player, untrusted); @@ -294,7 +294,7 @@ public boolean isTrusted(OfflinePlayer player, OfflinePlayer trusted) { } @Override - public void setEffect(OfflinePlayer player, String slot, @Nullable InfuseEffect effect) { + protected void reallySetEffect(OfflinePlayer player, String slot, @Nullable InfuseEffect effect) { // Updating the cache cache.setEffect(player, slot, effect); @@ -328,7 +328,7 @@ public InfuseEffect getEffect(OfflinePlayer player, String slot) { } @Override - public void setControlMode(OfflinePlayer player, String controlMode) { + protected void reallySetControlMode(OfflinePlayer player, String controlMode) { // Updating the cache cache.setControlMode(player, controlMode);