Open chocolatecraft opened 3 years ago
Can you make autosaving without save fake user account until load data ?
I found api. Its has only save all players its not save per player.
If its has save per player . I will use repeat async auto save after player join server Playerjoinevent
Can you recode it?
I found api. Its has only save all players its not save per player.
I think its has save single player every time they join, i found these in source code, in MainListener at package com.sucy.skill.listener:
/**
* Saves player data when they log out and stops passives
*
* @param event event details
*/
@EventHandler(priority = EventPriority.MONITOR)
public void onQuit(PlayerQuitEvent event)
{
unload(event.getPlayer());
}
/**
* Unloads a player's data from the server
*
* @param player player to unload
*/
public static void unload(Player player)
{
if (CitizensHook.isNPC(player))
return;
boolean skipSaving = false;
if (loadingPlayers.containsKey(player.getUniqueId())) {
loadingPlayers.remove(player.getUniqueId()).cancel();
skipSaving = true;
}
PlayerData data = SkillAPI.getPlayerData(player);
if (SkillAPI.getSettings().isWorldEnabled(player.getWorld()))
{
data.record(player);
data.stopPassives(player);
}
FlagManager.clearFlags(player);
BuffManager.clearData(player);
Combat.clearData(player);
DynamicSkill.clearCastData(player);
player.setDisplayName(player.getName());
if (VersionManager.isVersionAtLeast(VersionManager.V1_9_0)) {
player.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(20);
} else {
player.setMaxHealth(20);
}
player.setWalkSpeed(0.2f);
SkillAPI.unloadPlayerData(player, skipSaving);
}
skipSaving should be false if this player is not loading data, so go to SkillAPI.unloadPlayerData(OfflinePlayer, boolean) in com.sucy.skill:
/**
* Unloads player data from memory, saving it to the config
* first and then removing it from the map.
*
* @param player player to unload data for
*/
public static void unloadPlayerData(final OfflinePlayer player) {
unloadPlayerData(player, false);
}
public static void unloadPlayerData(final OfflinePlayer player, final boolean skipSaving) {
if (singleton == null || player == null || singleton.disabling || !singleton.players.containsKey(new VersionPlayer(player).getIdString())) {
return;
}
singleton.getServer().getScheduler().runTaskAsynchronously(singleton, () -> {
PlayerAccounts accounts = getPlayerAccountData(player);
if (!skipSaving) {
singleton.io.saveData(accounts);
}
singleton.players.remove(new VersionPlayer(player).getIdString());
});
}
singleton is instance of SkillApi class, and io feild is instance of abstract class IOManager in com.sucy.skill.data.io, saveData(OfflinePlayer) is a abstract method, and i think if we use mysql then the IOManager will be SQLIO class's instance in com.sucy.skill.data.io, see saveData(OfflinePlayer) in SQLIO:
@Override
public void saveData(PlayerAccounts data)
{
SQLConnection connection = openConnection();
saveSingle(connection, data);
connection.database.closeConnection();
}
every thing seems normal, i can't find the key of the problem, same with when player join:
/**
* Starts passives and applies class data when a player logs in.
*/
@EventHandler
public void onJoin(final PlayerJoinEvent event) {
final Player player = event.getPlayer();
if (player.hasMetadata("NPC") || !SkillAPI.getSettings().isWorldEnabled(player.getWorld()))
return;
final int delay = SkillAPI.getSettings().getSqlDelay();
if (SkillAPI.getSettings().isUseSql() && delay > 0) {
final BukkitTask task = SkillAPI.schedule(() -> {
try {
SkillAPI.reloadPlayerData(player);
init(player);
} finally {
loadingPlayers.remove(event.getPlayer().getUniqueId());
}
}, delay);
loadingPlayers.put(event.getPlayer().getUniqueId(), task);
} else {
init(player);
}
}
and in SkillAPI.reloadPlayerData(OfflinePlayer) method:
/**
* Do not use this method outside of onJoin. This will delete any progress a player
* has made since joining.
*/
public static void reloadPlayerData(final Player player) {
doLoad(player);
}
see doLoad(OfflinePlayer):
private static PlayerAccounts doLoad(OfflinePlayer player) {
// Load the data
PlayerAccounts data = singleton.io.loadData(player);
singleton.players.put(player.getUniqueId().toString(), data);
return data;
}
see loadData(OfflinePlayer) in SQLIO:
@Override
public PlayerAccounts loadData(OfflinePlayer player)
{
if (player == null) return null;
SQLConnection connection = openConnection();
PlayerAccounts result = load(connection, player);
connection.database.closeConnection();
return result;
}
Its normally for auto save when quit. But auto save period in config its save all player data. I got bug if enabled it some player join while auto save runing. They lost data (if I disable period auto save its worked but when server crash or closed server some player level rollback)
I'am not sure about this I dont have java skill. What method or api can I use with playerjoinevent for repeat async auto save single player? Reference sucy.skill.task savetask.java
I read this whole thread and still can't understand what the issue is due to the broken english :P
Auto saving mysql lost data.
When I enabled this function some player got lost all data.
I find many time for check this problem. I got know it right now.
When I enabled config delay load data for sync multi server. its will lost data from auto save. I set delay "100" From config 100 = 5 sec Example.
When I join to server and then config will check delay for load sync data from mysql. And While delay loading... skillapi saving In the moment. it causing data loss.
if skillapi autosave when player join in 5 sec that player still lost data. Saving will save fake user account.