mirror of
https://gitlab.com/phoenix-dvpmt/mmocore.git
synced 2025-11-18 06:24:17 +01:00
Player data load queues to avoid SQL bursting
This commit is contained in:
parent
e6dadf9dda
commit
fbaa6c68f9
@ -3,7 +3,6 @@ package net.Indyuce.mmocore;
|
|||||||
import io.lumine.mythic.lib.MythicLib;
|
import io.lumine.mythic.lib.MythicLib;
|
||||||
import io.lumine.mythic.lib.UtilityMethods;
|
import io.lumine.mythic.lib.UtilityMethods;
|
||||||
import io.lumine.mythic.lib.data.SynchronizedDataManager;
|
import io.lumine.mythic.lib.data.SynchronizedDataManager;
|
||||||
import io.lumine.mythic.lib.data.sql.SQLDataSource;
|
|
||||||
import io.lumine.mythic.lib.metrics.bukkit.Metrics;
|
import io.lumine.mythic.lib.metrics.bukkit.Metrics;
|
||||||
import io.lumine.mythic.lib.module.MMOPlugin;
|
import io.lumine.mythic.lib.module.MMOPlugin;
|
||||||
import io.lumine.mythic.lib.player.modifier.PlayerModifier;
|
import io.lumine.mythic.lib.player.modifier.PlayerModifier;
|
||||||
@ -12,8 +11,8 @@ import io.lumine.mythic.lib.version.SpigotPlugin;
|
|||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
import net.Indyuce.mmocore.api.player.attribute.AttributeModifier;
|
import net.Indyuce.mmocore.api.player.attribute.AttributeModifier;
|
||||||
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
|
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
|
||||||
import net.Indyuce.mmocore.command.builtin.mmocore.MMOCoreCommandTreeRoot;
|
|
||||||
import net.Indyuce.mmocore.command.ToggleableCommand;
|
import net.Indyuce.mmocore.command.ToggleableCommand;
|
||||||
|
import net.Indyuce.mmocore.command.builtin.mmocore.MMOCoreCommandTreeRoot;
|
||||||
import net.Indyuce.mmocore.comp.citizens.CitizenInteractEventListener;
|
import net.Indyuce.mmocore.comp.citizens.CitizenInteractEventListener;
|
||||||
import net.Indyuce.mmocore.comp.citizens.CitizensMMOLoader;
|
import net.Indyuce.mmocore.comp.citizens.CitizensMMOLoader;
|
||||||
import net.Indyuce.mmocore.comp.mythicmobs.MythicHook;
|
import net.Indyuce.mmocore.comp.mythicmobs.MythicHook;
|
||||||
@ -39,7 +38,8 @@ import net.Indyuce.mmocore.manager.data.DataProvider;
|
|||||||
import net.Indyuce.mmocore.manager.data.GuildDataManager;
|
import net.Indyuce.mmocore.manager.data.GuildDataManager;
|
||||||
import net.Indyuce.mmocore.manager.data.LegacyDataProvider;
|
import net.Indyuce.mmocore.manager.data.LegacyDataProvider;
|
||||||
import net.Indyuce.mmocore.manager.data.PlayerDataManager;
|
import net.Indyuce.mmocore.manager.data.PlayerDataManager;
|
||||||
import net.Indyuce.mmocore.manager.data.sql.SQLDataHandler;
|
import net.Indyuce.mmocore.manager.data.sql.SQLDatabaseImpl;
|
||||||
|
import net.Indyuce.mmocore.manager.data.yaml.YAMLDatabaseImpl;
|
||||||
import net.Indyuce.mmocore.manager.profession.*;
|
import net.Indyuce.mmocore.manager.profession.*;
|
||||||
import net.Indyuce.mmocore.manager.social.BoosterManager;
|
import net.Indyuce.mmocore.manager.social.BoosterManager;
|
||||||
import net.Indyuce.mmocore.manager.social.PartyManager;
|
import net.Indyuce.mmocore.manager.social.PartyManager;
|
||||||
@ -152,10 +152,7 @@ public class MMOCore extends MMOPlugin {
|
|||||||
getLogger().warning("(Your config version: '" + configVersion + "' | Expected config version: '" + defConfigVersion + "')");
|
getLogger().warning("(Your config version: '" + configVersion + "' | Expected config version: '" + defConfigVersion + "')");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getConfig().isConfigurationSection("mysql") && getConfig().getBoolean("mysql.enabled")) {
|
playerDataManager.setupDatabase(SQLDatabaseImpl::new, YAMLDatabaseImpl::new);
|
||||||
final SQLDataSource dataSource = new SQLDataSource(this);
|
|
||||||
playerDataManager.setDataHandler(new SQLDataHandler(dataSource));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getConfig().isConfigurationSection("default-playerdata"))
|
if (getConfig().isConfigurationSection("default-playerdata"))
|
||||||
playerDataManager.loadDefaultData(getConfig().getConfigurationSection("default-playerdata"));
|
playerDataManager.loadDefaultData(getConfig().getConfigurationSection("default-playerdata"));
|
||||||
|
|||||||
@ -3,10 +3,9 @@ package net.Indyuce.mmocore.command.builtin.mmocore.admin;
|
|||||||
import io.lumine.mythic.lib.command.CommandTreeExplorer;
|
import io.lumine.mythic.lib.command.CommandTreeExplorer;
|
||||||
import io.lumine.mythic.lib.command.CommandTreeNode;
|
import io.lumine.mythic.lib.command.CommandTreeNode;
|
||||||
import io.lumine.mythic.lib.data.DataExport;
|
import io.lumine.mythic.lib.data.DataExport;
|
||||||
import io.lumine.mythic.lib.data.sql.SQLDataSource;
|
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.manager.data.sql.SQLDataHandler;
|
import net.Indyuce.mmocore.manager.data.sql.SQLDatabaseImpl;
|
||||||
import net.Indyuce.mmocore.manager.data.yaml.YAMLPlayerDataHandler;
|
import net.Indyuce.mmocore.manager.data.yaml.YAMLDatabaseImpl;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -25,8 +24,8 @@ public class ExportDataTreeNode extends CommandTreeNode {
|
|||||||
|
|
||||||
// Export YAML to SQL
|
// Export YAML to SQL
|
||||||
final boolean result = new DataExport<>(MMOCore.plugin.playerDataManager, sender).start(
|
final boolean result = new DataExport<>(MMOCore.plugin.playerDataManager, sender).start(
|
||||||
() -> new YAMLPlayerDataHandler(MMOCore.plugin),
|
YAMLDatabaseImpl::new,
|
||||||
() -> new SQLDataHandler(new SQLDataSource(MMOCore.plugin)));
|
SQLDatabaseImpl::new);
|
||||||
|
|
||||||
return result ? CommandResult.SUCCESS : CommandResult.FAILURE;
|
return result ? CommandResult.SUCCESS : CommandResult.FAILURE;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ public class SaveDataTreeNode extends CommandTreeNode {
|
|||||||
return CommandResult.FAILURE;
|
return CommandResult.FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
MMOCore.plugin.playerDataManager.getDataHandler().saveData(PlayerData.get(player), SaveReason.AUTOSAVE);
|
MMOCore.plugin.playerDataManager.saveData(PlayerData.get(player), SaveReason.AUTOSAVE);
|
||||||
|
|
||||||
return CommandResult.SUCCESS;
|
return CommandResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import net.Indyuce.mmocore.MMOCore;
|
|||||||
import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
|
import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
import net.Indyuce.mmocore.comp.profile.MMOCoreProfileDataModule;
|
import net.Indyuce.mmocore.comp.profile.MMOCoreProfileDataModule;
|
||||||
import net.Indyuce.mmocore.manager.data.yaml.YAMLPlayerDataHandler;
|
|
||||||
import net.Indyuce.mmocore.player.DefaultPlayerData;
|
import net.Indyuce.mmocore.player.DefaultPlayerData;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -16,7 +15,7 @@ public class PlayerDataManager extends SynchronizedDataManager<PlayerData, Offli
|
|||||||
private DefaultPlayerData defaultData = DefaultPlayerData.DEFAULT;
|
private DefaultPlayerData defaultData = DefaultPlayerData.DEFAULT;
|
||||||
|
|
||||||
public PlayerDataManager(MMOCore plugin) {
|
public PlayerDataManager(MMOCore plugin) {
|
||||||
super(plugin, new YAMLPlayerDataHandler(plugin));
|
super(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
package net.Indyuce.mmocore.manager.data.sql;
|
package net.Indyuce.mmocore.manager.data.sql;
|
||||||
|
|
||||||
import io.lumine.mythic.lib.data.SaveReason;
|
import io.lumine.mythic.lib.data.SaveReason;
|
||||||
import io.lumine.mythic.lib.data.sql.SQLDataSource;
|
|
||||||
import io.lumine.mythic.lib.gson.JsonArray;
|
import io.lumine.mythic.lib.gson.JsonArray;
|
||||||
import io.lumine.mythic.lib.gson.JsonObject;
|
import io.lumine.mythic.lib.gson.JsonObject;
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
import net.Indyuce.mmocore.manager.data.yaml.YAMLPlayerDataHandler;
|
import net.Indyuce.mmocore.manager.data.yaml.YAMLDatabaseImpl;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@ -18,44 +17,27 @@ import java.util.logging.Level;
|
|||||||
|
|
||||||
public class PlayerDataTableUpdater {
|
public class PlayerDataTableUpdater {
|
||||||
private final PlayerData playerData;
|
private final PlayerData playerData;
|
||||||
private final SQLDataSource provider;
|
private final SQLDatabaseImpl provider;
|
||||||
private final UUID effectiveId;
|
private final UUID effectiveId;
|
||||||
private final Map<String, String> requestMap = new HashMap<>();
|
private final Map<String, String> requestMap = new HashMap<>();
|
||||||
|
|
||||||
public PlayerDataTableUpdater(SQLDataSource provider, PlayerData playerData) {
|
public PlayerDataTableUpdater(SQLDatabaseImpl provider, PlayerData playerData) {
|
||||||
this.playerData = playerData;
|
this.playerData = playerData;
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.effectiveId = playerData.getEffectiveId();
|
this.effectiveId = playerData.getEffectiveId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void executeRequest(@NotNull SaveReason saveReason) {
|
public void executeRequest(@NotNull SaveReason saveReason) {
|
||||||
final String request = "INSERT INTO " + SQLDataHandler.DATA_TABLE_NAME + "(" + SQLDataHandler.UUID_FIELD_NAME + ", " + formatCollection(requestMap.keySet(), false)
|
final String request = "INSERT INTO " + provider.getUserDataTableName() + "(" + SQLDatabaseImpl.UUID_FIELD_NAME + ", " + formatCollection(requestMap.keySet(), false)
|
||||||
+ ") VALUES('" + effectiveId + "'," + formatCollection(requestMap.values(), true) + ")" +
|
+ ") VALUES('" + effectiveId + "'," + formatCollection(requestMap.values(), true) + ")" +
|
||||||
" ON DUPLICATE KEY UPDATE " + formatMap() + ";";
|
" ON DUPLICATE KEY UPDATE " + formatMap() + ";";
|
||||||
|
|
||||||
try {
|
try (Connection connection = provider.getConnection()) {
|
||||||
final Connection connection = provider.getConnection();
|
final PreparedStatement statement = connection.prepareStatement(request);
|
||||||
try {
|
statement.executeUpdate();
|
||||||
final PreparedStatement statement = connection.prepareStatement(request);
|
|
||||||
try {
|
|
||||||
statement.executeUpdate();
|
|
||||||
} catch (SQLException exception) {
|
|
||||||
MMOCore.log(Level.WARNING, "Could not save player data of " + effectiveId + ", saving through YAML instead");
|
|
||||||
new YAMLPlayerDataHandler(MMOCore.plugin).saveData(playerData, saveReason);
|
|
||||||
exception.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
statement.close();
|
|
||||||
}
|
|
||||||
} catch (SQLException exception) {
|
|
||||||
MMOCore.log(Level.WARNING, "Could not save player data of " + effectiveId + ", saving through YAML instead");
|
|
||||||
new YAMLPlayerDataHandler(MMOCore.plugin).saveData(playerData, saveReason);
|
|
||||||
exception.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
} catch (SQLException exception) {
|
} catch (SQLException exception) {
|
||||||
MMOCore.log(Level.WARNING, "Could not save player data of " + effectiveId + ", saving through YAML instead");
|
MMOCore.log(Level.WARNING, "Could not save player data of " + effectiveId + ", saving through YAML instead");
|
||||||
new YAMLPlayerDataHandler(MMOCore.plugin).saveData(playerData, saveReason);
|
new YAMLDatabaseImpl().saveData(playerData, saveReason);
|
||||||
exception.printStackTrace();
|
exception.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,8 +4,7 @@ import io.lumine.mythic.lib.MythicLib;
|
|||||||
import io.lumine.mythic.lib.UtilityMethods;
|
import io.lumine.mythic.lib.UtilityMethods;
|
||||||
import io.lumine.mythic.lib.data.DataLoadResult;
|
import io.lumine.mythic.lib.data.DataLoadResult;
|
||||||
import io.lumine.mythic.lib.data.SaveReason;
|
import io.lumine.mythic.lib.data.SaveReason;
|
||||||
import io.lumine.mythic.lib.data.sql.SQLDataSource;
|
import io.lumine.mythic.lib.data.sql.SQLDatabase;
|
||||||
import io.lumine.mythic.lib.data.sql.SQLSynchronizedDataHandler;
|
|
||||||
import io.lumine.mythic.lib.gson.JsonArray;
|
import io.lumine.mythic.lib.gson.JsonArray;
|
||||||
import io.lumine.mythic.lib.gson.JsonElement;
|
import io.lumine.mythic.lib.gson.JsonElement;
|
||||||
import io.lumine.mythic.lib.gson.JsonObject;
|
import io.lumine.mythic.lib.gson.JsonObject;
|
||||||
@ -33,12 +32,11 @@ import java.util.UUID;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class SQLDataHandler extends SQLSynchronizedDataHandler<PlayerData, OfflinePlayerData> {
|
public class SQLDatabaseImpl extends SQLDatabase<PlayerData, OfflinePlayerData> {
|
||||||
public static final String DATA_TABLE_NAME = "mmocore_playerdata";
|
|
||||||
public static final String UUID_FIELD_NAME = "uuid";
|
public static final String UUID_FIELD_NAME = "uuid";
|
||||||
|
|
||||||
public SQLDataHandler(SQLDataSource dataSource) {
|
public SQLDatabaseImpl() {
|
||||||
super(dataSource, DATA_TABLE_NAME, UUID_FIELD_NAME);
|
super(MMOCore.plugin, UUID_FIELD_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String[] NEW_COLUMNS = new String[]{
|
private static final String[] NEW_COLUMNS = new String[]{
|
||||||
@ -58,7 +56,7 @@ public class SQLDataHandler extends SQLSynchronizedDataHandler<PlayerData, Offli
|
|||||||
public void setup() {
|
public void setup() {
|
||||||
|
|
||||||
// Fully create table
|
// Fully create table
|
||||||
getDataSource().executeUpdateAsync("CREATE TABLE IF NOT EXISTS " + DATA_TABLE_NAME + "("
|
executeUpdate("CREATE TABLE IF NOT EXISTS " + userdataTableName + "("
|
||||||
+ UUID_FIELD_NAME + " VARCHAR(36)," +
|
+ UUID_FIELD_NAME + " VARCHAR(36)," +
|
||||||
"class_points INT(11) DEFAULT 0," +
|
"class_points INT(11) DEFAULT 0," +
|
||||||
"skill_points INT(11) DEFAULT 0," +
|
"skill_points INT(11) DEFAULT 0," +
|
||||||
@ -92,21 +90,16 @@ public class SQLDataHandler extends SQLSynchronizedDataHandler<PlayerData, Offli
|
|||||||
|
|
||||||
// Add columns that might not be here by default
|
// Add columns that might not be here by default
|
||||||
for (int i = 0; i < NEW_COLUMNS.length; i += 2) {
|
for (int i = 0; i < NEW_COLUMNS.length; i += 2) {
|
||||||
final String columnName = NEW_COLUMNS[i];
|
final var columnName = NEW_COLUMNS[i];
|
||||||
final String dataType = NEW_COLUMNS[i + 1];
|
final var dataType = NEW_COLUMNS[i + 1];
|
||||||
// TODO prepare
|
executeQuery("SELECT * FROM `information_schema`.`COLUMNS` WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND COLUMN_NAME = ?", result -> {
|
||||||
getDataSource().getResultAsync("SELECT * FROM information_schema.COLUMNS WHERE TABLE_NAME = '" + DATA_TABLE_NAME + "' AND COLUMN_NAME = '" + columnName + "'", result -> {
|
if (!result.next())
|
||||||
try {
|
executeUpdate("ALTER TABLE " + userdataTableName + " ADD COLUMN " + columnName + " " + dataType);
|
||||||
if (!result.next())
|
}, databaseName, userdataTableName, columnName);
|
||||||
getDataSource().executeUpdate("ALTER TABLE " + DATA_TABLE_NAME + " ADD COLUMN " + columnName + " " + dataType);
|
|
||||||
} catch (SQLException exception) {
|
|
||||||
exception.printStackTrace();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modify exp to be a double precision instead
|
// Modify exp to be a double precision instead
|
||||||
getDataSource().executeUpdateAsync("ALTER TABLE " + DATA_TABLE_NAME + " MODIFY COLUMN experience DOUBLE PRECISION");
|
executeUpdate("ALTER TABLE `" + userdataTableName + "` MODIFY COLUMN experience DOUBLE PRECISION");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -207,7 +200,7 @@ public class SQLDataHandler extends SQLSynchronizedDataHandler<PlayerData, Offli
|
|||||||
final UUID effectiveId = data.getEffectiveId();
|
final UUID effectiveId = data.getEffectiveId();
|
||||||
UtilityMethods.debug(MMOCore.plugin, "SQL", "Saving data for: '" + effectiveId + "'...");
|
UtilityMethods.debug(MMOCore.plugin, "SQL", "Saving data for: '" + effectiveId + "'...");
|
||||||
|
|
||||||
final PlayerDataTableUpdater updater = new PlayerDataTableUpdater(getDataSource(), data);
|
final PlayerDataTableUpdater updater = new PlayerDataTableUpdater(this, data);
|
||||||
updater.addData("class_points", data.getClassPoints());
|
updater.addData("class_points", data.getClassPoints());
|
||||||
updater.addData("skill_points", data.getSkillPoints());
|
updater.addData("skill_points", data.getSkillPoints());
|
||||||
updater.addData("skill_reallocation_points", data.getSkillReallocationPoints());
|
updater.addData("skill_reallocation_points", data.getSkillReallocationPoints());
|
||||||
@ -1,8 +1,7 @@
|
|||||||
package net.Indyuce.mmocore.manager.data.yaml;
|
package net.Indyuce.mmocore.manager.data.yaml;
|
||||||
|
|
||||||
import io.lumine.mythic.lib.data.DataLoadResult;
|
import io.lumine.mythic.lib.data.DataLoadResult;
|
||||||
import io.lumine.mythic.lib.data.yaml.YAMLSynchronizedDataHandler;
|
import io.lumine.mythic.lib.data.yaml.YAMLFlatDatabase;
|
||||||
import io.lumine.mythic.lib.module.MMOPlugin;
|
|
||||||
import io.lumine.mythic.lib.util.lang3.Validate;
|
import io.lumine.mythic.lib.util.lang3.Validate;
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
|
import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
|
||||||
@ -22,9 +21,9 @@ import java.util.UUID;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class YAMLPlayerDataHandler extends YAMLSynchronizedDataHandler<PlayerData, OfflinePlayerData> {
|
public class YAMLDatabaseImpl extends YAMLFlatDatabase<PlayerData, OfflinePlayerData> {
|
||||||
public YAMLPlayerDataHandler(MMOPlugin owning) {
|
public YAMLDatabaseImpl() {
|
||||||
super(owning);
|
super(MMOCore.plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -26,6 +26,8 @@ mysql:
|
|||||||
prepStmtCacheSize: 250
|
prepStmtCacheSize: 250
|
||||||
prepStmtCacheSqlLimit: 2048
|
prepStmtCacheSqlLimit: 2048
|
||||||
|
|
||||||
|
userdata-table-name: 'mmocore_playerdata'
|
||||||
|
|
||||||
# The default values for all playerdata
|
# The default values for all playerdata
|
||||||
# All new players will start with these values
|
# All new players will start with these values
|
||||||
default-playerdata:
|
default-playerdata:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user