diff --git a/core/src/main/java/github/nighter/smartspawner/extras/HopperHandler.java b/core/src/main/java/github/nighter/smartspawner/extras/HopperHandler.java index 9c99780d..0607f0ed 100644 --- a/core/src/main/java/github/nighter/smartspawner/extras/HopperHandler.java +++ b/core/src/main/java/github/nighter/smartspawner/extras/HopperHandler.java @@ -180,6 +180,30 @@ public void stopHopperTask(Location hopperLoc) { } } + /** + * Restart hopper task for a spawner location. + * This is called when spawner stack size changes to ensure hopper continues working. + * @param spawnerLoc The location of the spawner + */ + public void restartHopperForSpawner(Location spawnerLoc) { + if (!plugin.getConfig().getBoolean("hopper.enabled", false)) return; + + // Find hopper below the spawner + Block spawnerBlock = spawnerLoc.getBlock(); + if (spawnerBlock.getType() != Material.SPAWNER) return; + + Block hopperBlock = spawnerBlock.getRelative(BlockFace.DOWN); + if (hopperBlock.getType() != Material.HOPPER) return; + + Location hopperLoc = hopperBlock.getLocation(); + + // Stop existing hopper task if any + stopHopperTask(hopperLoc); + + // Start new hopper task + startHopperTask(hopperLoc, spawnerLoc); + } + private void transferItems(Location hopperLoc, Location spawnerLoc) { SpawnerData spawner = spawnerManager.getSpawnerByLocation(spawnerLoc); if (spawner == null) return; diff --git a/core/src/main/java/github/nighter/smartspawner/spawner/gui/main/SpawnerMenuAction.java b/core/src/main/java/github/nighter/smartspawner/spawner/gui/main/SpawnerMenuAction.java index 5d258eb9..f98800d1 100644 --- a/core/src/main/java/github/nighter/smartspawner/spawner/gui/main/SpawnerMenuAction.java +++ b/core/src/main/java/github/nighter/smartspawner/spawner/gui/main/SpawnerMenuAction.java @@ -10,7 +10,6 @@ import github.nighter.smartspawner.spawner.gui.synchronization.SpawnerGuiViewManager; import github.nighter.smartspawner.spawner.properties.SpawnerData; import github.nighter.smartspawner.spawner.sell.SpawnerSellManager; -import github.nighter.smartspawner.utils.DynamicMaterialDetector; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Particle; @@ -32,8 +31,18 @@ import java.util.concurrent.ConcurrentHashMap; public class SpawnerMenuAction implements Listener { - private static final Set SPAWNER_INFO_MATERIALS = - DynamicMaterialDetector.getSpawnerInfoMaterials(); + // Spawner info materials - manually defined to avoid Material.values() iteration + // which can trigger CraftLegacy initialization + private static final Set SPAWNER_INFO_MATERIALS = Set.of( + Material.PLAYER_HEAD, + Material.SPAWNER, + Material.ZOMBIE_HEAD, + Material.SKELETON_SKULL, + Material.WITHER_SKELETON_SKULL, + Material.CREEPER_HEAD, + Material.PIGLIN_HEAD, + Material.DRAGON_HEAD + ); private final SmartSpawner plugin; private final SpawnerMenuUI spawnerMenuUI; private final SpawnerStackerUI spawnerStackerUI; diff --git a/core/src/main/java/github/nighter/smartspawner/spawner/loot/EntityLootRegistry.java b/core/src/main/java/github/nighter/smartspawner/spawner/loot/EntityLootRegistry.java index 45d7f8b0..a4bd4f1e 100644 --- a/core/src/main/java/github/nighter/smartspawner/spawner/loot/EntityLootRegistry.java +++ b/core/src/main/java/github/nighter/smartspawner/spawner/loot/EntityLootRegistry.java @@ -54,6 +54,16 @@ public void loadConfigurations() { continue; } + // Validate entity type exists in current version + EntityType entityType; + try { + entityType = EntityType.valueOf(entityName.toUpperCase()); + } catch (IllegalArgumentException e) { + plugin.getLogger().warning("Entity type '" + entityName + "' is not available in server version " + + plugin.getServer().getBukkitVersion() + " - skipping"); + continue; + } + ConfigurationSection entitySection = lootConfig.getConfigurationSection(entityName); if (entitySection == null) continue; diff --git a/core/src/main/java/github/nighter/smartspawner/spawner/properties/SpawnerData.java b/core/src/main/java/github/nighter/smartspawner/spawner/properties/SpawnerData.java index fdf192fe..b206b5c1 100644 --- a/core/src/main/java/github/nighter/smartspawner/spawner/properties/SpawnerData.java +++ b/core/src/main/java/github/nighter/smartspawner/spawner/properties/SpawnerData.java @@ -243,6 +243,12 @@ private void updateStackSize(int newStackSize) { if (plugin.getSpawnerMenuFormUI() != null) { plugin.getSpawnerMenuFormUI().invalidateSpawnerCache(this.spawnerId); } + + // Restart hopper task if hopper integration is enabled + // This ensures hopper continues to work after stack size changes + if (plugin.getHopperHandler() != null) { + plugin.getHopperHandler().restartHopperForSpawner(this.spawnerLocation); + } } private void recreateVirtualInventory() { diff --git a/core/src/main/java/github/nighter/smartspawner/utils/DynamicMaterialDetector.java b/core/src/main/java/github/nighter/smartspawner/utils/DynamicMaterialDetector.java deleted file mode 100644 index b0b80d79..00000000 --- a/core/src/main/java/github/nighter/smartspawner/utils/DynamicMaterialDetector.java +++ /dev/null @@ -1,51 +0,0 @@ -package github.nighter.smartspawner.utils; - -import org.bukkit.Material; - -import java.util.Arrays; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Dynamically detects valid materials for spawner GUI based on current Minecraft version. - * Supports automatic detection of: - * - Player heads - * - Mob skulls/heads - * - Spawner blocks - */ -public class DynamicMaterialDetector { - private static final Set SPAWNER_INFO_MATERIALS; - - static { - // Auto-detect all head/skull materials from current version - SPAWNER_INFO_MATERIALS = Arrays.stream(Material.values()) - .filter(material -> { - String name = material.name(); - return name.equals("PLAYER_HEAD") || - name.equals("SPAWNER") || - name.endsWith("_HEAD") || - name.endsWith("_SKULL"); - }) - .filter(Material::isItem) - .collect(Collectors.toUnmodifiableSet()); - } - - /** - * Get all valid spawner info materials for the current Minecraft version - * - * @return Unmodifiable set of spawner info materials - */ - public static Set getSpawnerInfoMaterials() { - return SPAWNER_INFO_MATERIALS; - } - - /** - * Check if a material is a valid spawner info material - * - * @param material Material to check - * @return true if the material is a valid spawner info material - */ - public static boolean isValidSpawnerInfoMaterial(Material material) { - return SPAWNER_INFO_MATERIALS.contains(material); - } -}