Encapsulate Settings, tweak keys, add empty dead player save option, close #73

feat/data-edit-commands 2.2.4
William 2 years ago
parent 5a000add98
commit a9b1070725
No known key found for this signature in database

@ -92,7 +92,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
}
// Prepare data adapter
if (settings.compressData) {
if (settings.doCompressData()) {
dataAdapter = new CompressedDataAdapter();
} else {
dataAdapter = new JsonDataAdapter();
@ -169,7 +169,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
}
// Check for updates
if (settings.checkForUpdates) {
if (settings.doCheckForUpdates()) {
log(Level.INFO, "Checking for updates...");
getLatestVersionIfOutdated().thenAccept(newestVersion ->
newestVersion.ifPresent(newVersion -> log(Level.WARNING,
@ -304,8 +304,8 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
// Load locales from language preset default
final Locales languagePresets = Annotaml.create(Locales.class,
Objects.requireNonNull(getResource("locales/" + settings.language + ".yml"))).get();
this.locales = Annotaml.create(new File(getDataFolder(), "messages_" + settings.language + ".yml"),
Objects.requireNonNull(getResource("locales/" + settings.getLanguage() + ".yml"))).get();
this.locales = Annotaml.create(new File(getDataFolder(), "messages_" + settings.getLanguage() + ".yml"),
languagePresets).get();
return true;
} catch (IOException | NullPointerException | InvocationTargetException | IllegalAccessException |

@ -40,7 +40,7 @@ public class BukkitEventListener extends EventListener implements BukkitJoinEven
public BukkitEventListener(@NotNull BukkitHuskSync huskSync) {
super(huskSync);
this.blacklistedCommands = huskSync.getSettings().blacklistedCommandsWhileLocked;
this.blacklistedCommands = huskSync.getSettings().getBlacklistedCommandsWhileLocked();
Bukkit.getServer().getPluginManager().registerEvents(this, huskSync);
}
@ -75,7 +75,7 @@ public class BukkitEventListener extends EventListener implements BukkitJoinEven
}
// Handle saving player data snapshots on death
if (!plugin.getSettings().saveOnDeath) return;
if (!plugin.getSettings().doSaveOnDeath()) return;
// Truncate the drops list to the inventory size and save the player's inventory
final int maxInventorySize = BukkitInventoryMap.INVENTORY_SLOT_COUNT;
@ -89,7 +89,7 @@ public class BukkitEventListener extends EventListener implements BukkitJoinEven
@EventHandler(ignoreCancelled = true)
public void onWorldSave(@NotNull WorldSaveEvent event) {
// Handle saving player data snapshots when the world saves
if (!plugin.getSettings().saveOnWorldSave) return;
if (!plugin.getSettings().doSaveOnWorldSave()) return;
CompletableFuture.runAsync(() -> super.saveOnWorldSave(event.getWorld().getPlayers()
.stream().map(BukkitPlayer::adapt)

@ -37,11 +37,11 @@ public class LegacyMigrator extends Migrator {
public LegacyMigrator(@NotNull HuskSync plugin) {
super(plugin);
this.hslConverter = HSLConverter.getInstance();
this.sourceHost = plugin.getSettings().mySqlHost;
this.sourcePort = plugin.getSettings().mySqlPort;
this.sourceUsername = plugin.getSettings().mySqlUsername;
this.sourcePassword = plugin.getSettings().mySqlPassword;
this.sourceDatabase = plugin.getSettings().mySqlDatabase;
this.sourceHost = plugin.getSettings().getMySqlHost();
this.sourcePort = plugin.getSettings().getMySqlPort();
this.sourceUsername = plugin.getSettings().getMySqlUsername();
this.sourcePassword = plugin.getSettings().getMySqlPassword();
this.sourceDatabase = plugin.getSettings().getMySqlDatabase();
this.sourcePlayersTable = "husksync_players";
this.sourceDataTable = "husksync_data";
this.minecraftVersion = plugin.getMinecraftVersion().toString();

@ -42,11 +42,11 @@ public class MpdbMigrator extends Migrator {
public MpdbMigrator(@NotNull BukkitHuskSync plugin, @NotNull Plugin mySqlPlayerDataBridge) {
super(plugin);
this.mpdbConverter = MPDBConverter.getInstance(mySqlPlayerDataBridge);
this.sourceHost = plugin.getSettings().mySqlHost;
this.sourcePort = plugin.getSettings().mySqlPort;
this.sourceUsername = plugin.getSettings().mySqlUsername;
this.sourcePassword = plugin.getSettings().mySqlPassword;
this.sourceDatabase = plugin.getSettings().mySqlDatabase;
this.sourceHost = plugin.getSettings().getMySqlHost();
this.sourcePort = plugin.getSettings().getMySqlPort();
this.sourceUsername = plugin.getSettings().getMySqlUsername();
this.sourcePassword = plugin.getSettings().getMySqlPassword();
this.sourceDatabase = plugin.getSettings().getMySqlDatabase();
this.sourceInventoryTable = "mpdb_inventory";
this.sourceEnderChestTable = "mpdb_enderchest";
this.sourceExperienceTable = "mpdb_experience";

@ -19,7 +19,9 @@ import org.bukkit.attribute.Attribute;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
@ -146,7 +148,11 @@ public class BukkitPlayer extends OnlineUser {
@Override
public CompletableFuture<ItemData> getInventory() {
return BukkitSerializer.serializeItemStackArray(player.getInventory().getContents())
final PlayerInventory inventory = player.getInventory();
if (inventory.isEmpty()) {
return CompletableFuture.completedFuture(ItemData.empty());
}
return BukkitSerializer.serializeItemStackArray(inventory.getContents())
.thenApply(ItemData::new);
}
@ -166,7 +172,11 @@ public class BukkitPlayer extends OnlineUser {
@Override
public CompletableFuture<ItemData> getEnderChest() {
return BukkitSerializer.serializeItemStackArray(player.getEnderChest().getContents())
final Inventory enderChest = player.getEnderChest();
if (enderChest.isEmpty()) {
return CompletableFuture.completedFuture(ItemData.empty());
}
return BukkitSerializer.serializeItemStackArray(enderChest.getContents())
.thenApply(ItemData::new);
}

@ -126,7 +126,7 @@ public interface HuskSync {
* @param throwable a throwable to log
*/
default void debug(@NotNull String message, @NotNull Throwable... throwable) {
if (getSettings().debugLogging) {
if (getSettings().doDebugLogging()) {
log(Level.INFO, "[DEBUG] " + message, throwable);
}
}

@ -20,117 +20,255 @@ import java.util.Map;
Information: https://william278.net/project/husksync
Documentation: https://william278.net/docs/husksync""",
versionField = "config_version", versionNumber = 3)
versionField = "config_version", versionNumber = 4)
public class Settings {
// Top-level settings
public String language = "en-gb";
@YamlKey("language")
private String language = "en-gb";
@YamlKey("check_for_updates")
public boolean checkForUpdates = true;
private boolean checkForUpdates = true;
@YamlKey("cluster_id")
public String clusterId = "";
private String clusterId = "";
@YamlKey("debug_logging")
public boolean debugLogging = false;
private boolean debugLogging = false;
// Database settings
@YamlComment("Database connection settings")
@YamlKey("database.credentials.host")
public String mySqlHost = "localhost";
private String mySqlHost = "localhost";
@YamlKey("database.credentials.port")
public int mySqlPort = 3306;
private int mySqlPort = 3306;
@YamlKey("database.credentials.database")
public String mySqlDatabase = "HuskSync";
private String mySqlDatabase = "HuskSync";
@YamlKey("database.credentials.username")
public String mySqlUsername = "root";
private String mySqlUsername = "root";
@YamlKey("database.credentials.password")
public String mySqlPassword = "pa55w0rd";
private String mySqlPassword = "pa55w0rd";
@YamlKey("database.credentials.parameters")
public String mySqlConnectionParameters = "?autoReconnect=true&useSSL=false";
private String mySqlConnectionParameters = "?autoReconnect=true&useSSL=false";
@YamlComment("MySQL connection pool properties")
@YamlKey("database.connection_pool.maximum_pool_size")
public int mySqlConnectionPoolSize = 10;
private int mySqlConnectionPoolSize = 10;
@YamlKey("database.connection_pool.minimum_idle")
public int mySqlConnectionPoolIdle = 10;
private int mySqlConnectionPoolIdle = 10;
@YamlKey("database.connection_pool.maximum_lifetime")
public long mySqlConnectionPoolLifetime = 1800000;
private long mySqlConnectionPoolLifetime = 1800000;
@YamlKey("database.connection_pool.keepalive_time")
public long mySqlConnectionPoolKeepAlive = 0;
private long mySqlConnectionPoolKeepAlive = 0;
@YamlKey("database.connection_pool.connection_timeout")
public long mySqlConnectionPoolTimeout = 5000;
private long mySqlConnectionPoolTimeout = 5000;
@YamlKey("database.table_names")
public Map<String, String> tableNames = TableName.getDefaults();
@NotNull
public String getTableName(@NotNull TableName tableName) {
return tableNames.getOrDefault(tableName.name().toLowerCase(), tableName.defaultName);
}
private Map<String, String> tableNames = TableName.getDefaults();
// Redis settings
@YamlComment("Redis connection settings")
@YamlKey("redis.credentials.host")
public String redisHost = "localhost";
private String redisHost = "localhost";
@YamlKey("redis.credentials.port")
public int redisPort = 6379;
private int redisPort = 6379;
@YamlKey("redis.credentials.password")
public String redisPassword = "";
private String redisPassword = "";
@YamlKey("redis.use_ssl")
public boolean redisUseSsl = false;
private boolean redisUseSsl = false;
// Synchronization settings
@YamlComment("Synchronization settings")
@YamlKey("synchronization.max_user_data_snapshots")
public int maxUserDataSnapshots = 5;
private int maxUserDataSnapshots = 5;
@YamlKey("synchronization.save_on_world_save")
public boolean saveOnWorldSave = true;
private boolean saveOnWorldSave = true;
@YamlKey("synchronization.save_on_death")
public boolean saveOnDeath = false;
private boolean saveOnDeath = false;
@YamlKey("synchronization.save_empty_drops_on_death")
private boolean saveEmptyDropsOnDeath = true;
@YamlKey("synchronization.compress_data")
public boolean compressData = true;
private boolean compressData = true;
@YamlKey("synchronization.notification_display_slot")
public NotificationDisplaySlot notificationDisplaySlot = NotificationDisplaySlot.ACTION_BAR;
private NotificationDisplaySlot notificationDisplaySlot = NotificationDisplaySlot.ACTION_BAR;
@YamlKey("synchronization.save_dead_player_inventories")
public boolean saveDeadPlayerInventories = true;
@YamlKey("synchronization.synchronise_dead_players_changing_server")
private boolean synchroniseDeadPlayersChangingServer = true;
@YamlKey("synchronization.network_latency_milliseconds")
public int networkLatencyMilliseconds = 500;
private int networkLatencyMilliseconds = 500;
@YamlKey("synchronization.features")
public Map<String, Boolean> synchronizationFeatures = SynchronizationFeature.getDefaults();
private Map<String, Boolean> synchronizationFeatures = SynchronizationFeature.getDefaults();
@YamlKey("synchronization.blacklisted_commands_while_locked")
public List<String> blacklistedCommandsWhileLocked = new ArrayList<>();
private List<String> blacklistedCommandsWhileLocked = new ArrayList<>();
@YamlKey("synchronization.event_priorities")
private Map<String, String> synchronizationEventPriorities = EventType.getDefaults();
// Zero-args constructor for instantiation via Annotaml
public Settings() {
}
@NotNull
public String getLanguage() {
return language;
}
public boolean doCheckForUpdates() {
return checkForUpdates;
}
@NotNull
public String getClusterId() {
return clusterId;
}
public boolean doDebugLogging() {
return debugLogging;
}
@NotNull
public String getMySqlHost() {
return mySqlHost;
}
public int getMySqlPort() {
return mySqlPort;
}
@NotNull
public String getMySqlDatabase() {
return mySqlDatabase;
}
@NotNull
public String getMySqlUsername() {
return mySqlUsername;
}
@NotNull
public String getMySqlPassword() {
return mySqlPassword;
}
@NotNull
public String getMySqlConnectionParameters() {
return mySqlConnectionParameters;
}
@NotNull
public String getTableName(@NotNull TableName tableName) {
return tableNames.getOrDefault(tableName.name().toLowerCase(), tableName.defaultName);
}
public int getMySqlConnectionPoolSize() {
return mySqlConnectionPoolSize;
}
public int getMySqlConnectionPoolIdle() {
return mySqlConnectionPoolIdle;
}
public long getMySqlConnectionPoolLifetime() {
return mySqlConnectionPoolLifetime;
}
public long getMySqlConnectionPoolKeepAlive() {
return mySqlConnectionPoolKeepAlive;
}
public long getMySqlConnectionPoolTimeout() {
return mySqlConnectionPoolTimeout;
}
@NotNull
public String getRedisHost() {
return redisHost;
}
public int getRedisPort() {
return redisPort;
}
@NotNull
public String getRedisPassword() {
return redisPassword;
}
public boolean isRedisUseSsl() {
return redisUseSsl;
}
public int getMaxUserDataSnapshots() {
return maxUserDataSnapshots;
}
public boolean doSaveOnWorldSave() {
return saveOnWorldSave;
}
public boolean doSaveOnDeath() {
return saveOnDeath;
}
public boolean doSaveEmptyDropsOnDeath() {
return saveEmptyDropsOnDeath;
}
public boolean doCompressData() {
return compressData;
}
@NotNull
public NotificationDisplaySlot getNotificationDisplaySlot() {
return notificationDisplaySlot;
}
public boolean isSynchroniseDeadPlayersChangingServer() {
return synchroniseDeadPlayersChangingServer;
}
public int getNetworkLatencyMilliseconds() {
return networkLatencyMilliseconds;
}
@NotNull
public Map<String, Boolean> getSynchronizationFeatures() {
return synchronizationFeatures;
}
public boolean getSynchronizationFeature(@NotNull SynchronizationFeature feature) {
return synchronizationFeatures.getOrDefault(feature.name().toLowerCase(), feature.enabledByDefault);
return getSynchronizationFeatures().getOrDefault(feature.name().toLowerCase(), feature.enabledByDefault);
}
@YamlKey("synchronization.event_priorities")
public Map<String, String> synchronizationEventPriorities = EventType.getDefaults();
@NotNull
public List<String> getBlacklistedCommandsWhileLocked() {
return blacklistedCommandsWhileLocked;
}
@NotNull
public EventPriority getEventPriority(@NotNull Settings.EventType eventType) {
@ -142,7 +280,6 @@ public class Settings {
}
}
/**
* Represents the names of tables in the database
*/

@ -32,4 +32,13 @@ public class ItemData {
protected ItemData() {
}
/**
* Check if the item data is empty
*
* @return {@code true} if the item data is empty; {@code false} otherwise
*/
public boolean isEmpty() {
return serializedItems.isEmpty();
}
}

@ -52,17 +52,17 @@ public class MySqlDatabase extends Database {
public MySqlDatabase(@NotNull HuskSync plugin) {
super(plugin);
final Settings settings = plugin.getSettings();
this.mySqlHost = settings.mySqlHost;
this.mySqlPort = settings.mySqlPort;
this.mySqlDatabaseName = settings.mySqlDatabase;
this.mySqlUsername = settings.mySqlUsername;
this.mySqlPassword = settings.mySqlPassword;
this.mySqlConnectionParameters = settings.mySqlConnectionParameters;
this.hikariMaximumPoolSize = settings.mySqlConnectionPoolSize;
this.hikariMinimumIdle = settings.mySqlConnectionPoolIdle;
this.hikariMaximumLifetime = settings.mySqlConnectionPoolLifetime;
this.hikariKeepAliveTime = settings.mySqlConnectionPoolKeepAlive;
this.hikariConnectionTimeOut = settings.mySqlConnectionPoolTimeout;
this.mySqlHost = settings.getMySqlHost();
this.mySqlPort = settings.getMySqlPort();
this.mySqlDatabaseName = settings.getMySqlDatabase();
this.mySqlUsername = settings.getMySqlUsername();
this.mySqlPassword = settings.getMySqlPassword();
this.mySqlConnectionParameters = settings.getMySqlConnectionParameters();
this.hikariMaximumPoolSize = settings.getMySqlConnectionPoolSize();
this.hikariMinimumIdle = settings.getMySqlConnectionPoolIdle();
this.hikariMaximumLifetime = settings.getMySqlConnectionPoolLifetime();
this.hikariKeepAliveTime = settings.getMySqlConnectionPoolKeepAlive();
this.hikariConnectionTimeOut = settings.getMySqlConnectionPoolTimeout();
}
/**
@ -300,7 +300,7 @@ public class MySqlDatabase extends Database {
protected void rotateUserData(@NotNull User user) {
final List<UserDataSnapshot> unpinnedUserData = getUserData(user).join().stream()
.filter(dataSnapshot -> !dataSnapshot.pinned()).toList();
if (unpinnedUserData.size() > plugin.getSettings().maxUserDataSnapshots) {
if (unpinnedUserData.size() > plugin.getSettings().getMaxUserDataSnapshots()) {
try (Connection connection = getConnection()) {
try (PreparedStatement statement = connection.prepareStatement(formatStatementTables("""
DELETE FROM `%user_data_table%`
@ -308,7 +308,7 @@ public class MySqlDatabase extends Database {
AND `pinned` IS FALSE
ORDER BY `timestamp` ASC
LIMIT %entry_count%;""".replace("%entry_count%",
Integer.toString(unpinnedUserData.size() - plugin.getSettings().maxUserDataSnapshots))))) {
Integer.toString(unpinnedUserData.size() - plugin.getSettings().getMaxUserDataSnapshots()))))) {
statement.setString(1, user.uuid.toString());
statement.executeUpdate();
}

@ -60,7 +60,7 @@ public abstract class EventListener {
CompletableFuture.runAsync(() -> {
try {
// Hold reading data for the network latency threshold, to ensure the source server has set the redis key
Thread.sleep(Math.max(0, plugin.getSettings().networkLatencyMilliseconds));
Thread.sleep(Math.max(0, plugin.getSettings().getNetworkLatencyMilliseconds()));
} catch (InterruptedException e) {
plugin.log(Level.SEVERE, "An exception occurred handling a player join", e);
} finally {
@ -124,7 +124,7 @@ public abstract class EventListener {
*/
private void handleSynchronisationCompletion(@NotNull OnlineUser user, boolean succeeded) {
if (succeeded) {
switch (plugin.getSettings().notificationDisplaySlot) {
switch (plugin.getSettings().getNotificationDisplaySlot()) {
case CHAT -> plugin.getLocales().getLocale("synchronisation_complete")
.ifPresent(user::sendMessage);
case ACTION_BAR -> plugin.getLocales().getLocale("synchronisation_complete")
@ -179,7 +179,7 @@ public abstract class EventListener {
* @param usersInWorld a list of users in the world that is being saved
*/
protected final void saveOnWorldSave(@NotNull List<OnlineUser> usersInWorld) {
if (disabling || !plugin.getSettings().saveOnWorldSave) {
if (disabling || !plugin.getSettings().doSaveOnWorldSave()) {
return;
}
usersInWorld.stream()
@ -196,7 +196,8 @@ public abstract class EventListener {
* @param drops The items that this user would have dropped
*/
protected void saveOnPlayerDeath(@NotNull OnlineUser user, @NotNull ItemData drops) {
if (disabling || !plugin.getSettings().saveOnDeath || lockedPlayers.contains(user.uuid) || user.isNpc()) {
if (disabling || !plugin.getSettings().doSaveOnDeath() || lockedPlayers.contains(user.uuid) || user.isNpc()
|| (!plugin.getSettings().doSaveEmptyDropsOnDeath() && drops.isEmpty())) {
return;
}

@ -43,12 +43,12 @@ public abstract class OnlineUser extends User {
public final CompletableFuture<Void> setStatus(@NotNull StatusData statusData,
@NotNull List<StatusDataFlag> statusDataFlags) {
final Settings settings = new Settings();
settings.synchronizationFeatures.put(Settings.SynchronizationFeature.HEALTH.name().toLowerCase(), statusDataFlags.contains(StatusDataFlag.SET_HEALTH));
settings.synchronizationFeatures.put(Settings.SynchronizationFeature.MAX_HEALTH.name().toLowerCase(), statusDataFlags.contains(StatusDataFlag.SET_MAX_HEALTH));
settings.synchronizationFeatures.put(Settings.SynchronizationFeature.HUNGER.name().toLowerCase(), statusDataFlags.contains(StatusDataFlag.SET_HUNGER));
settings.synchronizationFeatures.put(Settings.SynchronizationFeature.EXPERIENCE.name().toLowerCase(), statusDataFlags.contains(StatusDataFlag.SET_EXPERIENCE));
settings.synchronizationFeatures.put(Settings.SynchronizationFeature.INVENTORIES.name().toLowerCase(), statusDataFlags.contains(StatusDataFlag.SET_SELECTED_ITEM_SLOT));
settings.synchronizationFeatures.put(Settings.SynchronizationFeature.LOCATION.name().toLowerCase(), statusDataFlags.contains(StatusDataFlag.SET_GAME_MODE) || statusDataFlags.contains(StatusDataFlag.SET_FLYING));
settings.getSynchronizationFeatures().put(Settings.SynchronizationFeature.HEALTH.name().toLowerCase(), statusDataFlags.contains(StatusDataFlag.SET_HEALTH));
settings.getSynchronizationFeatures().put(Settings.SynchronizationFeature.MAX_HEALTH.name().toLowerCase(), statusDataFlags.contains(StatusDataFlag.SET_MAX_HEALTH));
settings.getSynchronizationFeatures().put(Settings.SynchronizationFeature.HUNGER.name().toLowerCase(), statusDataFlags.contains(StatusDataFlag.SET_HUNGER));
settings.getSynchronizationFeatures().put(Settings.SynchronizationFeature.EXPERIENCE.name().toLowerCase(), statusDataFlags.contains(StatusDataFlag.SET_EXPERIENCE));
settings.getSynchronizationFeatures().put(Settings.SynchronizationFeature.INVENTORIES.name().toLowerCase(), statusDataFlags.contains(StatusDataFlag.SET_SELECTED_ITEM_SLOT));
settings.getSynchronizationFeatures().put(Settings.SynchronizationFeature.LOCATION.name().toLowerCase(), statusDataFlags.contains(StatusDataFlag.SET_GAME_MODE) || statusDataFlags.contains(StatusDataFlag.SET_FLYING));
return setStatus(statusData, settings);
}
@ -325,7 +325,7 @@ public abstract class OnlineUser extends User {
if (!isOffline()) {
final Settings settings = plugin.getSettings();
if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.INVENTORIES)) {
if (isDead() && settings.saveDeadPlayerInventories) {
if (isDead() && settings.isSynchroniseDeadPlayersChangingServer()) {
plugin.debug("Player " + username + " is dead, so their inventory will be set to empty.");
add(CompletableFuture.runAsync(() -> builder.setInventory(ItemData.empty())));
} else {

@ -33,13 +33,13 @@ public class RedisManager extends JedisPubSub {
public RedisManager(@NotNull HuskSync plugin) {
this.plugin = plugin;
clusterId = plugin.getSettings().clusterId;
clusterId = plugin.getSettings().getClusterId();
// Set redis credentials
this.redisHost = plugin.getSettings().redisHost;
this.redisPort = plugin.getSettings().redisPort;
this.redisPassword = plugin.getSettings().redisPassword;
this.redisUseSsl = plugin.getSettings().redisUseSsl;
this.redisHost = plugin.getSettings().getRedisHost();
this.redisPort = plugin.getSettings().getRedisPort();
this.redisPassword = plugin.getSettings().getRedisPassword();
this.redisUseSsl = plugin.getSettings().isRedisUseSsl();
// Configure the jedis pool
this.jedisPoolConfig = new JedisPoolConfig();
@ -91,7 +91,7 @@ public class RedisManager extends JedisPubSub {
final UserData userData = plugin.getDataAdapter().fromBytes(redisMessage.data);
user.setData(userData, plugin).thenAccept(succeeded -> {
if (succeeded) {
switch (plugin.getSettings().notificationDisplaySlot) {
switch (plugin.getSettings().getNotificationDisplaySlot()) {
case CHAT -> plugin.getLocales().getLocale("data_update_complete")
.ifPresent(user::sendMessage);
case ACTION_BAR -> plugin.getLocales().getLocale("data_update_complete")

Loading…
Cancel
Save