Migrate config to Annotaml

feat/data-edit-commands
William 2 years ago
parent 8c0f7a295f
commit acd97a1cb0

@ -12,6 +12,7 @@ dependencies {
compileOnly 'dev.dejvokep:boosted-yaml:1.3' compileOnly 'dev.dejvokep:boosted-yaml:1.3'
compileOnly 'com.zaxxer:HikariCP:5.0.1' compileOnly 'com.zaxxer:HikariCP:5.0.1'
compileOnly 'net.william278:DesertWell:1.1' compileOnly 'net.william278:DesertWell:1.1'
compileOnly 'net.william278:Annotaml:2.0'
} }
shadowJar { shadowJar {
@ -35,4 +36,5 @@ shadowJar {
relocate 'org.bstats', 'net.william278.husksync.libraries.bstats' relocate 'org.bstats', 'net.william278.husksync.libraries.bstats'
relocate 'net.william278.mpdbconverter', 'net.william278.husksync.libraries.mpdbconverter' relocate 'net.william278.mpdbconverter', 'net.william278.husksync.libraries.mpdbconverter'
relocate 'net.william278.hslmigrator', 'net.william278.husksync.libraries.hslconverter' relocate 'net.william278.hslmigrator', 'net.william278.husksync.libraries.hslconverter'
relocate 'net.william278.annotaml', 'net.william278.husksync.libraries.annotaml'
} }

@ -1,12 +1,7 @@
package net.william278.husksync; package net.william278.husksync;
import dev.dejvokep.boostedyaml.YamlDocument;
import dev.dejvokep.boostedyaml.dvs.versioning.BasicVersioning;
import dev.dejvokep.boostedyaml.settings.dumper.DumperSettings;
import dev.dejvokep.boostedyaml.settings.general.GeneralSettings;
import dev.dejvokep.boostedyaml.settings.loader.LoaderSettings;
import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings;
import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.william278.annotaml.Annotaml;
import net.william278.desertwell.Version; import net.william278.desertwell.Version;
import net.william278.husksync.command.BukkitCommand; import net.william278.husksync.command.BukkitCommand;
import net.william278.husksync.command.BukkitCommandType; import net.william278.husksync.command.BukkitCommandType;
@ -45,6 +40,7 @@ import org.jetbrains.annotations.NotNull;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -102,14 +98,14 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
getLoggingAdapter().log(Level.INFO, "Loading plugin configuration settings & locales..."); getLoggingAdapter().log(Level.INFO, "Loading plugin configuration settings & locales...");
initialized.set(reload().join()); initialized.set(reload().join());
if (initialized.get()) { if (initialized.get()) {
logger.showDebugLogs(settings.getBooleanValue(Settings.ConfigOption.DEBUG_LOGGING)); logger.showDebugLogs(settings.debugLogging);
getLoggingAdapter().log(Level.INFO, "Successfully loaded plugin configuration settings & locales"); getLoggingAdapter().log(Level.INFO, "Successfully loaded plugin configuration settings & locales");
} else { } else {
throw new HuskSyncInitializationException("Failed to load plugin configuration settings and/or locales"); throw new HuskSyncInitializationException("Failed to load plugin configuration settings and/or locales");
} }
// Prepare data adapter // Prepare data adapter
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_COMPRESS_DATA)) { if (settings.compressData) {
dataAdapter = new CompressedDataAdapter(); dataAdapter = new CompressedDataAdapter();
} else { } else {
dataAdapter = new JsonDataAdapter(); dataAdapter = new JsonDataAdapter();
@ -189,7 +185,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
} }
// Check for updates // Check for updates
if (settings.getBooleanValue(Settings.ConfigOption.CHECK_FOR_UPDATES)) { if (settings.checkForUpdates) {
getLoggingAdapter().log(Level.INFO, "Checking for updates..."); getLoggingAdapter().log(Level.INFO, "Checking for updates...");
getLatestVersionIfOutdated().thenAccept(newestVersion -> getLatestVersionIfOutdated().thenAccept(newestVersion ->
newestVersion.ifPresent(newVersion -> getLoggingAdapter().log(Level.WARNING, newestVersion.ifPresent(newVersion -> getLoggingAdapter().log(Level.WARNING,
@ -325,11 +321,17 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
public CompletableFuture<Boolean> reload() { public CompletableFuture<Boolean> reload() {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
try { try {
this.settings = Settings.load(YamlDocument.create(new File(getDataFolder(), "config.yml"), Objects.requireNonNull(resourceReader.getResource("config.yml")), GeneralSettings.builder().setUseDefaults(false).build(), LoaderSettings.builder().setAutoUpdate(true).build(), DumperSettings.builder().setEncoding(DumperSettings.Encoding.UNICODE).build(), UpdaterSettings.builder().setVersioning(new BasicVersioning("config_version")).build())); // Load plugin settings
this.settings = Annotaml.create(new File(getDataFolder(), "config.yml"), new Settings()).get();
this.locales = Locales.load(YamlDocument.create(new File(getDataFolder(), "messages-" + settings.getStringValue(Settings.ConfigOption.LANGUAGE) + ".yml"), Objects.requireNonNull(resourceReader.getResource("locales/" + settings.getStringValue(Settings.ConfigOption.LANGUAGE) + ".yml"))));
// 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"),
languagePresets).get();
return true; return true;
} catch (IOException | NullPointerException e) { } catch (IOException | NullPointerException | InvocationTargetException | IllegalAccessException |
InstantiationException e) {
getLoggingAdapter().log(Level.SEVERE, "Failed to load data from the config", e); getLoggingAdapter().log(Level.SEVERE, "Failed to load data from the config", e);
return false; return false;
} }

@ -4,7 +4,6 @@ import com.zaxxer.hikari.HikariDataSource;
import me.william278.husksync.bukkit.data.DataSerializer; import me.william278.husksync.bukkit.data.DataSerializer;
import net.william278.hslmigrator.HSLConverter; import net.william278.hslmigrator.HSLConverter;
import net.william278.husksync.HuskSync; import net.william278.husksync.HuskSync;
import net.william278.husksync.config.Settings;
import net.william278.husksync.data.*; import net.william278.husksync.data.*;
import net.william278.husksync.player.User; import net.william278.husksync.player.User;
import org.bukkit.Material; import org.bukkit.Material;
@ -38,11 +37,11 @@ public class LegacyMigrator extends Migrator {
public LegacyMigrator(@NotNull HuskSync plugin) { public LegacyMigrator(@NotNull HuskSync plugin) {
super(plugin); super(plugin);
this.hslConverter = HSLConverter.getInstance(); this.hslConverter = HSLConverter.getInstance();
this.sourceHost = plugin.getSettings().getStringValue(Settings.ConfigOption.DATABASE_HOST); this.sourceHost = plugin.getSettings().mySqlHost;
this.sourcePort = plugin.getSettings().getIntegerValue(Settings.ConfigOption.DATABASE_PORT); this.sourcePort = plugin.getSettings().mySqlPort;
this.sourceUsername = plugin.getSettings().getStringValue(Settings.ConfigOption.DATABASE_USERNAME); this.sourceUsername = plugin.getSettings().mySqlUsername;
this.sourcePassword = plugin.getSettings().getStringValue(Settings.ConfigOption.DATABASE_PASSWORD); this.sourcePassword = plugin.getSettings().mySqlPassword;
this.sourceDatabase = plugin.getSettings().getStringValue(Settings.ConfigOption.DATABASE_NAME); this.sourceDatabase = plugin.getSettings().mySqlDatabase;
this.sourcePlayersTable = "husksync_players"; this.sourcePlayersTable = "husksync_players";
this.sourceDataTable = "husksync_data"; this.sourceDataTable = "husksync_data";
this.minecraftVersion = plugin.getMinecraftVersion().toString(); this.minecraftVersion = plugin.getMinecraftVersion().toString();

@ -2,7 +2,6 @@ package net.william278.husksync.migrator;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import net.william278.husksync.BukkitHuskSync; import net.william278.husksync.BukkitHuskSync;
import net.william278.husksync.config.Settings;
import net.william278.husksync.data.*; import net.william278.husksync.data.*;
import net.william278.husksync.player.User; import net.william278.husksync.player.User;
import net.william278.mpdbconverter.MPDBConverter; import net.william278.mpdbconverter.MPDBConverter;
@ -16,7 +15,9 @@ import org.jetbrains.annotations.NotNull;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.util.*; import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level; import java.util.logging.Level;
@ -41,11 +42,11 @@ public class MpdbMigrator extends Migrator {
public MpdbMigrator(@NotNull BukkitHuskSync plugin, @NotNull Plugin mySqlPlayerDataBridge) { public MpdbMigrator(@NotNull BukkitHuskSync plugin, @NotNull Plugin mySqlPlayerDataBridge) {
super(plugin); super(plugin);
this.mpdbConverter = MPDBConverter.getInstance(mySqlPlayerDataBridge); this.mpdbConverter = MPDBConverter.getInstance(mySqlPlayerDataBridge);
this.sourceHost = plugin.getSettings().getStringValue(Settings.ConfigOption.DATABASE_HOST); this.sourceHost = plugin.getSettings().mySqlHost;
this.sourcePort = plugin.getSettings().getIntegerValue(Settings.ConfigOption.DATABASE_PORT); this.sourcePort = plugin.getSettings().mySqlPort;
this.sourceUsername = plugin.getSettings().getStringValue(Settings.ConfigOption.DATABASE_USERNAME); this.sourceUsername = plugin.getSettings().mySqlUsername;
this.sourcePassword = plugin.getSettings().getStringValue(Settings.ConfigOption.DATABASE_PASSWORD); this.sourcePassword = plugin.getSettings().mySqlPassword;
this.sourceDatabase = plugin.getSettings().getStringValue(Settings.ConfigOption.DATABASE_NAME); this.sourceDatabase = plugin.getSettings().mySqlDatabase;
this.sourceInventoryTable = "mpdb_inventory"; this.sourceInventoryTable = "mpdb_inventory";
this.sourceEnderChestTable = "mpdb_enderchest"; this.sourceEnderChestTable = "mpdb_enderchest";
this.sourceExperienceTable = "mpdb_experience"; this.sourceExperienceTable = "mpdb_experience";

@ -5,6 +5,7 @@ import de.themoep.minedown.adventure.MineDownParser;
import net.kyori.adventure.audience.Audience; import net.kyori.adventure.audience.Audience;
import net.william278.desertwell.Version; import net.william278.desertwell.Version;
import net.william278.husksync.BukkitHuskSync; import net.william278.husksync.BukkitHuskSync;
import net.william278.husksync.config.Settings;
import net.william278.husksync.data.*; import net.william278.husksync.data.*;
import net.william278.husksync.editor.ItemEditorMenu; import net.william278.husksync.editor.ItemEditorMenu;
import org.bukkit.*; import org.bukkit.*;
@ -83,19 +84,18 @@ public class BukkitPlayer extends OnlineUser {
} }
@Override @Override
public CompletableFuture<Void> setStatus(@NotNull StatusData statusData, public CompletableFuture<Void> setStatus(@NotNull StatusData statusData, @NotNull Settings settings) {
@NotNull List<StatusDataFlag> statusDataFlags) {
return CompletableFuture.runAsync(() -> { return CompletableFuture.runAsync(() -> {
double currentMaxHealth = Objects.requireNonNull(player.getAttribute(Attribute.GENERIC_MAX_HEALTH)) double currentMaxHealth = Objects.requireNonNull(player.getAttribute(Attribute.GENERIC_MAX_HEALTH))
.getBaseValue(); .getBaseValue();
if (statusDataFlags.contains(StatusDataFlag.SET_MAX_HEALTH)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.MAX_HEALTH)) {
if (statusData.maxHealth != 0d) { if (statusData.maxHealth != 0d) {
Objects.requireNonNull(player.getAttribute(Attribute.GENERIC_MAX_HEALTH)) Objects.requireNonNull(player.getAttribute(Attribute.GENERIC_MAX_HEALTH))
.setBaseValue(statusData.maxHealth); .setBaseValue(statusData.maxHealth);
currentMaxHealth = statusData.maxHealth; currentMaxHealth = statusData.maxHealth;
} }
} }
if (statusDataFlags.contains(StatusDataFlag.SET_HEALTH)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.HEALTH)) {
final double currentHealth = player.getHealth(); final double currentHealth = player.getHealth();
if (statusData.health != currentHealth) { if (statusData.health != currentHealth) {
final double healthToSet = currentHealth > currentMaxHealth ? currentMaxHealth : statusData.health; final double healthToSet = currentHealth > currentMaxHealth ? currentMaxHealth : statusData.health;
@ -113,24 +113,24 @@ public class BukkitPlayer extends OnlineUser {
} }
player.setHealthScaled(statusData.healthScale != 0D); player.setHealthScaled(statusData.healthScale != 0D);
} }
if (statusDataFlags.contains(StatusDataFlag.SET_HUNGER)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.HUNGER)) {
player.setFoodLevel(statusData.hunger); player.setFoodLevel(statusData.hunger);
player.setSaturation(statusData.saturation); player.setSaturation(statusData.saturation);
player.setExhaustion(statusData.saturationExhaustion); player.setExhaustion(statusData.saturationExhaustion);
} }
if (statusDataFlags.contains(StatusDataFlag.SET_SELECTED_ITEM_SLOT)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.INVENTORIES)) {
player.getInventory().setHeldItemSlot(statusData.selectedItemSlot); player.getInventory().setHeldItemSlot(statusData.selectedItemSlot);
} }
if (statusDataFlags.contains(StatusDataFlag.SET_EXPERIENCE)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.EXPERIENCE)) {
player.setTotalExperience(statusData.totalExperience); player.setTotalExperience(statusData.totalExperience);
player.setLevel(statusData.expLevel); player.setLevel(statusData.expLevel);
player.setExp(statusData.expProgress); player.setExp(statusData.expProgress);
} }
if (statusDataFlags.contains(StatusDataFlag.SET_GAME_MODE)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.GAME_MODE)) {
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () ->
player.setGameMode(GameMode.valueOf(statusData.gameMode))); player.setGameMode(GameMode.valueOf(statusData.gameMode)));
} }
if (statusDataFlags.contains(StatusDataFlag.SET_FLYING)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.LOCATION)) {
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> { Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
if (statusData.isFlying) { if (statusData.isFlying) {
player.setAllowFlight(true); player.setAllowFlight(true);

@ -4,6 +4,7 @@ dependencies {
implementation 'net.kyori:adventure-api:4.11.0' implementation 'net.kyori:adventure-api:4.11.0'
implementation 'com.google.code.gson:gson:2.9.0' implementation 'com.google.code.gson:gson:2.9.0'
implementation 'dev.dejvokep:boosted-yaml:1.3' implementation 'dev.dejvokep:boosted-yaml:1.3'
implementation 'net.william278:Annotaml:2.0'
implementation 'net.william278:DesertWell:1.1' implementation 'net.william278:DesertWell:1.1'
implementation 'net.william278:PagineDown:1.1' implementation 'net.william278:PagineDown:1.1'
implementation('com.zaxxer:HikariCP:5.0.1') { implementation('com.zaxxer:HikariCP:5.0.1') {
@ -33,4 +34,5 @@ shadowJar {
relocate 'dev.dejvokep', 'net.william278.husksync.libraries' relocate 'dev.dejvokep', 'net.william278.husksync.libraries'
relocate 'net.william278.desertwell', 'net.william278.husksync.libraries.desertwell' relocate 'net.william278.desertwell', 'net.william278.husksync.libraries.desertwell'
relocate 'net.william278.paginedown', 'net.william278.husksync.libraries.paginedown' relocate 'net.william278.paginedown', 'net.william278.husksync.libraries.paginedown'
relocate 'net.william278.annotaml', 'net.william278.husksync.libraries.annotaml'
} }

@ -1,32 +1,37 @@
package net.william278.husksync.config; package net.william278.husksync.config;
import de.themoep.minedown.adventure.MineDown; import de.themoep.minedown.adventure.MineDown;
import dev.dejvokep.boostedyaml.YamlDocument; import net.william278.annotaml.YamlFile;
import net.william278.paginedown.ListOptions; import net.william278.paginedown.ListOptions;
import org.apache.commons.text.StringEscapeUtils; import org.apache.commons.text.StringEscapeUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
/** /**
* Loaded locales used by the plugin to display various locales * Loaded locales used by the plugin to display styled messages
*/ */
@YamlFile(rootedMap = true, header = """
HuskHomes Locales
Developed by William278
See plugin about menu for international locale credits
Formatted in MineDown: https://github.com/Phoenix616/MineDown
Translate HuskSync: https://william278.net/docs/husksync/Translations""")
public class Locales { public class Locales {
/**
* The raw set of locales loaded from yaml
*/
@NotNull @NotNull
private final HashMap<String, String> rawLocales; public Map<String, String> rawLocales = new HashMap<>();
private Locales(@NotNull YamlDocument localesConfig) {
this.rawLocales = new HashMap<>();
for (String localeId : localesConfig.getRoutesAsStrings(false)) {
rawLocales.put(localeId, localesConfig.getString(localeId));
}
}
/** /**
* Returns an un-formatted locale loaded from the locales file * Returns a raw, un-formatted locale loaded from the locales file
* *
* @param localeId String identifier of the locale, corresponding to a key in the file * @param localeId String identifier of the locale, corresponding to a key in the file
* @return An {@link Optional} containing the locale corresponding to the id, if it exists * @return An {@link Optional} containing the locale corresponding to the id, if it exists
@ -36,7 +41,9 @@ public class Locales {
} }
/** /**
* Returns an un-formatted locale loaded from the locales file, with replacements applied * Returns a raw, un-formatted locale loaded from the locales file, with replacements applied
* <p>
* Note that replacements will not be MineDown-escaped; use {@link #escapeMineDown(String)} to escape replacements
* *
* @param localeId String identifier of the locale, corresponding to a key in the file * @param localeId String identifier of the locale, corresponding to a key in the file
* @param replacements Ordered array of replacement strings to fill in placeholders with * @param replacements Ordered array of replacement strings to fill in placeholders with
@ -77,12 +84,13 @@ public class Locales {
* @param replacements Ordered array of replacement strings to fill in placeholders with * @param replacements Ordered array of replacement strings to fill in placeholders with
* @return the raw locale, with inserted placeholders * @return the raw locale, with inserted placeholders
*/ */
@NotNull
private String applyReplacements(@NotNull String rawLocale, @NotNull String... replacements) { private String applyReplacements(@NotNull String rawLocale, @NotNull String... replacements) {
int replacementIndexer = 1; int replacementIndexer = 1;
for (String replacement : replacements) { for (String replacement : replacements) {
String replacementString = "%" + replacementIndexer + "%"; String replacementString = "%" + replacementIndexer + "%";
rawLocale = rawLocale.replace(replacementString, replacement); rawLocale = rawLocale.replace(replacementString, replacement);
replacementIndexer = replacementIndexer + 1; replacementIndexer += 1;
} }
return rawLocale; return rawLocale;
} }
@ -143,14 +151,8 @@ public class Locales {
.setSpaceBeforeFooter(false); .setSpaceBeforeFooter(false);
} }
/** @SuppressWarnings("unused")
* Load the locales from a BoostedYaml {@link YamlDocument} locales file public Locales() {
*
* @param localesConfig The loaded {@link YamlDocument} locales.yml file
* @return the loaded {@link Locales}
*/
public static Locales load(@NotNull YamlDocument localesConfig) {
return new Locales(localesConfig);
} }
} }

@ -1,275 +1,189 @@
package net.william278.husksync.config; package net.william278.husksync.config;
import dev.dejvokep.boostedyaml.YamlDocument; import net.william278.annotaml.YamlComment;
import net.william278.annotaml.YamlFile;
import net.william278.annotaml.YamlKey;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*; import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
/** /**
* Settings used for the plugin, as read from the config file * Plugin settings, read from config.yml
*/ */
@YamlFile(header = """
HuskSync Config
Developed by William278
Information: https://william278.net/project/husksync
Documentation: https://william278.net/docs/husksync""",
versionField = "config_version", versionNumber = 2)
public class Settings { public class Settings {
/** // Top-level settings
* Map of {@link ConfigOption}s read from the config file public String language = "en-gb";
*/
private final Map<ConfigOption, Object> configOptions;
// Load the settings from the document
private Settings(@NotNull YamlDocument config) {
this.configOptions = new HashMap<>();
Arrays.stream(ConfigOption.values()).forEach(configOption -> configOptions
.put(configOption, switch (configOption.optionType) {
case BOOLEAN -> configOption.getBooleanValue(config);
case STRING -> configOption.getStringValue(config);
case DOUBLE -> configOption.getDoubleValue(config);
case FLOAT -> configOption.getFloatValue(config);
case INTEGER -> configOption.getIntValue(config);
case STRING_LIST -> configOption.getStringListValue(config);
}));
}
// Default constructor for empty settings @YamlKey("check_for_updates")
protected Settings(@NotNull Map<ConfigOption, Object> configOptions) { public boolean checkForUpdates = true;
this.configOptions = configOptions;
}
/** @YamlKey("cluster_id")
* Get the value of the specified {@link ConfigOption} public String clusterId = "";
*
* @param option the {@link ConfigOption} to check
* @return the value of the {@link ConfigOption} as a boolean
* @throws ClassCastException if the option is not a boolean
*/
public boolean getBooleanValue(@NotNull ConfigOption option) throws ClassCastException {
return (Boolean) configOptions.get(option);
}
/** @YamlKey("debug_logging")
* Get the value of the specified {@link ConfigOption} public boolean debugLogging = false;
*
* @param option the {@link ConfigOption} to check
* @return the value of the {@link ConfigOption} as a string
* @throws ClassCastException if the option is not a string
*/
public String getStringValue(@NotNull ConfigOption option) throws ClassCastException {
return (String) configOptions.get(option);
}
/**
* Get the value of the specified {@link ConfigOption}
*
* @param option the {@link ConfigOption} to check
* @return the value of the {@link ConfigOption} as a double
* @throws ClassCastException if the option is not a double
*/
public double getDoubleValue(@NotNull ConfigOption option) throws ClassCastException {
return (Double) configOptions.get(option);
}
/** // Database settings
* Get the value of the specified {@link ConfigOption} @YamlComment("Database connection settings")
* @YamlKey("database.credentials.host")
* @param option the {@link ConfigOption} to check public String mySqlHost = "localhost";
* @return the value of the {@link ConfigOption} as a float
* @throws ClassCastException if the option is not a float
*/
public double getFloatValue(@NotNull ConfigOption option) throws ClassCastException {
return (Float) configOptions.get(option);
}
/** @YamlKey("database.credentials.port")
* Get the value of the specified {@link ConfigOption} public int mySqlPort = 3306;
*
* @param option the {@link ConfigOption} to check
* @return the value of the {@link ConfigOption} as an integer
* @throws ClassCastException if the option is not an integer
*/
public int getIntegerValue(@NotNull ConfigOption option) throws ClassCastException {
return (Integer) configOptions.get(option);
}
/** @YamlKey("database.credentials.database")
* Get the value of the specified {@link ConfigOption} public String mySqlDatabase = "HuskSync";
*
* @param option the {@link ConfigOption} to check
* @return the value of the {@link ConfigOption} as a string {@link List}
* @throws ClassCastException if the option is not a string list
*/
@SuppressWarnings("unchecked")
public List<String> getStringListValue(@NotNull ConfigOption option) throws ClassCastException {
return (List<String>) configOptions.get(option);
}
@YamlKey("database.mysql.credentials.username")
public String mySqlUsername = "root";
/** @YamlKey("database.credentials.password")
* Load the settings from a BoostedYaml {@link YamlDocument} config file public String mySqlPassword = "pa55w0rd";
*
* @param config The loaded {@link YamlDocument} config.yml file
* @return the loaded {@link Settings}
*/
public static Settings load(@NotNull YamlDocument config) {
return new Settings(config);
}
/** @YamlKey("database.credentials.parameters")
* Represents an option stored by a path in config.yml public String mySqlConnectionParameters = "?autoReconnect=true&useSSL=false";
*/
public enum ConfigOption {
LANGUAGE("language", OptionType.STRING, "en-gb"),
CHECK_FOR_UPDATES("check_for_updates", OptionType.BOOLEAN, true),
CLUSTER_ID("cluster_id", OptionType.STRING, ""),
DEBUG_LOGGING("debug_logging", OptionType.BOOLEAN, false),
DATABASE_HOST("database.credentials.host", OptionType.STRING, "localhost"),
DATABASE_PORT("database.credentials.port", OptionType.INTEGER, 3306),
DATABASE_NAME("database.credentials.database", OptionType.STRING, "HuskSync"),
DATABASE_USERNAME("database.credentials.username", OptionType.STRING, "root"),
DATABASE_PASSWORD("database.credentials.password", OptionType.STRING, "pa55w0rd"),
DATABASE_CONNECTION_PARAMS("database.credentials.params", OptionType.STRING, "?autoReconnect=true&useSSL=false"),
DATABASE_CONNECTION_POOL_MAX_SIZE("database.connection_pool.maximum_pool_size", OptionType.INTEGER, 10),
DATABASE_CONNECTION_POOL_MIN_IDLE("database.connection_pool.minimum_idle", OptionType.INTEGER, 10),
DATABASE_CONNECTION_POOL_MAX_LIFETIME("database.connection_pool.maximum_lifetime", OptionType.INTEGER, 1800000),
DATABASE_CONNECTION_POOL_KEEPALIVE("database.connection_pool.keepalive_time", OptionType.INTEGER, 0),
DATABASE_CONNECTION_POOL_TIMEOUT("database.connection_pool.connection_timeout", OptionType.INTEGER, 5000),
DATABASE_USERS_TABLE_NAME("database.table_names.users_table", OptionType.STRING, "husksync_users"),
DATABASE_USER_DATA_TABLE_NAME("database.table_names.user_data_table", OptionType.STRING, "husksync_user_data"),
REDIS_HOST("redis.credentials.host", OptionType.STRING, "localhost"),
REDIS_PORT("redis.credentials.port", OptionType.INTEGER, 6379),
REDIS_PASSWORD("redis.credentials.password", OptionType.STRING, ""),
REDIS_USE_SSL("redis.use_ssl", OptionType.BOOLEAN, false),
SYNCHRONIZATION_MAX_USER_DATA_SNAPSHOTS("synchronization.max_user_data_snapshots", OptionType.INTEGER, 5),
SYNCHRONIZATION_SAVE_ON_WORLD_SAVE("synchronization.save_on_world_save", OptionType.BOOLEAN, true),
SYNCHRONIZATION_COMPRESS_DATA("synchronization.compress_data", OptionType.BOOLEAN, true),
SYNCHRONIZATION_NETWORK_LATENCY_MILLISECONDS("synchronization.network_latency_milliseconds", OptionType.INTEGER, 500),
SYNCHRONIZATION_SAVE_DEAD_PLAYER_INVENTORIES("synchronization.save_dead_player_inventories", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_INVENTORIES("synchronization.features.inventories", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_ENDER_CHESTS("synchronization.features.ender_chests", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_HEALTH("synchronization.features.health", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_MAX_HEALTH("synchronization.features.max_health", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_HUNGER("synchronization.features.hunger", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_EXPERIENCE("synchronization.features.experience", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_POTION_EFFECTS("synchronization.features.potion_effects", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_ADVANCEMENTS("synchronization.features.advancements", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_GAME_MODE("synchronization.features.game_mode", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_STATISTICS("synchronization.features.statistics", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_PERSISTENT_DATA_CONTAINER("synchronization.features.persistent_data_container", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_LOCATION("synchronization.features.location", OptionType.BOOLEAN, true);
/** @YamlComment("MySQL connection pool properties")
* The path in the config.yml file to the value @YamlKey("database.connection_pool.maximum_pool_size")
*/ public int mySqlConnectionPoolSize = 10;
@NotNull
public final String configPath;
/** @YamlKey("database.connection_pool.minimum_idle")
* The {@link OptionType} of this option public int mySqlConnectionPoolIdle = 10;
*/
@NotNull
public final OptionType optionType;
/** @YamlKey("database.connection_pool.maximum_lifetime")
* The default value of this option if not set in config public long mySqlConnectionPoolLifetime = 1800000;
*/
@Nullable
private final Object defaultValue;
ConfigOption(@NotNull String configPath, @NotNull OptionType optionType, @Nullable Object defaultValue) { @YamlKey("database.connection_pool.keepalive_time")
this.configPath = configPath; public long mySqlConnectionPoolKeepAlive = 0;
this.optionType = optionType;
this.defaultValue = defaultValue; @YamlKey("database.connection_pool.connection_timeout")
} public long mySqlConnectionPoolTimeout = 5000;
@YamlKey("database.table_names")
public Map<String, String> tableNames = TableName.getDefaults();
ConfigOption(@NotNull String configPath, @NotNull OptionType optionType) { @NotNull
this.configPath = configPath; public String getTableName(@NotNull TableName tableName) {
this.optionType = optionType; return Optional.ofNullable(tableNames.get(tableName.name().toLowerCase()))
this.defaultValue = null; .orElse(tableName.defaultName);
} }
/**
* Get the value at the path specified (or return default if set), as a string // Redis settings
* @YamlComment("Redis connection settings")
* @param config The {@link YamlDocument} config file @YamlKey("redis.credentials.host")
* @return the value defined in the config, as a string public String redisHost = "localhost";
*/
public String getStringValue(@NotNull YamlDocument config) { @YamlKey("redis.credentials.port")
return defaultValue != null public int redisPort = 6379;
? config.getString(configPath, (String) defaultValue)
: config.getString(configPath); @YamlKey("redis.credentials.password")
public String redisPassword = "";
@YamlKey("redis.use_ssl")
public boolean redisUseSsl = false;
// Synchronization settings
@YamlComment("Synchronization settings")
@YamlKey("synchronization.max_user_data_snapshots")
public int maxUserDataSnapshots = 5;
@YamlKey("synchronization.save_on_world_save")
public boolean saveOnWorldSave = true;
@YamlKey("synchronization.save_on_death")
public boolean saveOnDeath = false;
@YamlKey("synchronization.compress_data")
public boolean compressData = true;
@YamlKey("synchronization.save_dead_player_inventories")
public boolean saveDeadPlayerInventories = true;
@YamlKey("synchronization.network_latency_milliseconds")
public int networkLatencyMilliseconds = 500;
@YamlKey("synchronization.features")
public Map<String, Boolean> synchronizationFeatures = SynchronizationFeature.getDefaults();
public boolean getSynchronizationFeature(@NotNull SynchronizationFeature feature) {
return Optional.ofNullable(synchronizationFeatures.get(feature.name().toLowerCase()))
.orElse(feature.enabledByDefault);
} }
/** /**
* Get the value at the path specified (or return default if set), as a boolean * Represents the names of tables in the database
*
* @param config The {@link YamlDocument} config file
* @return the value defined in the config, as a boolean
*/ */
public boolean getBooleanValue(@NotNull YamlDocument config) { public enum TableName {
return defaultValue != null USERS("husksync_users"),
? config.getBoolean(configPath, (Boolean) defaultValue) USER_DATA("husksync_user_data");
: config.getBoolean(configPath);
private final String defaultName;
TableName(@NotNull String defaultName) {
this.defaultName = defaultName;
} }
/** private Map.Entry<String, String> toEntry() {
* Get the value at the path specified (or return default if set), as a double return Map.entry(name().toLowerCase(), defaultName);
*
* @param config The {@link YamlDocument} config file
* @return the value defined in the config, as a double
*/
public double getDoubleValue(@NotNull YamlDocument config) {
return defaultValue != null
? config.getDouble(configPath, (Double) defaultValue)
: config.getDouble(configPath);
} }
/** @SuppressWarnings("unchecked")
* Get the value at the path specified (or return default if set), as a float private static Map<String, String> getDefaults() {
* return Map.ofEntries(Arrays.stream(values())
* @param config The {@link YamlDocument} config file .map(TableName::toEntry)
* @return the value defined in the config, as a float .toArray(Map.Entry[]::new));
*/ }
public float getFloatValue(@NotNull YamlDocument config) {
return defaultValue != null
? config.getFloat(configPath, (Float) defaultValue)
: config.getFloat(configPath);
} }
/** /**
* Get the value at the path specified (or return default if set), as an int * Represents enabled synchronisation features
*
* @param config The {@link YamlDocument} config file
* @return the value defined in the config, as an int
*/ */
public int getIntValue(@NotNull YamlDocument config) { public enum SynchronizationFeature {
return defaultValue != null
? config.getInt(configPath, (Integer) defaultValue) INVENTORIES(true),
: config.getInt(configPath); ENDER_CHESTS(true),
HEALTH(true),
MAX_HEALTH(true),
HUNGER(true),
EXPERIENCE(true),
POTION_EFFECTS(true),
ADVANCEMENTS(true),
GAME_MODE(true),
STATISTICS(true),
PERSISTENT_DATA_CONTAINER(false),
LOCATION(false);
private final boolean enabledByDefault;
SynchronizationFeature(boolean enabledByDefault) {
this.enabledByDefault = enabledByDefault;
} }
/** private Map.Entry<String, Boolean> toEntry() {
* Get the value at the path specified (or return default if set), as a string {@link List} return Map.entry(name().toLowerCase(), enabledByDefault);
*
* @param config The {@link YamlDocument} config file
* @return the value defined in the config, as a string {@link List}
*/
public List<String> getStringListValue(@NotNull YamlDocument config) {
return config.getStringList(configPath, new ArrayList<>());
} }
/** @SuppressWarnings("unchecked")
* Represents the type of the object private static Map<String, Boolean> getDefaults() {
*/ return Map.ofEntries(Arrays.stream(values())
public enum OptionType { .map(SynchronizationFeature::toEntry)
BOOLEAN, .toArray(Map.Entry[]::new));
STRING,
DOUBLE,
FLOAT,
INTEGER,
STRING_LIST
} }
} }

@ -8,29 +8,34 @@ import java.util.List;
/** /**
* Flags for setting {@link StatusData}, indicating which elements should be synced * Flags for setting {@link StatusData}, indicating which elements should be synced
*
* @deprecated Use the more direct {@link Settings#getSynchronizationFeature(Settings.SynchronizationFeature)} instead
*/ */
@Deprecated(since = "2.1")
public enum StatusDataFlag { public enum StatusDataFlag {
SET_HEALTH(Settings.ConfigOption.SYNCHRONIZATION_SYNC_HEALTH), SET_HEALTH(Settings.SynchronizationFeature.HEALTH),
SET_MAX_HEALTH(Settings.ConfigOption.SYNCHRONIZATION_SYNC_MAX_HEALTH), SET_MAX_HEALTH(Settings.SynchronizationFeature.MAX_HEALTH),
SET_HUNGER(Settings.ConfigOption.SYNCHRONIZATION_SYNC_HUNGER), SET_HUNGER(Settings.SynchronizationFeature.HUNGER),
SET_EXPERIENCE(Settings.ConfigOption.SYNCHRONIZATION_SYNC_EXPERIENCE), SET_EXPERIENCE(Settings.SynchronizationFeature.EXPERIENCE),
SET_GAME_MODE(Settings.ConfigOption.SYNCHRONIZATION_SYNC_GAME_MODE), SET_GAME_MODE(Settings.SynchronizationFeature.GAME_MODE),
SET_FLYING(Settings.ConfigOption.SYNCHRONIZATION_SYNC_LOCATION), SET_FLYING(Settings.SynchronizationFeature.LOCATION),
SET_SELECTED_ITEM_SLOT(Settings.ConfigOption.SYNCHRONIZATION_SYNC_INVENTORIES); SET_SELECTED_ITEM_SLOT(Settings.SynchronizationFeature.INVENTORIES);
private final Settings.ConfigOption configOption; private final Settings.SynchronizationFeature feature;
StatusDataFlag(@NotNull Settings.ConfigOption configOption) { StatusDataFlag(@NotNull Settings.SynchronizationFeature feature) {
this.configOption = configOption; this.feature = feature;
} }
/** /**
* Returns all status data flags * Returns all status data flags
* *
* @return all status data flags as a list * @return all status data flags as a list
* @deprecated Use {@link Settings#getSynchronizationFeature(Settings.SynchronizationFeature)} instead
*/ */
@NotNull @NotNull
@Deprecated(since = "2.1")
@SuppressWarnings("unused") @SuppressWarnings("unused")
public static List<StatusDataFlag> getAll() { public static List<StatusDataFlag> getAll() {
return Arrays.stream(StatusDataFlag.values()).toList(); return Arrays.stream(StatusDataFlag.values()).toList();
@ -41,11 +46,13 @@ public enum StatusDataFlag {
* *
* @param settings the settings to use for determining which flags are enabled * @param settings the settings to use for determining which flags are enabled
* @return all status data flags that are enabled for setting * @return all status data flags that are enabled for setting
* @deprecated Use {@link Settings#getSynchronizationFeature(Settings.SynchronizationFeature)} instead
*/ */
@NotNull @NotNull
@Deprecated(since = "2.1")
public static List<StatusDataFlag> getFromSettings(@NotNull Settings settings) { public static List<StatusDataFlag> getFromSettings(@NotNull Settings settings) {
return Arrays.stream(StatusDataFlag.values()).filter( return Arrays.stream(StatusDataFlag.values()).filter(
flag -> settings.getBooleanValue(flag.configOption)).toList(); flag -> settings.getSynchronizationFeature(flag.feature)).toList();
} }
} }

@ -40,9 +40,9 @@ public class MySqlDatabase extends Database {
private final int hikariMaximumPoolSize; private final int hikariMaximumPoolSize;
private final int hikariMinimumIdle; private final int hikariMinimumIdle;
private final int hikariMaximumLifetime; private final long hikariMaximumLifetime;
private final int hikariKeepAliveTime; private final long hikariKeepAliveTime;
private final int hikariConnectionTimeOut; private final long hikariConnectionTimeOut;
private static final String DATA_POOL_NAME = "HuskSyncHikariPool"; private static final String DATA_POOL_NAME = "HuskSyncHikariPool";
@ -53,21 +53,21 @@ public class MySqlDatabase extends Database {
public MySqlDatabase(@NotNull Settings settings, @NotNull ResourceReader resourceReader, @NotNull Logger logger, public MySqlDatabase(@NotNull Settings settings, @NotNull ResourceReader resourceReader, @NotNull Logger logger,
@NotNull DataAdapter dataAdapter, @NotNull EventCannon eventCannon) { @NotNull DataAdapter dataAdapter, @NotNull EventCannon eventCannon) {
super(settings.getStringValue(Settings.ConfigOption.DATABASE_USERS_TABLE_NAME), super(settings.getTableName(Settings.TableName.USERS),
settings.getStringValue(Settings.ConfigOption.DATABASE_USER_DATA_TABLE_NAME), settings.getTableName(Settings.TableName.USER_DATA),
Math.max(1, Math.min(20, settings.getIntegerValue(Settings.ConfigOption.SYNCHRONIZATION_MAX_USER_DATA_SNAPSHOTS))), Math.max(1, Math.min(20, settings.maxUserDataSnapshots)),
resourceReader, dataAdapter, eventCannon, logger); resourceReader, dataAdapter, eventCannon, logger);
this.mySqlHost = settings.getStringValue(Settings.ConfigOption.DATABASE_HOST); this.mySqlHost = settings.mySqlHost;
this.mySqlPort = settings.getIntegerValue(Settings.ConfigOption.DATABASE_PORT); this.mySqlPort = settings.mySqlPort;
this.mySqlDatabaseName = settings.getStringValue(Settings.ConfigOption.DATABASE_NAME); this.mySqlDatabaseName = settings.mySqlDatabase;
this.mySqlUsername = settings.getStringValue(Settings.ConfigOption.DATABASE_USERNAME); this.mySqlUsername = settings.mySqlUsername;
this.mySqlPassword = settings.getStringValue(Settings.ConfigOption.DATABASE_PASSWORD); this.mySqlPassword = settings.mySqlPassword;
this.mySqlConnectionParameters = settings.getStringValue(Settings.ConfigOption.DATABASE_CONNECTION_PARAMS); this.mySqlConnectionParameters = settings.mySqlConnectionParameters;
this.hikariMaximumPoolSize = settings.getIntegerValue(Settings.ConfigOption.DATABASE_CONNECTION_POOL_MAX_SIZE); this.hikariMaximumPoolSize = settings.mySqlConnectionPoolSize;
this.hikariMinimumIdle = settings.getIntegerValue(Settings.ConfigOption.DATABASE_CONNECTION_POOL_MIN_IDLE); this.hikariMinimumIdle = settings.mySqlConnectionPoolIdle;
this.hikariMaximumLifetime = settings.getIntegerValue(Settings.ConfigOption.DATABASE_CONNECTION_POOL_MAX_LIFETIME); this.hikariMaximumLifetime = settings.mySqlConnectionPoolLifetime;
this.hikariKeepAliveTime = settings.getIntegerValue(Settings.ConfigOption.DATABASE_CONNECTION_POOL_KEEPALIVE); this.hikariKeepAliveTime = settings.mySqlConnectionPoolKeepAlive;
this.hikariConnectionTimeOut = settings.getIntegerValue(Settings.ConfigOption.DATABASE_CONNECTION_POOL_TIMEOUT); this.hikariConnectionTimeOut = settings.mySqlConnectionPoolTimeout;
} }
/** /**

@ -1,11 +1,10 @@
package net.william278.husksync.listener; package net.william278.husksync.listener;
import net.william278.husksync.HuskSync; import net.william278.husksync.HuskSync;
import net.william278.husksync.config.Settings;
import net.william278.husksync.data.ItemData;
import net.william278.husksync.data.DataSaveCause; import net.william278.husksync.data.DataSaveCause;
import net.william278.husksync.player.OnlineUser; import net.william278.husksync.data.ItemData;
import net.william278.husksync.editor.ItemEditorMenuType; import net.william278.husksync.editor.ItemEditorMenuType;
import net.william278.husksync.player.OnlineUser;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.HashSet; import java.util.HashSet;
@ -57,7 +56,7 @@ public abstract class EventListener {
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
try { try {
// Hold reading data for the network latency threshold, to ensure the source server has set the redis key // 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().getIntegerValue(Settings.ConfigOption.SYNCHRONIZATION_NETWORK_LATENCY_MILLISECONDS))); Thread.sleep(Math.max(0, plugin.getSettings().networkLatencyMilliseconds));
} catch (InterruptedException e) { } catch (InterruptedException e) {
plugin.getLoggingAdapter().log(Level.SEVERE, "An exception occurred handling a player join", e); plugin.getLoggingAdapter().log(Level.SEVERE, "An exception occurred handling a player join", e);
} finally { } finally {
@ -170,7 +169,7 @@ public abstract class EventListener {
* @param usersInWorld a list of users in the world that is being saved * @param usersInWorld a list of users in the world that is being saved
*/ */
protected final void handleAsyncWorldSave(@NotNull List<OnlineUser> usersInWorld) { protected final void handleAsyncWorldSave(@NotNull List<OnlineUser> usersInWorld) {
if (disabling || !plugin.getSettings().getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SAVE_ON_WORLD_SAVE)) { if (disabling || !plugin.getSettings().saveOnWorldSave) {
return; return;
} }
usersInWorld.forEach(user -> user.getUserData(plugin.getLoggingAdapter(), plugin.getSettings()).join().ifPresent( usersInWorld.forEach(user -> user.getUserData(plugin.getLoggingAdapter(), plugin.getSettings()).join().ifPresent(

@ -39,9 +39,30 @@ public abstract class OnlineUser extends User {
* @param statusData the player's {@link StatusData} * @param statusData the player's {@link StatusData}
* @param statusDataFlags the flags to use for setting the status data * @param statusDataFlags the flags to use for setting the status data
* @return a future returning void when complete * @return a future returning void when complete
* @deprecated Use {@link #setStatus(StatusData, Settings)} instead
*/
@Deprecated(since = "2.1")
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));
return setStatus(statusData, settings);
}
/**
* Set the player's {@link StatusData}
*
* @param statusData the player's {@link StatusData}
* @param settings settings, containing information about which features should be synced
* @return a future returning void when complete
*/ */
public abstract CompletableFuture<Void> setStatus(@NotNull StatusData statusData, public abstract CompletableFuture<Void> setStatus(@NotNull StatusData statusData,
@NotNull List<StatusDataFlag> statusDataFlags); @NotNull Settings settings);
/** /**
* Get the player's inventory {@link ItemData} contents * Get the player's inventory {@link ItemData} contents
@ -237,27 +258,26 @@ public abstract class OnlineUser extends User {
final UserData finalData = preSyncEvent.getUserData(); final UserData finalData = preSyncEvent.getUserData();
final List<CompletableFuture<Void>> dataSetOperations = new ArrayList<>() {{ final List<CompletableFuture<Void>> dataSetOperations = new ArrayList<>() {{
if (!isOffline() && !preSyncEvent.isCancelled()) { if (!isOffline() && !preSyncEvent.isCancelled()) {
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SYNC_INVENTORIES)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.INVENTORIES)) {
finalData.getInventory().ifPresent(itemData -> add(setInventory(itemData))); finalData.getInventory().ifPresent(itemData -> add(setInventory(itemData)));
} }
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SYNC_ENDER_CHESTS)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.ENDER_CHESTS)) {
finalData.getEnderChest().ifPresent(itemData -> add(setEnderChest(itemData))); finalData.getEnderChest().ifPresent(itemData -> add(setEnderChest(itemData)));
} }
finalData.getStatus().ifPresent(statusData -> add(setStatus(statusData, finalData.getStatus().ifPresent(statusData -> add(setStatus(statusData, settings)));
StatusDataFlag.getFromSettings(settings)))); if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.POTION_EFFECTS)) {
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SYNC_POTION_EFFECTS)) {
finalData.getPotionEffects().ifPresent(potionEffectData -> add(setPotionEffects(potionEffectData))); finalData.getPotionEffects().ifPresent(potionEffectData -> add(setPotionEffects(potionEffectData)));
} }
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SYNC_ADVANCEMENTS)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.ADVANCEMENTS)) {
finalData.getAdvancements().ifPresent(advancementData -> add(setAdvancements(advancementData))); finalData.getAdvancements().ifPresent(advancementData -> add(setAdvancements(advancementData)));
} }
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SYNC_STATISTICS)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.STATISTICS)) {
finalData.getStatistics().ifPresent(statisticData -> add(setStatistics(statisticData))); finalData.getStatistics().ifPresent(statisticData -> add(setStatistics(statisticData)));
} }
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SYNC_LOCATION)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.LOCATION)) {
finalData.getLocation().ifPresent(locationData -> add(setLocation(locationData))); finalData.getLocation().ifPresent(locationData -> add(setLocation(locationData)));
} }
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SYNC_PERSISTENT_DATA_CONTAINER)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.PERSISTENT_DATA_CONTAINER)) {
finalData.getPersistentDataContainer().ifPresent(persistentDataContainerData -> finalData.getPersistentDataContainer().ifPresent(persistentDataContainerData ->
add(setPersistentDataContainer(persistentDataContainerData))); add(setPersistentDataContainer(persistentDataContainerData)));
} }
@ -294,30 +314,30 @@ public abstract class OnlineUser extends User {
final UserDataBuilder builder = UserData.builder(getMinecraftVersion()); final UserDataBuilder builder = UserData.builder(getMinecraftVersion());
final List<CompletableFuture<Void>> dataGetOperations = new ArrayList<>() {{ final List<CompletableFuture<Void>> dataGetOperations = new ArrayList<>() {{
if (!isOffline()) { if (!isOffline()) {
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SYNC_INVENTORIES)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.INVENTORIES)) {
if (isDead() && settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SAVE_DEAD_PLAYER_INVENTORIES)) { if (isDead() && settings.saveDeadPlayerInventories) {
add(CompletableFuture.runAsync(() -> builder.setInventory(ItemData.empty()))); add(CompletableFuture.runAsync(() -> builder.setInventory(ItemData.empty())));
} else { } else {
add(getInventory().thenAccept(builder::setInventory)); add(getInventory().thenAccept(builder::setInventory));
} }
} }
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SYNC_ENDER_CHESTS)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.ENDER_CHESTS)) {
add(getEnderChest().thenAccept(builder::setEnderChest)); add(getEnderChest().thenAccept(builder::setEnderChest));
} }
add(getStatus().thenAccept(builder::setStatus)); add(getStatus().thenAccept(builder::setStatus));
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SYNC_POTION_EFFECTS)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.POTION_EFFECTS)) {
add(getPotionEffects().thenAccept(builder::setPotionEffects)); add(getPotionEffects().thenAccept(builder::setPotionEffects));
} }
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SYNC_ADVANCEMENTS)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.ADVANCEMENTS)) {
add(getAdvancements().thenAccept(builder::setAdvancements)); add(getAdvancements().thenAccept(builder::setAdvancements));
} }
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SYNC_STATISTICS)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.STATISTICS)) {
add(getStatistics().thenAccept(builder::setStatistics)); add(getStatistics().thenAccept(builder::setStatistics));
} }
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SYNC_LOCATION)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.LOCATION)) {
add(getLocation().thenAccept(builder::setLocation)); add(getLocation().thenAccept(builder::setLocation));
} }
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SYNC_PERSISTENT_DATA_CONTAINER)) { if (settings.getSynchronizationFeature(Settings.SynchronizationFeature.PERSISTENT_DATA_CONTAINER)) {
add(getPersistentDataContainer().thenAccept(builder::setPersistentDataContainer)); add(getPersistentDataContainer().thenAccept(builder::setPersistentDataContainer));
} }
} }

@ -1,7 +1,6 @@
package net.william278.husksync.redis; package net.william278.husksync.redis;
import net.william278.husksync.HuskSync; import net.william278.husksync.HuskSync;
import net.william278.husksync.config.Settings;
import net.william278.husksync.data.UserData; import net.william278.husksync.data.UserData;
import net.william278.husksync.player.User; import net.william278.husksync.player.User;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -33,13 +32,13 @@ public class RedisManager {
public RedisManager(@NotNull HuskSync plugin) { public RedisManager(@NotNull HuskSync plugin) {
this.plugin = plugin; this.plugin = plugin;
clusterId = plugin.getSettings().getStringValue(Settings.ConfigOption.CLUSTER_ID); clusterId = plugin.getSettings().clusterId;
// Set redis credentials // Set redis credentials
this.redisHost = plugin.getSettings().getStringValue(Settings.ConfigOption.REDIS_HOST); this.redisHost = plugin.getSettings().redisHost;
this.redisPort = plugin.getSettings().getIntegerValue(Settings.ConfigOption.REDIS_PORT); this.redisPort = plugin.getSettings().redisPort;
this.redisPassword = plugin.getSettings().getStringValue(Settings.ConfigOption.REDIS_PASSWORD); this.redisPassword = plugin.getSettings().redisPassword;
this.redisUseSsl = plugin.getSettings().getBooleanValue(Settings.ConfigOption.REDIS_USE_SSL); this.redisUseSsl = plugin.getSettings().redisUseSsl;
// Configure the jedis pool // Configure the jedis pool
this.jedisPoolConfig = new JedisPoolConfig(); this.jedisPoolConfig = new JedisPoolConfig();

@ -1,6 +1,7 @@
package net.william278.husksync.player; package net.william278.husksync.player;
import de.themoep.minedown.adventure.MineDown; import de.themoep.minedown.adventure.MineDown;
import net.william278.husksync.config.Settings;
import net.william278.husksync.data.*; import net.william278.husksync.data.*;
import net.william278.husksync.editor.ItemEditorMenu; import net.william278.husksync.editor.ItemEditorMenu;
import net.william278.desertwell.Version; import net.william278.desertwell.Version;
@ -31,7 +32,7 @@ public class DummyPlayer extends OnlineUser {
} }
@Override @Override
public CompletableFuture<Void> setStatus(@NotNull StatusData statusData, @NotNull List<StatusDataFlag> statusDataFlags) { public CompletableFuture<Void> setStatus(@NotNull StatusData statusData, @NotNull Settings settings) {
return CompletableFuture.runAsync(() -> { return CompletableFuture.runAsync(() -> {
// do nothing // do nothing
}); });

Loading…
Cancel
Save