diff --git a/pom.xml b/pom.xml index 41723d4..6a74a3a 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ com.songoda UltimateStacker 4.0.0 - 2.1.5 + 2.1.6 clean install UltimateStacker-${project.version} @@ -118,7 +118,7 @@ com.songoda SongodaCore - LATEST + 2.4.55 compile diff --git a/src/main/java/com/songoda/ultimatestacker/UltimateStacker.java b/src/main/java/com/songoda/ultimatestacker/UltimateStacker.java index d3e9785..5756dd8 100644 --- a/src/main/java/com/songoda/ultimatestacker/UltimateStacker.java +++ b/src/main/java/com/songoda/ultimatestacker/UltimateStacker.java @@ -11,6 +11,7 @@ import com.songoda.core.database.DatabaseConnector; import com.songoda.core.database.MySQLConnector; import com.songoda.core.database.SQLiteConnector; import com.songoda.core.gui.GuiManager; +import com.songoda.core.hooks.EntityStackerManager; import com.songoda.core.hooks.HologramManager; import com.songoda.core.hooks.WorldGuardHook; import com.songoda.core.utils.TextUtils; @@ -25,6 +26,7 @@ import com.songoda.ultimatestacker.database.DataManager; import com.songoda.ultimatestacker.database.migrations._1_InitialMigration; import com.songoda.ultimatestacker.database.migrations._2_EntityStacks; import com.songoda.ultimatestacker.database.migrations._3_BlockStacks; +import com.songoda.ultimatestacker.database.migrations._4_DataPurge; import com.songoda.ultimatestacker.hook.StackerHook; import com.songoda.ultimatestacker.hook.hooks.JobsHook; import com.songoda.ultimatestacker.listeners.*; @@ -196,6 +198,7 @@ public class UltimateStacker extends SongodaPlugin { stackerHooks.add(new JobsHook()); HologramManager.load(this); + EntityStackerManager.load(); // Database stuff, go! try { @@ -222,7 +225,8 @@ public class UltimateStacker extends SongodaPlugin { this.dataMigrationManager = new DataMigrationManager(this.databaseConnector, this.dataManager, new _1_InitialMigration(), new _2_EntityStacks(), - new _3_BlockStacks()); + new _3_BlockStacks(), + new _4_DataPurge()); this.dataMigrationManager.runMigrations(); } diff --git a/src/main/java/com/songoda/ultimatestacker/commands/CommandRemoveAll.java b/src/main/java/com/songoda/ultimatestacker/commands/CommandRemoveAll.java index bea99df..01d36c8 100644 --- a/src/main/java/com/songoda/ultimatestacker/commands/CommandRemoveAll.java +++ b/src/main/java/com/songoda/ultimatestacker/commands/CommandRemoveAll.java @@ -46,8 +46,10 @@ public class CommandRemoveAll extends AbstractCommand { for (Entity entityO : world.getEntities()) { if (entityO instanceof Player) continue; - if (entityO instanceof LivingEntity && (stackManager.isStackedAndLoaded((LivingEntity)entityO) || all) && type.equalsIgnoreCase("entities")) { + if (entityO instanceof LivingEntity && (stackManager.isStackedAndLoaded((LivingEntity)entityO) || all) + && type.equalsIgnoreCase("entities")) { entityO.remove(); + plugin.getEntityStackManager().removeStack(entityO); amountRemoved++; } else if (entityO.getType() == EntityType.DROPPED_ITEM && type.equalsIgnoreCase("items")) { if (!UltimateStacker.hasCustomAmount((Item)entityO) && !all) diff --git a/src/main/java/com/songoda/ultimatestacker/database/DataManager.java b/src/main/java/com/songoda/ultimatestacker/database/DataManager.java index 5a35604..1894f18 100644 --- a/src/main/java/com/songoda/ultimatestacker/database/DataManager.java +++ b/src/main/java/com/songoda/ultimatestacker/database/DataManager.java @@ -3,6 +3,7 @@ package com.songoda.ultimatestacker.database; import com.songoda.core.compatibility.CompatibleMaterial; import com.songoda.core.database.DataManagerAbstract; import com.songoda.core.database.DatabaseConnector; +import com.songoda.ultimatestacker.settings.Settings; import com.songoda.ultimatestacker.stackable.block.BlockStack; import com.songoda.ultimatestacker.stackable.entity.ColdEntityStack; import com.songoda.ultimatestacker.stackable.entity.EntityStack; @@ -16,6 +17,7 @@ import org.bukkit.plugin.Plugin; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -152,7 +154,7 @@ public class DataManager extends DataManagerAbstract { public void updateHost(ColdEntityStack hostStack) { this.async(() -> this.databaseConnector.connect(connection -> { - String updateHost = "UPDATE " + this.getTablePrefix() + "host_entities SET uuid = ?, create_duplicates = ? WHERE id = ?"; + String updateHost = "UPDATE " + this.getTablePrefix() + "host_entities SET uuid = ?, create_duplicates = ?, updated_at = current_timestamp WHERE id = ?"; try (PreparedStatement statement = connection.prepareStatement(updateHost)) { if (hostStack.getHostUniqueId() == null) return; statement.setString(1, hostStack.getHostUniqueId().toString()); @@ -225,9 +227,25 @@ public class DataManager extends DataManagerAbstract { public void getEntities(Consumer> callback) { this.async(() -> this.databaseConnector.connect(connection -> { - + Map entities = new HashMap<>(); + String selectOldEntities = "SELECT * FROM " + this.getTablePrefix() + "host_entities where updated_at <= date('now','-" + Settings.DATABASE_PURGE.getInt() + " day')"; + try (Statement statement = connection.createStatement()) { + List toDelete = new ArrayList<>(); + + ResultSet result = statement.executeQuery(selectOldEntities); + while (result.next()) { + int hostId = result.getInt("id"); + toDelete.add(String.valueOf(hostId)); + } + statement.execute("DELETE FROM " + this.getTablePrefix() + "host_entities where updated_at <= date('now','-" + Settings.DATABASE_PURGE.getInt() + " day')"); + statement.execute("DELETE FROM " + this.getTablePrefix() + "stacked_entities where host IN (" + String.join(", ", toDelete) + ")"); + } catch (Exception e) { + e.printStackTrace(); + } + + String selectEntities = "SELECT * FROM " + this.getTablePrefix() + "host_entities"; try (Statement statement = connection.createStatement()) { ResultSet result = statement.executeQuery(selectEntities); diff --git a/src/main/java/com/songoda/ultimatestacker/database/migrations/_4_DataPurge.java b/src/main/java/com/songoda/ultimatestacker/database/migrations/_4_DataPurge.java new file mode 100644 index 0000000..2ce6297 --- /dev/null +++ b/src/main/java/com/songoda/ultimatestacker/database/migrations/_4_DataPurge.java @@ -0,0 +1,23 @@ +package com.songoda.ultimatestacker.database.migrations; + +import com.songoda.core.database.DataMigration; +import com.songoda.core.database.MySQLConnector; +import com.songoda.ultimatestacker.UltimateStacker; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + +public class _4_DataPurge extends DataMigration { + + public _4_DataPurge() { + super(4); + } + + @Override + public void migrate(Connection connection, String tablePrefix) throws SQLException { + try (Statement statement = connection.createStatement()) { + statement.execute("ALTER TABLE " + tablePrefix + "host_entities ADD COLUMN updated_at datetime DEFAULT NULL"); + } + } +} diff --git a/src/main/java/com/songoda/ultimatestacker/listeners/BlockListeners.java b/src/main/java/com/songoda/ultimatestacker/listeners/BlockListeners.java index a8ce55d..583a9ab 100644 --- a/src/main/java/com/songoda/ultimatestacker/listeners/BlockListeners.java +++ b/src/main/java/com/songoda/ultimatestacker/listeners/BlockListeners.java @@ -4,7 +4,6 @@ import com.songoda.core.compatibility.CompatibleHand; import com.songoda.core.compatibility.CompatibleMaterial; import com.songoda.core.nms.NmsManager; import com.songoda.core.nms.nbt.NBTItem; -import com.songoda.core.utils.PlayerUtils; import com.songoda.ultimatestacker.UltimateStacker; import com.songoda.ultimatestacker.events.SpawnerBreakEvent; import com.songoda.ultimatestacker.events.SpawnerPlaceEvent; @@ -65,7 +64,7 @@ public class BlockListeners implements Listener { if (!isStacked) plugin.getDataManager().createBlock(stack); if (stack.getMaterial() == CompatibleMaterial.getMaterial(inHand)) { int amountToAdd = player.isSneaking() || Settings.ALWAYS_ADD_ALL.getBoolean() ? inHand.getAmount() : 1; - if (!isStacked) amountToAdd ++; + if (!isStacked) amountToAdd++; stack.add(amountToAdd); event.setCancelled(true); if (player.getGameMode() != GameMode.CREATIVE) @@ -162,7 +161,8 @@ public class BlockListeners implements Listener { stack.setAmount(stack.getAmount() + itemAmount); plugin.updateHologram(stack); - hand.takeItem(player); + if (player.getGameMode() != GameMode.CREATIVE) + hand.takeItem(player); } } } diff --git a/src/main/java/com/songoda/ultimatestacker/listeners/DeathListeners.java b/src/main/java/com/songoda/ultimatestacker/listeners/DeathListeners.java index ded22b3..7fb6612 100644 --- a/src/main/java/com/songoda/ultimatestacker/listeners/DeathListeners.java +++ b/src/main/java/com/songoda/ultimatestacker/listeners/DeathListeners.java @@ -87,6 +87,8 @@ public class DeathListeners implements Listener { private boolean shouldDrop(LivingEntity entity, Material material) { if (entity.getEquipment() != null && entity.getEquipment().getArmorContents().length != 0) { + if (Settings.DONT_DROP_ARMOR.getBoolean()) + return false; if (finalItems.containsKey(entity.getUniqueId())) { List items = finalItems.get(entity.getUniqueId()); for (ItemStack item : items) @@ -94,7 +96,7 @@ public class DeathListeners implements Listener { return true; } } - if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11) + if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_12) && entity instanceof ChestedHorse && ((ChestedHorse) entity).getInventory().contains(material)) return true; diff --git a/src/main/java/com/songoda/ultimatestacker/listeners/SpawnerListeners.java b/src/main/java/com/songoda/ultimatestacker/listeners/SpawnerListeners.java index 298b689..9e859d4 100644 --- a/src/main/java/com/songoda/ultimatestacker/listeners/SpawnerListeners.java +++ b/src/main/java/com/songoda/ultimatestacker/listeners/SpawnerListeners.java @@ -1,20 +1,21 @@ package com.songoda.ultimatestacker.listeners; +import com.songoda.core.compatibility.CompatibleHand; import com.songoda.core.compatibility.ServerVersion; import com.songoda.core.nms.NmsManager; +import com.songoda.core.utils.EntityUtils; import com.songoda.ultimatestacker.UltimateStacker; import com.songoda.ultimatestacker.settings.Settings; -import com.songoda.ultimatestacker.stackable.entity.EntityStack; import com.songoda.ultimatestacker.stackable.spawner.SpawnerStack; import com.songoda.ultimatestacker.stackable.spawner.SpawnerStackManager; -import com.songoda.ultimatestacker.utils.Methods; -import com.songoda.ultimatestacker.utils.ReflectionUtil; +import org.bukkit.Bukkit; import org.bukkit.GameMode; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.CreatureSpawner; +import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; -import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -23,11 +24,14 @@ import org.bukkit.event.block.Action; import org.bukkit.event.entity.SpawnerSpawnEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.material.SpawnEgg; +import org.bukkit.metadata.FixedMetadataValue; public class SpawnerListeners implements Listener { private final UltimateStacker plugin; + private static final boolean mcmmo = Bukkit.getPluginManager().isPluginEnabled("mcMMO"); + public SpawnerListeners(UltimateStacker plugin) { this.plugin = plugin; } @@ -37,18 +41,39 @@ public class SpawnerListeners implements Listener { if (!Settings.STACK_ENTITIES.getBoolean() || !plugin.spawnersEnabled() || plugin.getStackingTask().isWorldDisabled(event.getLocation().getWorld())) return; + SpawnerStackManager spawnerStackManager = plugin.getSpawnerStackManager(); if (!spawnerStackManager.isSpawner(event.getSpawner().getLocation())) return; - SpawnerStack spawnerStack = spawnerStackManager.getSpawner(event.getSpawner().getLocation()); + Entity entity = event.getEntity(); + if (entity.getType() == EntityType.FIREWORK) return; + if (entity.getVehicle() != null) { + entity.getVehicle().remove(); + entity.remove(); + } - spawnerStack.initialize(); + if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)) { + if (entity.getPassengers().size() != 0) { + for (Entity e : entity.getPassengers()) { + e.remove(); + } + entity.remove(); + } + } + entity.remove(); - EntityStack stack = plugin.getEntityStackManager().addStack((LivingEntity)event.getEntity()); - stack.createDuplicates(spawnerStack.calculateSpawnCount()); - stack.updateStack(); + Location location = event.getSpawner().getLocation(); - plugin.getStackingTask().attemptSplit(stack, (LivingEntity) event.getEntity()); + SpawnerStack spawnerStack = spawnerStackManager.getSpawner(location); + + spawnerStack.spawn(spawnerStack.calculateSpawnCount(), "EXPLOSION_NORMAL", null, (e) -> { + if (Settings.NO_AI.getBoolean()) + EntityUtils.setUnaware(e); + + if (mcmmo) + entity.setMetadata("mcMMO: Spawned Entity", new FixedMetadataValue(plugin, true)); + return true; + }, event.getEntityType()); } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @@ -92,7 +117,7 @@ public class SpawnerListeners implements Listener { .replace("MOOSHROOM", "MUSHROOM_COW") .replace("ZOMBIE_PIGMAN", "PIG_ZOMBIE")); else if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_12)) { - String str = ReflectionUtil.getNBTTagCompound(ReflectionUtil.getNMSItemStack(event.getItem())).toString(); + String str = NmsManager.getNbt().of(event.getItem()).toString(); if (str.contains("minecraft:")) entityType = EntityType.fromName(str.substring(str.indexOf("minecraft:") + 10, str.indexOf("\"}"))); else @@ -113,7 +138,7 @@ public class SpawnerListeners implements Listener { } - CreatureSpawner creatureSpawner = (CreatureSpawner) block.getState(); + CreatureSpawner creatureSpawner = (CreatureSpawner) block.getState(); if (entityType == creatureSpawner.getSpawnedType()) { plugin.getLocale().getMessage("event.egg.sametype") @@ -125,8 +150,7 @@ public class SpawnerListeners implements Listener { creatureSpawner.update(); plugin.updateHologram(spawner); - if (player.getGameMode() != GameMode.CREATIVE) { - Methods.takeItem(player, stackSize); - } + if (player.getGameMode() != GameMode.CREATIVE) + CompatibleHand.getHand(event).takeItem(player, stackSize); } } diff --git a/src/main/java/com/songoda/ultimatestacker/settings/Settings.java b/src/main/java/com/songoda/ultimatestacker/settings/Settings.java index f6e8bee..b4b55ff 100644 --- a/src/main/java/com/songoda/ultimatestacker/settings/Settings.java +++ b/src/main/java/com/songoda/ultimatestacker/settings/Settings.java @@ -88,6 +88,9 @@ public class Settings { public static final ConfigSetting NO_EXP_INSTANT_KILL = new ConfigSetting(config, "Entities.No Exp For Instant Kills", false, "Should no experience be dropped when an instant kill is performed?"); + public static final ConfigSetting DONT_DROP_ARMOR = new ConfigSetting(config, "Entities.Dont Drop Armor", false, + "Should entities not drop their armor when custom drops are enabled?"); + public static final ConfigSetting STACK_CHECKS = new ConfigSetting(config, "Entities.Stack Checks", Arrays.asList(Check.values()).stream() .filter(Check::isEnabledByDefault).map(Check::name).collect(Collectors.toList()), "These are checks that are processed before an entity is stacked.", @@ -161,6 +164,11 @@ public class Settings { "List the entities using their plugin name as a prefix in all lowercase.", "Example: mythicmobs_test"); + public static final ConfigSetting DATABASE_PURGE = new ConfigSetting(config, "Entities.Database purge", 14, + "How many days must an entity be dormant before it is removed", + "from the database? This setting will prevent dead entities killed incorrectly", + "by other plugins from building up inside of your database and creating lag."); + public static final ConfigSetting STACK_ITEMS = new ConfigSetting(config, "Items.Enabled", true, "Should items be stacked?"); @@ -231,6 +239,9 @@ public class Settings { public static final ConfigSetting EXPLOSION_DROP_CHANCE_CREEPER = new ConfigSetting(config, "Spawners.Chance On Creeper Explosion", "100%", "Chance of a creeper explosion dropping a spawner."); + public static final ConfigSetting NO_AI = new ConfigSetting(config, "Spawners.Nerf Spawner Mobs", false, + "If enabled mobs spawned by spawners will not move or attack."); + public static final ConfigSetting NAME_FORMAT_SPAWNER = new ConfigSetting(config, "Spawners.Name Format", "&f{TYPE} Spawner &6{AMT}x", "The text displayed above a stacked spawner where {TYPE} refers to", "The entities type and {AMT} is the amount currently stacked."); diff --git a/src/main/java/com/songoda/ultimatestacker/stackable/entity/EntityStack.java b/src/main/java/com/songoda/ultimatestacker/stackable/entity/EntityStack.java index d646505..112fcab 100644 --- a/src/main/java/com/songoda/ultimatestacker/stackable/entity/EntityStack.java +++ b/src/main/java/com/songoda/ultimatestacker/stackable/entity/EntityStack.java @@ -111,6 +111,15 @@ public class EntityStack extends ColdEntityStack { preStackedDrops.addAll(drops); } + // In versions 1.14 and below experience is not dropping. Because of this we are doing this ourselves. + if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_14)) { + Location killedLocation = killed.getLocation(); + if (droppedExp > 0) + killedLocation.getWorld().spawn(killedLocation, ExperienceOrb.class).setExperience(droppedExp * getAmount()); + } else { + event.setDroppedExp(droppedExp * getAmount()); + } + DropUtils.processStackedDrop(killed, preStackedDrops, event); if (killed.getKiller() == null) return; @@ -123,9 +132,6 @@ public class EntityStack extends ColdEntityStack { killed.remove(); LivingEntity newEntity = takeOneAndSpawnEntity(killed.getLocation()); - //if (!EntityUtils.isAware(killed)) - // EntityUtils.setUnaware(newEntity); - // In versions 1.14 and below experience is not dropping. Because of this we are doing this ourselves. if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_14)) { Location killedLocation = killed.getLocation(); diff --git a/src/main/java/com/songoda/ultimatestacker/stackable/entity/EntityStackManager.java b/src/main/java/com/songoda/ultimatestacker/stackable/entity/EntityStackManager.java index 0eb9c75..29d8a77 100644 --- a/src/main/java/com/songoda/ultimatestacker/stackable/entity/EntityStackManager.java +++ b/src/main/java/com/songoda/ultimatestacker/stackable/entity/EntityStackManager.java @@ -135,6 +135,7 @@ public class EntityStackManager { EntityStack stack = new EntityStack(entity, coldStack); stack.updateStack(); stacks.put(entity.getUniqueId(), stack); + plugin.getDataManager().updateHost(coldStack); } public void unloadStack(LivingEntity entity) { diff --git a/src/main/java/com/songoda/ultimatestacker/stackable/spawner/SpawnerStack.java b/src/main/java/com/songoda/ultimatestacker/stackable/spawner/SpawnerStack.java index 9c0981b..76a01a4 100644 --- a/src/main/java/com/songoda/ultimatestacker/stackable/spawner/SpawnerStack.java +++ b/src/main/java/com/songoda/ultimatestacker/stackable/spawner/SpawnerStack.java @@ -1,32 +1,28 @@ package com.songoda.ultimatestacker.stackable.spawner; import com.songoda.core.compatibility.CompatibleMaterial; -import com.songoda.core.compatibility.ServerVersion; +import com.songoda.core.world.SSpawner; import com.songoda.ultimatestacker.UltimateStacker; import com.songoda.ultimatestacker.settings.Settings; import com.songoda.ultimatestacker.stackable.Hologramable; import com.songoda.ultimatestacker.utils.Methods; -import com.songoda.ultimatestacker.utils.ReflectionUtil; import com.songoda.ultimatestacker.utils.Stackable; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.CreatureSpawner; import java.util.Random; -public class SpawnerStack implements Stackable, Hologramable { +public class SpawnerStack extends SSpawner implements Stackable, Hologramable { private int id; - private boolean initialized = false; - private final Location location; private int amount; private static final UltimateStacker plugin = UltimateStacker.getInstance(); public SpawnerStack(Location location, int amount) { - this.location = location; + super(location); this.amount = amount; } @@ -45,23 +41,6 @@ public class SpawnerStack implements Stackable, Hologramable { plugin.getDataManager().updateSpawner(this); } - public void updateAmount() { - Bukkit.getScheduler().runTaskLater(plugin, () -> { - if (!(location.getBlock().getState() instanceof CreatureSpawner)) return; - int count = Settings.STACK_ENTITIES.getBoolean() - && !plugin.getStackingTask().isWorldDisabled(location.getWorld()) ? 1 : calculateSpawnCount(); - int maxNearby = amount > 6 ? amount + 3 : 6; - CreatureSpawner creatureSpawner = (CreatureSpawner) location.getBlock().getState(); - if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_12)) { - creatureSpawner.setMaxNearbyEntities(maxNearby); - creatureSpawner.setSpawnCount(count); - } else { - ReflectionUtil.updateSpawner(creatureSpawner, count, maxNearby); - } - creatureSpawner.update(); - }, 1L); - } - public int calculateSpawnCount() { Random random = new Random(); int count = 0; @@ -114,13 +93,6 @@ public class SpawnerStack implements Stackable, Hologramable { return location.getWorld(); } - public void initialize() { - if (!initialized) { - updateAmount(); - this.initialized = true; - } - } - @Override public String toString() { return "SpawnerStack:{" diff --git a/src/main/java/com/songoda/ultimatestacker/utils/Methods.java b/src/main/java/com/songoda/ultimatestacker/utils/Methods.java index b499312..92a2eaa 100644 --- a/src/main/java/com/songoda/ultimatestacker/utils/Methods.java +++ b/src/main/java/com/songoda/ultimatestacker/utils/Methods.java @@ -130,17 +130,6 @@ public class Methods { return TextUtils.formatText(nameFormat).trim(); } - public static void takeItem(Player player, int amount) { - if (player.getGameMode() == GameMode.CREATIVE) return; - - ItemStack item = player.getInventory().getItemInHand(); - - int result = item.getAmount() - amount; - item.setAmount(result); - - player.setItemInHand(result > 0 ? item : null); - } - public static ItemStack getSpawnerItem(EntityType entityType, int amount) { ItemStack item = CompatibleMaterial.SPAWNER.getItem(); ItemMeta meta = item.getItemMeta(); diff --git a/src/main/java/com/songoda/ultimatestacker/utils/ReflectionUtil.java b/src/main/java/com/songoda/ultimatestacker/utils/ReflectionUtil.java deleted file mode 100644 index 5abf0e2..0000000 --- a/src/main/java/com/songoda/ultimatestacker/utils/ReflectionUtil.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.songoda.ultimatestacker.utils; - -import org.bukkit.Bukkit; -import org.bukkit.block.CreatureSpawner; -import org.bukkit.inventory.ItemStack; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; - -public class ReflectionUtil { - - private static Class clazzCraftCreatureSpawner, clazzTileEntityMobSpawner = null; - private static Method methodGetTileEntity, methodGetSpawner; - private static Field fieldSpawnount, fieldMaxNearbyEntities, fieldSpawner; - - public static CreatureSpawner updateSpawner(CreatureSpawner creatureSpawner, int count, int max) { - if (!Bukkit.getServer().getClass().getPackage().getName().contains("1.8")) { - try { - if (creatureSpawner == null) return null; - if (clazzCraftCreatureSpawner == null) { - String ver = Bukkit.getServer().getClass().getPackage().getName().substring(23); - clazzCraftCreatureSpawner = Class.forName("org.bukkit.craftbukkit." + ver + ".block.CraftCreatureSpawner"); - clazzTileEntityMobSpawner = Class.forName("net.minecraft.server." + ver + ".TileEntityMobSpawner"); - Class clazzMobSpawnerAbstract = Class.forName("net.minecraft.server." + ver + ".MobSpawnerAbstract"); - methodGetTileEntity = clazzCraftCreatureSpawner.getDeclaredMethod("getTileEntity"); - methodGetSpawner = clazzTileEntityMobSpawner.getDeclaredMethod("getSpawner"); - fieldSpawnount = clazzMobSpawnerAbstract.getDeclaredField("spawnCount"); - fieldSpawnount.setAccessible(true); - fieldMaxNearbyEntities = clazzMobSpawnerAbstract.getDeclaredField("maxNearbyEntities"); - fieldMaxNearbyEntities.setAccessible(true); - } - - Object objCraftCreatureSpawner = clazzCraftCreatureSpawner.cast(creatureSpawner); - Object objTileEntityMobSpawner = clazzTileEntityMobSpawner.cast(methodGetTileEntity.invoke(objCraftCreatureSpawner)); - Object objMobSpawnerAbstract = methodGetSpawner.invoke(objTileEntityMobSpawner); - fieldSpawnount.set(objMobSpawnerAbstract, count); - fieldMaxNearbyEntities.set(objMobSpawnerAbstract, max); - - } catch (ReflectiveOperationException e) { - e.printStackTrace(); - } - return creatureSpawner; - } else { - try { - if (clazzCraftCreatureSpawner == null) { - String ver = Bukkit.getServer().getClass().getPackage().getName().substring(23); - clazzCraftCreatureSpawner = Class.forName("org.bukkit.craftbukkit." + ver + ".block.CraftCreatureSpawner"); - clazzTileEntityMobSpawner = Class.forName("net.minecraft.server." + ver + ".TileEntityMobSpawner"); - Class clazzMobSpawnerAbstract = Class.forName("net.minecraft.server." + ver + ".MobSpawnerAbstract"); - methodGetSpawner = clazzTileEntityMobSpawner.getDeclaredMethod("getSpawner"); - fieldSpawner = clazzCraftCreatureSpawner.getDeclaredField("spawner"); - fieldSpawner.setAccessible(true); - fieldSpawnount = clazzMobSpawnerAbstract.getDeclaredField("spawnCount"); - fieldSpawnount.setAccessible(true); - fieldMaxNearbyEntities = clazzMobSpawnerAbstract.getDeclaredField("maxNearbyEntities"); - fieldMaxNearbyEntities.setAccessible(true); - } - Object objcraftCreatureSpawner = clazzCraftCreatureSpawner.cast(creatureSpawner); - Object objTileEntityMobSpawner = fieldSpawner.get(objcraftCreatureSpawner); - Object objMobSpawnerAbstract = methodGetSpawner.invoke(objTileEntityMobSpawner); - fieldSpawnount.set(objMobSpawnerAbstract, count); - fieldMaxNearbyEntities.set(objMobSpawnerAbstract, max); - - } catch (ReflectiveOperationException e) { - e.printStackTrace(); - } - return creatureSpawner; - } - } - - public static Object getNMSItemStack(ItemStack item) { - Class cis = getCraftItemStack(); - java.lang.reflect.Method methodAsNMSCopy; - try { - methodAsNMSCopy = cis.getMethod("asNMSCopy", ItemStack.class); - Object answer = methodAsNMSCopy.invoke(cis, item); - return answer; - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return null; - } - - public static Object getNBTTagCompound(Object nmsitem) { - Class c = nmsitem.getClass(); - java.lang.reflect.Method methodGetTag; - try { - methodGetTag = c.getMethod("getTag"); - return methodGetTag.invoke(nmsitem); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return null; - } - - public static Class getCraftItemStack() { - String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; - try { - return Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftItemStack"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI! (Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - - } - - -}