diff --git a/core/src/main/java/github/nighter/smartspawner/commands/hologram/SpawnerHologram.java b/core/src/main/java/github/nighter/smartspawner/commands/hologram/SpawnerHologram.java index 8f500893..7f6f0234 100644 --- a/core/src/main/java/github/nighter/smartspawner/commands/hologram/SpawnerHologram.java +++ b/core/src/main/java/github/nighter/smartspawner/commands/hologram/SpawnerHologram.java @@ -86,6 +86,8 @@ public void createHologram() { // Add custom name for identification td.setCustomName(uniqueIdentifier); td.setCustomNameVisible(false); + // Set persistent to false to prevent hologram from being saved and potentially getting stuck + td.setPersistent(false); }); textDisplay.set(display); @@ -115,6 +117,15 @@ public void updateText() { replacements.put("%max_exp%", languageManager.formatNumber(maxExp)); replacements.put("%used_slots%", languageManager.formatNumber(currentItems)); replacements.put("%max_slots%", languageManager.formatNumber(maxSlots)); + + // Calculate and add percentage placeholders + double percentStorageDecimal = maxSlots > 0 ? ((double) currentItems / maxSlots) * 100 : 0; + String formattedPercentStorage = String.format("%.1f", percentStorageDecimal); + replacements.put("%percentage_storage%", formattedPercentStorage); + + double percentExpDecimal = maxExp > 0 ? ((double) currentExp / maxExp) * 100 : 0; + String formattedPercentExp = String.format("%.1f", percentExpDecimal); + replacements.put("%percentage_exp%", formattedPercentExp); String hologramText = languageManager.getHologramText(); diff --git a/core/src/main/java/github/nighter/smartspawner/spawner/events/WorldEventHandler.java b/core/src/main/java/github/nighter/smartspawner/spawner/events/WorldEventHandler.java index b7fd7367..7a525a31 100644 --- a/core/src/main/java/github/nighter/smartspawner/spawner/events/WorldEventHandler.java +++ b/core/src/main/java/github/nighter/smartspawner/spawner/events/WorldEventHandler.java @@ -147,6 +147,9 @@ public void attemptInitialSpawnerLoad() { if (pendingCount > 0) { logger.info("Pending spawners will be loaded when their worlds become available."); } + + // Initialize chunk spawner limits after spawners are loaded + plugin.getChunkSpawnerLimiter().reloadConfig(); } /** @@ -180,6 +183,9 @@ private void loadPendingSpawnersForWorld(String worldName) { if (loadedCount > 0) { logger.info("Loaded " + loadedCount + " pending spawners for world: " + worldName); + + // Reinitialize chunk spawner limits after loading pending spawners + plugin.getChunkSpawnerLimiter().reloadConfig(); } } diff --git a/core/src/main/java/github/nighter/smartspawner/spawner/gui/main/SpawnerMenuFormUI.java b/core/src/main/java/github/nighter/smartspawner/spawner/gui/main/SpawnerMenuFormUI.java index 0c956490..028ec374 100644 --- a/core/src/main/java/github/nighter/smartspawner/spawner/gui/main/SpawnerMenuFormUI.java +++ b/core/src/main/java/github/nighter/smartspawner/spawner/gui/main/SpawnerMenuFormUI.java @@ -322,7 +322,7 @@ private Map createPlaceholders(SpawnerData spawner) { placeholders.put("current_items", String.valueOf(currentItems)); placeholders.put("max_items", languageManager.formatNumber(maxSlots)); - placeholders.put("formatted_storage", formattedPercentStorage); + placeholders.put("percentage_storage", formattedPercentStorage); // Experience information long currentExp = spawner.getSpawnerExp(); @@ -337,7 +337,7 @@ private Map createPlaceholders(SpawnerData spawner) { placeholders.put("max_exp", formattedMaxExp); placeholders.put("raw_current_exp", String.valueOf(currentExp)); placeholders.put("raw_max_exp", String.valueOf(maxExp)); - placeholders.put("formatted_exp", formattedPercentExp); + placeholders.put("percentage_exp", formattedPercentExp); // Total sell price information double totalSellPrice = spawner.getAccumulatedSellValue(); diff --git a/core/src/main/java/github/nighter/smartspawner/spawner/gui/main/SpawnerMenuUI.java b/core/src/main/java/github/nighter/smartspawner/spawner/gui/main/SpawnerMenuUI.java index 10b49bde..30082718 100644 --- a/core/src/main/java/github/nighter/smartspawner/spawner/gui/main/SpawnerMenuUI.java +++ b/core/src/main/java/github/nighter/smartspawner/spawner/gui/main/SpawnerMenuUI.java @@ -347,7 +347,7 @@ public ItemStack createSpawnerInfoItem(Player player, SpawnerData spawner) { // Storage information placeholders.put("current_items", String.valueOf(currentItems)); placeholders.put("max_items", languageManager.formatNumber(maxSlots)); - placeholders.put("formatted_storage", formattedPercentStorage); + placeholders.put("percentage_storage", formattedPercentStorage); // Experience information String formattedCurrentExp = languageManager.formatNumber(currentExp); @@ -357,7 +357,7 @@ public ItemStack createSpawnerInfoItem(Player player, SpawnerData spawner) { placeholders.put("max_exp", formattedMaxExp); placeholders.put("raw_current_exp", String.valueOf(currentExp)); placeholders.put("raw_max_exp", String.valueOf(maxExp)); - placeholders.put("formatted_exp", formattedPercentExp); + placeholders.put("percentage_exp", formattedPercentExp); // Total sell price information double totalSellPrice = spawner.getAccumulatedSellValue(); diff --git a/core/src/main/java/github/nighter/smartspawner/spawner/properties/SpawnerManager.java b/core/src/main/java/github/nighter/smartspawner/spawner/properties/SpawnerManager.java index ea88089b..a1f8c28a 100644 --- a/core/src/main/java/github/nighter/smartspawner/spawner/properties/SpawnerManager.java +++ b/core/src/main/java/github/nighter/smartspawner/spawner/properties/SpawnerManager.java @@ -244,11 +244,38 @@ public void reloadAllHolograms() { } public void cleanupAllSpawners() { + // First, remove all holograms synchronously before clearing data + removeAllHolograms(); + spawners.clear(); locationIndex.clear(); worldIndex.clear(); confirmedGhostSpawners.clear(); } + + public void removeAllHolograms() { + plugin.getLogger().info("Removing all spawner holograms..."); + int removed = 0; + + for (SpawnerData spawner : spawners.values()) { + try { + spawner.removeHologram(); + removed++; + } catch (Exception e) { + plugin.getLogger().warning("Error removing hologram for spawner " + + spawner.getSpawnerId() + ": " + e.getMessage()); + } + } + + // Give the scheduler time to process all removal tasks + try { + Thread.sleep(100); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + + plugin.getLogger().info("Removed " + removed + " spawner holograms"); + } public int getTotalSpawners() { return this.spawners.size(); diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 59ad80d8..cbf616cf 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -187,6 +187,8 @@ hologram: # %max_exp% - Maximum XP capacity # %used_slots% - Used inventory slots # %max_slots% - Total inventory slots + # %percentage_storage% - Storage usage as percentage (e.g., "75.5" for 75.5% full) + # %percentage_exp% - Experience storage as percentage (e.g., "50.0" for 50.0% full) text: - '[&#f8f8ff%stack_size%] b68ee%ᴇɴᴛɪᴛʏ% ꜱᴘᴀᴡɴᴇʀ' - '&#ab7afd• &#e6e6faxᴘ: %eb9a%current_exp%&#f8f8ff/%eb9a%max_exp%' diff --git a/core/src/main/resources/language/DonutSMP/gui.yml b/core/src/main/resources/language/DonutSMP/gui.yml index f8d772b2..77af3bf9 100644 --- a/core/src/main/resources/language/DonutSMP/gui.yml +++ b/core/src/main/resources/language/DonutSMP/gui.yml @@ -32,12 +32,12 @@ spawner_info_item: name: '&#FCE300%stack_size% %ᴇɴᴛɪᴛʏ% ꜱᴘᴀᴡɴᴇʀ' lore: - '&#FCE300● &fClick to sell items and collect xp' - - '&#FCE300Storage:&f %formatted_storage%% &#FCE300Filled.' - - '&#FCE300Exp:&f %formatted_exp%% &#FCE300Stored.' + - '&#FCE300Storage:&f %percentage_storage%% &#FCE300Filled.' + - '&#FCE300Exp:&f %percentage_exp%% &#FCE300Stored.' lore_no_shop: - '&#FCE300● &fClick to collect xp' - - '&#FCE300Storage:&f %formatted_storage%% &#FCE300Filled.' - - '&#FCE300Exp:&f %formatted_exp%% &#FCE300Stored.' + - '&#FCE300Storage:&f %percentage_storage%% &#FCE300Filled.' + - '&#FCE300Exp:&f %percentage_exp%% &#FCE300Stored.' lore_full: '' lore_inactive: '' @@ -350,10 +350,10 @@ bedrock: - '' - '§9◈ §fStorage:' - ' §7• Items: §9%current_items% §7/ §9%max_items%' - - ' §7• Storage: §9%formatted_storage%% §7full' + - ' §7• Storage: §9%percentage_storage%% §7full' - '' - '§9◈ §fExperience:' - ' §7• Current: §a%current_exp% §7/ §a%max_exp% §axp' - - ' §7• Stored: §a%formatted_exp%% §7xp' + - ' §7• Stored: §a%percentage_exp%% §7xp' - '' - '§a◈ §fSellable Value: §a+$%total_sell_price%' \ No newline at end of file diff --git a/core/src/main/resources/language/de_DE/gui.yml b/core/src/main/resources/language/de_DE/gui.yml index 9e404f35..8bd04093 100644 --- a/core/src/main/resources/language/de_DE/gui.yml +++ b/core/src/main/resources/language/de_DE/gui.yml @@ -80,7 +80,7 @@ spawner_storage_item: # %current_items% - Current number of items stored # %max_items% - Maximum storage capacity for items # %percent_storage% - Storage usage as integer percentage (e.g., "87") -# %formatted_storage% - Storage usage as formatted percentage with decimal (e.g., "87.5") +# %percentage_storage% - Storage usage as formatted percentage with decimal (e.g., "87.5") # # Experience Information: # %current_exp% - Current experience stored (formatted with commas) @@ -88,7 +88,7 @@ spawner_storage_item: # %raw_current_exp% - Raw current experience number # %raw_max_exp% - Raw maximum experience number # %percent_exp% - Experience storage as integer percentage -# %formatted_exp% - Experience storage as formatted percentage with decimal (e.g., "42.7") +# %percentage_exp% - Experience storage as formatted percentage with decimal (e.g., "42.7") spawner_info_item: name: 'ඪdb%ᴇɴᴛɪᴛʏ% ꜱᴘᴀᴡɴᴇʀ' lore: @@ -432,10 +432,10 @@ bedrock: - '' - '§9◈ §fLager:' - ' §7• Items: §9%current_items% §7/ §9%max_items%' - - ' §7• Lager: §9%formatted_storage%% §7voll' + - ' §7• Lager: §9%percentage_storage%% §7voll' - '' - '§9◈ §fErfahrung:' - ' §7• Aktuell: §a%current_exp% §7/ §a%max_exp% §aXP' - - ' §7• Gespeichert: §a%formatted_exp%% §7XP' + - ' §7• Gespeichert: §a%percentage_exp%% §7XP' - '' - '§a◈ §fVerkaufswert: §a+$%total_sell_price%' \ No newline at end of file diff --git a/core/src/main/resources/language/en_US/gui.yml b/core/src/main/resources/language/en_US/gui.yml index 8db0c21c..2bce39d1 100644 --- a/core/src/main/resources/language/en_US/gui.yml +++ b/core/src/main/resources/language/en_US/gui.yml @@ -80,7 +80,7 @@ spawner_storage_item: # %current_items% - Current number of items stored # %max_items% - Maximum storage capacity for items # %percent_storage% - Storage usage as integer percentage (e.g., "87") -# %formatted_storage% - Storage usage as formatted percentage with decimal (e.g., "87.5") +# %percentage_storage% - Storage usage as formatted percentage with decimal (e.g., "87.5") # # Experience Information: # %current_exp% - Current experience stored (formatted with commas) @@ -88,7 +88,7 @@ spawner_storage_item: # %raw_current_exp% - Raw current experience number # %raw_max_exp% - Raw maximum experience number # %percent_exp% - Experience storage as integer percentage -# %formatted_exp% - Experience storage as formatted percentage with decimal (e.g., "42.7") +# %percentage_exp% - Experience storage as formatted percentage with decimal (e.g., "42.7") spawner_info_item: name: 'ඪdb%ᴇɴᴛɪᴛʏ% ꜱᴘᴀᴡɴᴇʀ' lore: @@ -424,8 +424,8 @@ bedrock: # Entity: %entity%, %ᴇɴᴛɪᴛʏ%, %entity_type% # Stack: %stack_size% # Settings: %range%, %delay%, %delay_raw%, %min_mobs%, %max_mobs% - # Storage: %current_items%, %max_items%, %formatted_storage% - # Experience: %current_exp%, %max_exp%, %raw_current_exp%, %raw_max_exp%, %formatted_exp% + # Storage: %current_items%, %max_items%, %percentage_storage% + # Experience: %current_exp%, %max_exp%, %raw_current_exp%, %raw_max_exp%, %percentage_exp% # Sell Price: %total_sell_price% # # IMPORTANT: Only use Bedrock-compatible color codes: @@ -442,10 +442,10 @@ bedrock: - '' - '§9◈ §fStorage:' - ' §7• Items: §9%current_items% §7/ §9%max_items%' - - ' §7• Storage: §9%formatted_storage%% §7full' + - ' §7• Storage: §9%percentage_storage%% §7full' - '' - '§9◈ §fExperience:' - ' §7• Current: §a%current_exp% §7/ §a%max_exp% §axp' - - ' §7• Stored: §a%formatted_exp%% §7xp' + - ' §7• Stored: §a%percentage_exp%% §7xp' - '' - '§a◈ §fSellable Value: §a+$%total_sell_price%' \ No newline at end of file diff --git a/core/src/main/resources/language/vi_VN/gui.yml b/core/src/main/resources/language/vi_VN/gui.yml index 57eb7e2f..0a610a8e 100644 --- a/core/src/main/resources/language/vi_VN/gui.yml +++ b/core/src/main/resources/language/vi_VN/gui.yml @@ -401,10 +401,10 @@ bedrock: - '' - '§9◈ §fKho lưu trữ:' - ' §7• Vật phẩm: §9%current_items% §7/ §9%max_items%' - - ' §7• Kho: §9%formatted_storage%% §7đầy' + - ' §7• Kho: §9%percentage_storage%% §7đầy' - '' - '§9◈ §fKinh nghiệm:' - ' §7• Hiện tại: §a%current_exp% §7/ §a%max_exp% §aXP' - - ' §7• Đã lưu: §a%formatted_exp%% §7XP' + - ' §7• Đã lưu: §a%percentage_exp%% §7XP' - '' - '§a◈ §fGiá trị bán: §a+$%total_sell_price%'