From b3ca94a9d36d5db37f47f9dbbc08351e222eb418 Mon Sep 17 00:00:00 2001 From: AlexSlurp Date: Wed, 30 Jul 2025 18:07:55 -0400 Subject: [PATCH] Statistic sync fixes for review --- .../hd/sphinx/sync/listener/JoinListener.java | 96 ++++++++++++------- .../hd/sphinx/sync/mysql/ManageMySQLData.java | 5 +- .../sphinx/sync/util/StatisticsManager.java | 73 +++++++++++--- 3 files changed, 128 insertions(+), 46 deletions(-) diff --git a/src/main/java/hd/sphinx/sync/listener/JoinListener.java b/src/main/java/hd/sphinx/sync/listener/JoinListener.java index 1ed03ad..bd3f04e 100644 --- a/src/main/java/hd/sphinx/sync/listener/JoinListener.java +++ b/src/main/java/hd/sphinx/sync/listener/JoinListener.java @@ -16,63 +16,95 @@ import org.bukkit.event.player.PlayerPickupItemEvent; import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; public class JoinListener implements Listener { + // Tracks players who are still loading + private static final Set loadingPlayers = new HashSet<>(); + @EventHandler public void onJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); - if (ConfigManager.getBoolean("settings.onlySyncPermission") && !player.hasPermission("sync.sync")) return; - MainManageData.loadedPlayerData.add(player); - MainManageData.commandHashMap.put(player, new ArrayList()); - if (DeathListener.deadPlayers.contains(player)) { - DeathListener.deadPlayers.remove(player); + + // Permission check + if (ConfigManager.getBoolean("settings.onlySyncPermission") && !player.hasPermission("sync.sync")) { + return; } + + // Prepare data structures for this player + MainManageData.commandHashMap.put(player, new ArrayList<>()); + + // Reset death state + DeathListener.deadPlayers.remove(player); + + // Mark the player as loading + loadingPlayers.add(player); + + // If new player if (!MainManageData.isPlayerKnown(player)) { - if (ConfigManager.getBoolean("settings.sending.generated")) { - player.sendMessage(ConfigManager.getColoredString("messages.generated")); + String generatedMessage = ConfigManager.getColoredString("messages.generated"); + if (!generatedMessage.trim().isEmpty()) { + player.sendMessage(generatedMessage); } + MainManageData.generatePlayer(player); - Bukkit.getPluginManager().callEvent(new GeneratingPlayerProfileEvent(player, ConfigManager.getBoolean("settings.usingOldData"))); + Bukkit.getPluginManager().callEvent( + new GeneratingPlayerProfileEvent(player, ConfigManager.getBoolean("settings.usingOldData")) + ); + if (!ConfigManager.getBoolean("settings.usingOldData")) { - if (ConfigManager.getBoolean("settings.syncing.enderchest")) { - player.getEnderChest().clear(); - } - if (ConfigManager.getBoolean("settings.syncing.inventory")) { - player.getInventory().clear(); - } - if (ConfigManager.getBoolean("settings.syncing.exp")) { - player.setLevel(0); - } + if (ConfigManager.getBoolean("settings.syncing.enderchest")) player.getEnderChest().clear(); + if (ConfigManager.getBoolean("settings.syncing.inventory")) player.getInventory().clear(); + if (ConfigManager.getBoolean("settings.syncing.exp")) player.setLevel(0); } - return; } else { - if (ConfigManager.getBoolean("settings.syncing.enderchest")) { - player.getEnderChest().clear(); - } - if (ConfigManager.getBoolean("settings.syncing.inventory")) { - player.getInventory().clear(); - } - if (ConfigManager.getBoolean("settings.syncing.exp")) { - player.setLevel(0); - } + // Known player: clear inventories if needed + if (ConfigManager.getBoolean("settings.syncing.enderchest")) player.getEnderChest().clear(); + if (ConfigManager.getBoolean("settings.syncing.inventory")) player.getInventory().clear(); + if (ConfigManager.getBoolean("settings.syncing.exp")) player.setLevel(0); } + + // Send loading message if (ConfigManager.getBoolean("settings.sending.loading")) { - player.sendMessage(ConfigManager.getColoredString("messages.loading")); + String generatedMessage = ConfigManager.getColoredString("messages.loading"); + if (!generatedMessage.trim().isEmpty()) { + player.sendMessage(generatedMessage); + } } + + // Trigger loading event Bukkit.getPluginManager().callEvent(new ProcessingLoadingPlayerDataEvent(player, new SyncSettings())); + + // Schedule async join data loading Main.schedulerManager.getScheduler().scheduleJoin(player); + + // When scheduleJoin completes loading, call this: + Bukkit.getScheduler().runTaskLater(Main.getPlugin(Main.class), () -> { + // Player is fully loaded + MainManageData.loadedPlayerData.add(player); + loadingPlayers.remove(player); + }, 40L); // ~2 seconds delay (adjust based on your loading time) } @EventHandler public void onPickup(PlayerPickupItemEvent event) { - if (MainManageData.loadedPlayerData.contains(event.getPlayer())) event.setCancelled(true); - if (DeathListener.deadPlayers.contains(event.getPlayer())) event.setCancelled(true); + Player player = event.getPlayer(); + // Cancel only if player is still loading or dead + if (loadingPlayers.contains(player) || DeathListener.deadPlayers.contains(player)) { + event.setCancelled(true); + } } @EventHandler public void onInteract(PlayerInteractEvent event) { - if (!MainManageData.loadedPlayerData.contains(event.getPlayer())) return; - if (event.getClickedBlock() != null && event.getClickedBlock().getType() != Material.AIR) event.setCancelled(true); + Player player = event.getPlayer(); + // Cancel if still loading or dead + if (loadingPlayers.contains(player) || DeathListener.deadPlayers.contains(player)) { + if (event.getClickedBlock() != null && event.getClickedBlock().getType() != Material.AIR) { + event.setCancelled(true); + } + } } } diff --git a/src/main/java/hd/sphinx/sync/mysql/ManageMySQLData.java b/src/main/java/hd/sphinx/sync/mysql/ManageMySQLData.java index 7768470..a38803e 100644 --- a/src/main/java/hd/sphinx/sync/mysql/ManageMySQLData.java +++ b/src/main/java/hd/sphinx/sync/mysql/ManageMySQLData.java @@ -144,7 +144,10 @@ public static void loadPlayer(Player player) { syncProfile.setRawStatistics(StatisticsManager.loadPlayerStatistics(player, result)); } } catch (Exception ignored) { } - player.sendMessage(ConfigManager.getColoredString("messages.loaded")); + String generatedMessage = ConfigManager.getColoredString("messages.loaded"); + if (!generatedMessage.trim().isEmpty()) { + player.sendMessage(generatedMessage); + } } Main.schedulerManager.getScheduler().scheduleExecuteCommands(player); Main.schedulerManager.getScheduler().scheduleCompleteLoadEvent(player, syncProfile); diff --git a/src/main/java/hd/sphinx/sync/util/StatisticsManager.java b/src/main/java/hd/sphinx/sync/util/StatisticsManager.java index d640a8e..e3c42a1 100644 --- a/src/main/java/hd/sphinx/sync/util/StatisticsManager.java +++ b/src/main/java/hd/sphinx/sync/util/StatisticsManager.java @@ -33,14 +33,25 @@ public static HashMap getStatisticsMap(Player player) { String drop = Statistic.DROP.toString(); String pickup = Statistic.PICKUP.toString(); for (Material material : Material.values()) { + // MINE_BLOCK only for blocks if (material.isBlock()) { - returnHashMap.put(material.toString() + "==/=" + mineBlock, player.getStatistic(Statistic.MINE_BLOCK, material)); + try { + returnHashMap.put(material + "==/=" + mineBlock, player.getStatistic(Statistic.MINE_BLOCK, material)); + } catch (IllegalArgumentException ignored) {} + } + + // The following stats must only be called for items + if (!material.isItem()) continue; + + try { + returnHashMap.put(material + "==/=" + useItem, player.getStatistic(Statistic.USE_ITEM, material)); + returnHashMap.put(material + "==/=" + breakItem, player.getStatistic(Statistic.BREAK_ITEM, material)); + returnHashMap.put(material + "==/=" + craftItem, player.getStatistic(Statistic.CRAFT_ITEM, material)); + returnHashMap.put(material + "==/=" + drop, player.getStatistic(Statistic.DROP, material)); + returnHashMap.put(material + "==/=" + pickup, player.getStatistic(Statistic.PICKUP, material)); + } catch (IllegalArgumentException ignored) { + // Skip invalid materials } - returnHashMap.put(material.toString() + "==/=" + useItem, player.getStatistic(Statistic.USE_ITEM, material)); - returnHashMap.put(material.toString() + "==/=" + breakItem, player.getStatistic(Statistic.BREAK_ITEM, material)); - returnHashMap.put(material.toString() + "==/=" + craftItem, player.getStatistic(Statistic.CRAFT_ITEM, material)); - returnHashMap.put(material.toString() + "==/=" + drop, player.getStatistic(Statistic.DROP, material)); - returnHashMap.put(material.toString() + "==/=" + pickup, player.getStatistic(Statistic.PICKUP, material)); } String killEntity = Statistic.KILL_ENTITY.toString(); @@ -66,16 +77,52 @@ public static HashMap loadPlayerStatistics(Player player, Strin } for (String statistic : statistics.keySet()) { - if (statistic.contains("==/=") && statistic.contains("entity")) { - String[] statisticArray = statistic.split("==/="); - player.setStatistic(Statistic.valueOf(statisticArray[1]), EntityType.valueOf(statisticArray[0]), statistics.get(statistic)); - } else if (statistic.contains("==/=")) { + int value = statistics.get(statistic); + + if (statistic.contains("==/=")) { String[] statisticArray = statistic.split("==/="); - player.setStatistic(Statistic.valueOf(statisticArray[1]), Material.valueOf(statisticArray[0]), statistics.get(statistic)); + String key = statisticArray[0]; + String statName = statisticArray[1]; + + try { + Statistic stat = Statistic.valueOf(statName); + + if (isEntityStatistic(stat)) { + // Handle Entity statistics + try { + EntityType entityType = EntityType.valueOf(key); + player.setStatistic(stat, entityType, value); + } catch (IllegalArgumentException ignored) { } + } else { + // Handle Material statistics + try { + Material material = Material.valueOf(key); + // Only set item stats for real items + if (requiresItemStatistic(stat) && !material.isItem()) continue; + player.setStatistic(stat, material, value); + } catch (IllegalArgumentException ignored) { } + } + } catch (IllegalArgumentException ignored) { } } else { - player.setStatistic(Statistic.valueOf(statistic), statistics.get(statistic)); + // Handle simple statistics + try { + player.setStatistic(Statistic.valueOf(statistic), value); + } catch (IllegalArgumentException ignored) { } } } + return statistics; } -} + + private static boolean isEntityStatistic(Statistic stat) { + return stat == Statistic.KILL_ENTITY || stat == Statistic.ENTITY_KILLED_BY; + } + + private static boolean requiresItemStatistic(Statistic stat) { + return stat == Statistic.USE_ITEM || + stat == Statistic.BREAK_ITEM || + stat == Statistic.CRAFT_ITEM || + stat == Statistic.DROP || + stat == Statistic.PICKUP; + } +} \ No newline at end of file