9
0
mirror of https://github.com/WiIIiam278/HuskSync.git synced 2025-12-30 20:29:28 +00:00

Shrink built jar file size, work on MySQLPlayerDataBridge migrator

This commit is contained in:
William
2022-07-09 00:29:39 +01:00
parent f650db4438
commit 96c6a878c4
16 changed files with 436 additions and 62 deletions

View File

@@ -6,7 +6,9 @@ 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.william278.husksync.command.*;
import net.william278.husksync.command.BukkitCommand;
import net.william278.husksync.command.BukkitCommandType;
import net.william278.husksync.command.Permission;
import net.william278.husksync.config.Locales;
import net.william278.husksync.config.Settings;
import net.william278.husksync.data.CompressedDataAdapter;
@@ -19,6 +21,9 @@ import net.william278.husksync.event.BukkitEventCannon;
import net.william278.husksync.event.EventCannon;
import net.william278.husksync.listener.BukkitEventListener;
import net.william278.husksync.listener.EventListener;
import net.william278.husksync.migrator.LegacyMigrator;
import net.william278.husksync.migrator.Migrator;
import net.william278.husksync.migrator.MpdbMigrator;
import net.william278.husksync.player.BukkitPlayer;
import net.william278.husksync.player.OnlineUser;
import net.william278.husksync.redis.RedisManager;
@@ -27,6 +32,7 @@ import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@@ -40,24 +46,16 @@ import java.util.stream.Collectors;
public class BukkitHuskSync extends JavaPlugin implements HuskSync {
private Database database;
private RedisManager redisManager;
private Logger logger;
private ResourceReader resourceReader;
private EventListener eventListener;
private DataAdapter dataAdapter;
private DataEditor dataEditor;
private EventCannon eventCannon;
private Settings settings;
private Locales locales;
private List<Migrator> availableMigrators;
private static BukkitHuskSync instance;
/**
@@ -72,18 +70,6 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
@Override
public void onLoad() {
instance = this;
/*getLogger().log(Level.INFO, "Loading runtime libraries...");
final BukkitLibraryManager libraryManager = new BukkitLibraryManager(this);
final Library[] libraries = new Library[]{
Library.builder().groupId("redis{}clients")
.artifactId("jedis")
.version("4.2.3")
.id("jedis")
.build()
};
libraryManager.addMavenCentral();
Arrays.stream(libraries).forEach(libraryManager::loadLibrary);
getLogger().log(Level.INFO, "Successfully loaded runtime libraries.");*/
}
@Override
@@ -127,6 +113,17 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
dataEditor = new DataEditor(locales);
}
return succeeded;
}).thenApply(succeeded -> {
// Prepare migrators
if (succeeded) {
availableMigrators = new ArrayList<>();
availableMigrators.add(new LegacyMigrator(this));
final Plugin mySqlPlayerDataBridge = Bukkit.getPluginManager().getPlugin("MySqlPlayerDataBridge");
if (mySqlPlayerDataBridge != null) {
availableMigrators.add(new MpdbMigrator(this, mySqlPlayerDataBridge));
}
}
return succeeded;
}).thenApply(succeeded -> {
// Establish connection to the database
if (succeeded) {
@@ -254,6 +251,12 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
return eventCannon;
}
@NotNull
@Override
public List<Migrator> getAvailableMigrators() {
return null;
}
@Override
public @NotNull Settings getSettings() {
return settings;

View File

@@ -48,10 +48,10 @@ public class BukkitCommand implements CommandExecutor, TabExecutor {
if (sender instanceof Player player) {
this.command.onExecute(BukkitPlayer.adapt(player), args);
} else {
if (command instanceof ConsoleExecutable consoleExecutable) {
if (this.command instanceof ConsoleExecutable consoleExecutable) {
consoleExecutable.onConsoleExecute(args);
} else {
plugin.getLocales().getLocale("error_in_game_only").
plugin.getLocales().getLocale("error_in_game_command_only").
ifPresent(locale -> sender.spigot().sendMessage(locale.toComponent()));
}
}

View File

@@ -0,0 +1,243 @@
package net.william278.husksync.migrator;
import com.zaxxer.hikari.HikariDataSource;
import net.william278.husksync.BukkitHuskSync;
import net.william278.husksync.config.Settings;
import net.william278.husksync.data.*;
import net.william278.husksync.player.User;
import net.william278.mpdbconverter.MPDBConverter;
import org.bukkit.Bukkit;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import java.util.regex.Pattern;
public class MpdbMigrator extends Migrator {
private final MPDBConverter mpdbConverter;
private String sourceHost;
private int sourcePort;
private String sourceUsername;
private String sourcePassword;
private String sourceDatabase;
private String sourceInventoryTable;
private String sourceEnderChestTable;
private String sourceExperienceTable;
public MpdbMigrator(@NotNull BukkitHuskSync plugin, @NotNull Plugin mySqlPlayerDataBridge) {
super(plugin);
this.mpdbConverter = MPDBConverter.getInstance(mySqlPlayerDataBridge);
this.sourceHost = plugin.getSettings().getStringValue(Settings.ConfigOption.DATABASE_HOST);
this.sourcePort = plugin.getSettings().getIntegerValue(Settings.ConfigOption.DATABASE_PORT);
this.sourceUsername = plugin.getSettings().getStringValue(Settings.ConfigOption.DATABASE_USERNAME);
this.sourcePassword = plugin.getSettings().getStringValue(Settings.ConfigOption.DATABASE_PASSWORD);
this.sourceDatabase = plugin.getSettings().getStringValue(Settings.ConfigOption.DATABASE_NAME);
this.sourceInventoryTable = "mpdb_inventory";
this.sourceEnderChestTable = "mpdb_enderchest";
this.sourceExperienceTable = "mpdb_experience";
}
@Override
public CompletableFuture<Boolean> start() {
plugin.getLoggingAdapter().log(Level.INFO, "Starting migration from MySQLPlayerDataBridge to HuskSync...");
final long startTime = System.currentTimeMillis();
return CompletableFuture.supplyAsync(() -> {
// Create jdbc driver connection url
final String jdbcUrl = "jdbc:mysql://" + sourceHost + ":" + sourcePort + "/" + sourceDatabase;
// Create a new data source for the mpdb converter
try (final HikariDataSource connectionPool = new HikariDataSource()) {
plugin.getLoggingAdapter().log(Level.INFO, "Establishing connection to MySQLPlayerDataBridge database...");
connectionPool.setJdbcUrl(jdbcUrl);
connectionPool.setUsername(sourceUsername);
connectionPool.setPassword(sourcePassword);
connectionPool.setPoolName((getIdentifier() + "_migrator_pool").toUpperCase());
plugin.getLoggingAdapter().log(Level.INFO, "Downloading raw data from the MySQLPlayerDataBridge database...");
final List<MpdbData> dataToMigrate = new ArrayList<>();
try (final Connection connection = connectionPool.getConnection()) {
try (final PreparedStatement statement = connection.prepareStatement("""
SELECT `player_uuid`, `player_name`, `inventory`, `armor`, `enderchest`, `exp_lvl`, `exp`, `total_exp`
FROM `%source_inventory_table%`
INNER JOIN `%source_ender_chest_table%`
ON `%source_inventory_table%`.`player_uuid` = `%source_ender_chest_table%`.`player_uuid`
INNER JOIN `%source_experience_table%`
ON `%source_inventory_table%`.`player_uuid` = `%source_experience_table%`.`player_uuid`;
""".replaceAll(Pattern.quote("%source_inventory_table%"), sourceInventoryTable).replaceAll(Pattern.quote("%source_ender_chest_table%"), sourceEnderChestTable).replaceAll(Pattern.quote("%source_experience_table%"), sourceExperienceTable))) {
try (final ResultSet resultSet = statement.executeQuery()) {
int playersMigrated = 0;
while (resultSet.next()) {
dataToMigrate.add(new MpdbData(
new User(UUID.fromString(resultSet.getString("player_uuid")),
resultSet.getString("player_name")),
resultSet.getString("inventory"),
resultSet.getString("armor"),
resultSet.getString("enderchest"),
resultSet.getInt("exp_lvl"),
resultSet.getInt("exp"),
resultSet.getInt("total_exp")
));
playersMigrated++;
if (playersMigrated % 25 == 0) {
plugin.getLoggingAdapter().log(Level.INFO, "Downloaded MySQLPlayerDataBridge data for " + playersMigrated + " players...");
}
}
}
}
}
plugin.getLoggingAdapter().log(Level.INFO, "Completed download of " + dataToMigrate.size() + " entries from the MySQLPlayerDataBridge database!");
plugin.getLoggingAdapter().log(Level.INFO, "Converting raw MySQLPlayerDataBridge data to HuskSync user data...");
dataToMigrate.forEach(data -> data.toUserData(mpdbConverter).thenAccept(convertedData ->
plugin.getDatabase().ensureUser(data.user()).thenRun(() ->
plugin.getDatabase().setUserData(data.user(), convertedData, DataSaveCause.MPDB_MIGRATION))));
plugin.getLoggingAdapter().log(Level.INFO, "Migration complete for " + dataToMigrate.size() + " users in " + ((System.currentTimeMillis() - startTime) / 1000) + " seconds!");
return true;
} catch (Exception e) {
plugin.getLoggingAdapter().log(Level.SEVERE, "Error while migrating data: " + e.getMessage());
return false;
}
});
}
@Override
public void handleConfigurationCommand(@NotNull String[] args) {
if (args.length == 2) {
if (switch (args[0].toLowerCase()) {
case "host" -> {
this.sourceHost = args[1];
yield true;
}
case "port" -> {
try {
this.sourcePort = Integer.parseInt(args[1]);
yield true;
} catch (NumberFormatException e) {
yield false;
}
}
case "username" -> {
this.sourceUsername = args[1];
yield true;
}
case "password" -> {
this.sourcePassword = args[1];
yield true;
}
case "database" -> {
this.sourceDatabase = args[1];
yield true;
}
case "inventory_table" -> {
this.sourceInventoryTable = args[1];
yield true;
}
case "ender_chest_table" -> {
this.sourceEnderChestTable = args[1];
yield true;
}
case "experience_table" -> {
this.sourceExperienceTable = args[1];
yield true;
}
default -> false;
}) {
plugin.getLoggingAdapter().log(Level.INFO, getHelpMenu());
plugin.getLoggingAdapter().log(Level.INFO, "Successfully set " + args[0] + " to " + args[1]);
} else {
plugin.getLoggingAdapter().log(Level.INFO, "Invalid operation, could not set " + args[0] + " to " + args[1] + " (is it a valid option?)");
}
}
}
@NotNull
@Override
public String getIdentifier() {
return "mpdb";
}
@NotNull
@Override
public String getName() {
return "MySQLPlayerDataBridge";
}
@NotNull
@Override
public String getHelpMenu() {
return """
=== MySQLPlayerDataBridge Migration Wizard ==========
This will migrate inventories, ender chests and XP
from the MySQLPlayerDataBridge plugin to HuskSync.
To prevent excessive migration times, other non-vital
data will not be transferred.
STEP 1] Please ensure no players are on the server.
STEP 2] HuskSync will need to connect to the database
used to hold the source MySQLPlayerDataBridge data.
Please check these database parameters are OK:
- host: %source_host%
- port: %source_port%
- username: %source_username%
- password: %source_password%
- database: %source_database%
- inventory_table: %source_inventory_table%
- ender_chest_table: %source_ender_chest_table%
- experience_table: %source_xp_table%
If any of these are not correct, please correct them
using the command:
"husksync migrate mpdb set <parameter> <host>"
(e.g.: "husksync migrate mpdb set host 123.456.789")
STEP 3] HuskSync will migrate data into the database
tables configures in the config.yml file of this
server. Please make sure you're happy with this
before proceeding.
STEP 4] To start the migration, please run:
"husksync migrate mpdb start"
""";
}
private record MpdbData(@NotNull User user, @NotNull String serializedInventory,
@NotNull String serializedArmor, @NotNull String serializedEnderChest,
int expLevel, float expProgress, int totalExp) {
@NotNull
public CompletableFuture<UserData> toUserData(@NotNull MPDBConverter converter) {
return CompletableFuture.supplyAsync(() -> {
// Combine inventory and armour
final Inventory inventory = Bukkit.createInventory(null, InventoryType.PLAYER);
inventory.setContents(converter.getItemStackFromSerializedData(serializedInventory));
final ItemStack[] armor = converter.getItemStackFromSerializedData(serializedArmor).clone();
for (int i = 36; i < 36 + armor.length; i++) {
inventory.setItem(i, armor[i - 36]);
}
// Create user data record
return new UserData(
new StatusData(20, 20, 0, 20, 10,
1, 0, totalExp, expLevel, expProgress, "SURVIVAL",
false),
new ItemData(BukkitSerializer.serializeItemStackArray(inventory.getContents()).join()),
new ItemData(BukkitSerializer.serializeItemStackArray(converter
.getItemStackFromSerializedData(serializedEnderChest)).join()),
new PotionEffectData(""), new ArrayList<>(),
new StatisticsData(new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>()),
new LocationData("world", UUID.randomUUID(), "NORMAL", 0, 0, 0,
0f, 0f),
new PersistentDataContainerData(new HashMap<>()));
});
}
}
}