diff --git a/src/main/java/com/gmail/nossr50/listeners/BlockListener.java b/src/main/java/com/gmail/nossr50/listeners/BlockListener.java index 1c648b767..b58399ed5 100644 --- a/src/main/java/com/gmail/nossr50/listeners/BlockListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/BlockListener.java @@ -107,7 +107,7 @@ public class BlockListener implements Listener { int bonusCount = bonusDropMeta.asInt(); for (int i = 0; i < bonusCount; i++) { - Misc.spawnItemNaturally(event.getPlayer(), event.getBlockState().getLocation(), is, ItemSpawnReason.BONUS_DROPS); + ItemUtils.spawnItemNaturally(event.getPlayer(), event.getBlockState().getLocation(), is, ItemSpawnReason.BONUS_DROPS); } } } diff --git a/src/main/java/com/gmail/nossr50/skills/archery/Archery.java b/src/main/java/com/gmail/nossr50/skills/archery/Archery.java index d5cf998e8..b549c9a2c 100644 --- a/src/main/java/com/gmail/nossr50/skills/archery/Archery.java +++ b/src/main/java/com/gmail/nossr50/skills/archery/Archery.java @@ -4,7 +4,7 @@ import com.gmail.nossr50.api.ItemSpawnReason; import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.mcMMO; -import com.gmail.nossr50.util.Misc; +import com.gmail.nossr50.util.ItemUtils; import com.gmail.nossr50.util.skills.RankUtils; import org.bukkit.Material; import org.bukkit.entity.LivingEntity; @@ -57,7 +57,7 @@ public class Archery { TrackedEntity trackedEntity = entityIterator.next(); if (trackedEntity.getID() == livingEntity.getUniqueId()) { - Misc.spawnItems(null, livingEntity.getLocation(), new ItemStack(Material.ARROW), trackedEntity.getArrowCount(), ItemSpawnReason.ARROW_RETRIEVAL_ACTIVATED); + ItemUtils.spawnItems(null, livingEntity.getLocation(), new ItemStack(Material.ARROW), trackedEntity.getArrowCount(), ItemSpawnReason.ARROW_RETRIEVAL_ACTIVATED); entityIterator.remove(); return; } diff --git a/src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java b/src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java index 434b675b1..0bb822438 100644 --- a/src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java +++ b/src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java @@ -9,6 +9,7 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.datatypes.treasure.ExcavationTreasure; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.skills.SkillManager; +import com.gmail.nossr50.util.ItemUtils; import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.random.ProbabilityUtil; @@ -73,7 +74,7 @@ public class ExcavationManager extends SkillManager { int xp = 0; xp += treasure.getXp(); - Misc.spawnItem(getPlayer(), location, treasure.getDrop(), ItemSpawnReason.EXCAVATION_TREASURE); + ItemUtils.spawnItem(getPlayer(), location, treasure.getDrop(), ItemSpawnReason.EXCAVATION_TREASURE); if (xp > 0) { applyXpGain(xp, XPGainReason.PVE, XPGainSource.SELF); } diff --git a/src/main/java/com/gmail/nossr50/skills/fishing/FishingManager.java b/src/main/java/com/gmail/nossr50/skills/fishing/FishingManager.java index 7dbf66221..4d37adced 100644 --- a/src/main/java/com/gmail/nossr50/skills/fishing/FishingManager.java +++ b/src/main/java/com/gmail/nossr50/skills/fishing/FishingManager.java @@ -446,7 +446,7 @@ public class FishingManager extends SkillManager { if (fishingSucceeds) { if (mcMMO.p.getGeneralConfig().getFishingExtraFish()) { - Misc.spawnItem(getPlayer(), player.getEyeLocation(), fishingCatch.getItemStack(), ItemSpawnReason.FISHING_EXTRA_FISH); + ItemUtils.spawnItem(getPlayer(), player.getEyeLocation(), fishingCatch.getItemStack(), ItemSpawnReason.FISHING_EXTRA_FISH); } fishingCatch.setItemStack(treasureDrop); @@ -552,7 +552,7 @@ public class FishingManager extends SkillManager { return; } - Misc.spawnItem(getPlayer(), target.getLocation(), drop, ItemSpawnReason.FISHING_SHAKE_TREASURE); + ItemUtils.spawnItem(getPlayer(), target.getLocation(), drop, ItemSpawnReason.FISHING_SHAKE_TREASURE); CombatUtils.dealDamage(target, Math.min(Math.max(target.getMaxHealth() / 4, 1), 10), EntityDamageEvent.DamageCause.CUSTOM, getPlayer()); // Make it so you can shake a mob no more than 4 times. applyXpGain(ExperienceConfig.getInstance().getFishingShakeXP(), XPGainReason.PVE); } diff --git a/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java b/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java index adbdf2a84..0e39750ca 100644 --- a/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java +++ b/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java @@ -691,7 +691,7 @@ public class HerbalismManager extends SkillManager { return false; } blockState.setType(Material.AIR); - Misc.spawnItem(getPlayer(), location, treasure.getDrop(), ItemSpawnReason.HYLIAN_LUCK_TREASURE); + ItemUtils.spawnItem(getPlayer(), location, treasure.getDrop(), ItemSpawnReason.HYLIAN_LUCK_TREASURE); NotificationManager.sendPlayerInformation(mmoPlayer.getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Herbalism.HylianLuck"); return true; } diff --git a/src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java b/src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java index 3bb866cdd..07d934b98 100644 --- a/src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java +++ b/src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java @@ -204,7 +204,7 @@ public class MiningManager extends SkillManager { continue; if (Probability.ofPercent(50).evaluate()) { - Misc.spawnItem(getPlayer(), Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_DEBRIS_NON_ORES); // Initial block that would have been dropped + ItemUtils.spawnItem(getPlayer(), Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_DEBRIS_NON_ORES); // Initial block that would have been dropped } } @@ -215,12 +215,12 @@ public class MiningManager extends SkillManager { if (RandomUtils.nextFloat() < (yield + oreBonus)) { xp += Mining.getBlockXp(blockState); - Misc.spawnItem(getPlayer(), Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_ORES); // Initial block that would have been dropped + ItemUtils.spawnItem(getPlayer(), Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_ORES); // Initial block that would have been dropped if (mcMMO.p.getAdvancedConfig().isBlastMiningBonusDropsEnabled() && !mcMMO.getUserBlockTracker().isIneligible(blockState)) { for (int i = 1; i < dropMultiplier; i++) { // Bukkit.broadcastMessage("Bonus Drop on Ore: "+blockState.getType().toString()); - Misc.spawnItem(getPlayer(), Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_ORES_BONUS_DROP); // Initial block that would have been dropped + ItemUtils.spawnItem(getPlayer(), Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_ORES_BONUS_DROP); // Initial block that would have been dropped } } } diff --git a/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java b/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java index b80160c89..e1bf40e08 100644 --- a/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java +++ b/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java @@ -11,6 +11,7 @@ import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.skills.SkillManager; import com.gmail.nossr50.skills.salvage.salvageables.Salvageable; import com.gmail.nossr50.util.EventUtils; +import com.gmail.nossr50.util.ItemUtils; import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.player.NotificationManager; @@ -165,10 +166,10 @@ public class SalvageManager extends SkillManager { anvilLoc.add(0, .1, 0); if (enchantBook != null) { - Misc.spawnItemTowardsLocation(getPlayer(), anvilLoc.clone(), playerLoc.clone(), enchantBook, vectorSpeed, ItemSpawnReason.SALVAGE_ENCHANTMENT_BOOK); + ItemUtils.spawnItemTowardsLocation(getPlayer(), anvilLoc.clone(), playerLoc.clone(), enchantBook, vectorSpeed, ItemSpawnReason.SALVAGE_ENCHANTMENT_BOOK); } - Misc.spawnItemTowardsLocation(getPlayer(), anvilLoc.clone(), playerLoc.clone(), salvageResults, vectorSpeed, ItemSpawnReason.SALVAGE_MATERIALS); + ItemUtils.spawnItemTowardsLocation(getPlayer(), anvilLoc.clone(), playerLoc.clone(), salvageResults, vectorSpeed, ItemSpawnReason.SALVAGE_MATERIALS); // BWONG BWONG BWONG - CLUNK! if (mcMMO.p.getGeneralConfig().getSalvageAnvilUseSoundsEnabled()) { diff --git a/src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java b/src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java index 933dbb8f4..4d728abe6 100644 --- a/src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java +++ b/src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java @@ -106,7 +106,7 @@ public class UnarmedManager extends SkillManager { if (UserManager.getPlayer(defender) == null) return; - Item item = Misc.spawnItem(getPlayer(), defender.getLocation(), defender.getInventory().getItemInMainHand(), ItemSpawnReason.UNARMED_DISARMED_ITEM); + Item item = ItemUtils.spawnItem(getPlayer(), defender.getLocation(), defender.getInventory().getItemInMainHand(), ItemSpawnReason.UNARMED_DISARMED_ITEM); if (item != null && mcMMO.p.getAdvancedConfig().getDisarmProtected()) { item.setMetadata(MetadataConstants.METADATA_KEY_DISARMED_ITEM, UserManager.getPlayer(defender).getPlayerMetadata()); diff --git a/src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java b/src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java index 58b7403d9..76af4db6a 100644 --- a/src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java +++ b/src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java @@ -37,7 +37,7 @@ import java.util.Set; import java.util.concurrent.ThreadLocalRandom; import static com.gmail.nossr50.util.Misc.getBlockCenter; -import static com.gmail.nossr50.util.Misc.spawnItem; +import static com.gmail.nossr50.util.ItemUtils.spawnItem; import static com.gmail.nossr50.util.skills.RankUtils.hasUnlockedSubskill; //TODO: Seems to not be using the item drop event for bonus drops, may want to change that.. or may not be able to be changed? @@ -322,14 +322,14 @@ public class WoodcuttingManager extends SkillManager { xp += processTreeFellerXPGains(blockState, processedLogCount); //Drop displaced block - Misc.spawnItemsFromCollection(player, getBlockCenter(blockState), block.getDrops(itemStack), ItemSpawnReason.TREE_FELLER_DISPLACED_BLOCK); + ItemUtils.spawnItemsFromCollection(player, getBlockCenter(blockState), block.getDrops(itemStack), ItemSpawnReason.TREE_FELLER_DISPLACED_BLOCK); //Bonus Drops / Harvest lumber checks processBonusDropCheck(blockState); } else if (BlockUtils.isNonWoodPartOfTree(blockState)) { // 75% of the time do not drop leaf blocks if (ThreadLocalRandom.current().nextInt(100) > 75) { - Misc.spawnItemsFromCollection(player, + ItemUtils.spawnItemsFromCollection(player, getBlockCenter(blockState), block.getDrops(itemStack), ItemSpawnReason.TREE_FELLER_DISPLACED_BLOCK); @@ -422,7 +422,7 @@ public class WoodcuttingManager extends SkillManager { * @param blockState Block being broken */ protected void spawnHarvestLumberBonusDrops(@NotNull BlockState blockState) { - Misc.spawnItemsFromCollection( + ItemUtils.spawnItemsFromCollection( getPlayer(), getBlockCenter(blockState), blockState.getBlock().getDrops(getPlayer().getInventory().getItemInMainHand()), diff --git a/src/main/java/com/gmail/nossr50/util/ItemUtils.java b/src/main/java/com/gmail/nossr50/util/ItemUtils.java index e80bf3053..094664cff 100644 --- a/src/main/java/com/gmail/nossr50/util/ItemUtils.java +++ b/src/main/java/com/gmail/nossr50/util/ItemUtils.java @@ -1,29 +1,36 @@ package com.gmail.nossr50.util; +import com.gmail.nossr50.api.ItemSpawnReason; import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.config.party.ItemWeightConfig; import com.gmail.nossr50.datatypes.treasure.EnchantmentWrapper; import com.gmail.nossr50.datatypes.treasure.FishingTreasureBook; +import com.gmail.nossr50.events.items.McMMOItemSpawnEvent; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.skills.smelting.Smelting; import org.bukkit.ChatColor; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.inventory.FurnaceRecipe; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.Recipe; import org.bukkit.inventory.meta.EnchantmentStorageMeta; import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.function.Predicate; import static java.util.Objects.requireNonNull; @@ -787,4 +794,187 @@ public final class ItemUtils { int randomIndex = Misc.getRandom().nextInt(enchantmentWrappers.size()); return enchantmentWrappers.get(randomIndex); } + + /** + * Spawn item if conditions are met. + * + * @param potentialItemSpawn The item to spawn if conditions are met + * @param itemSpawnReason The reason for the item drop + * @param spawnLocation The location to spawn the item at + * @param predicate The predicate to test the item against + * @param player The player to spawn the item for + */ + public static void spawnItem(@NotNull ItemStack potentialItemSpawn, + @NotNull ItemSpawnReason itemSpawnReason, + @NotNull Location spawnLocation, + @NotNull Predicate predicate, + @NotNull Player player) { + if (predicate.test(potentialItemSpawn.getType().getKey().getKey())) { + spawnItem(player, spawnLocation, potentialItemSpawn, itemSpawnReason); + } + } + + /** + * Drop items at a given location. + * + * @param location The location to drop the items at + * @param is The items to drop + * @param quantity The amount of items to drop + */ + public static void spawnItems(@Nullable Player player, @NotNull Location location, @NotNull ItemStack is, int quantity, @NotNull ItemSpawnReason itemSpawnReason) { + for (int i = 0; i < quantity; i++) { + spawnItem(player, location, is, itemSpawnReason); + } + } + + /** + * Drop an item at a given location. + * + * @param location The location to drop the item at + * @param itemStack The item to drop + * @param itemSpawnReason the reason for the item drop + * @return Dropped Item entity or null if invalid or cancelled + */ + public static @Nullable Item spawnItem(@Nullable Player player, @NotNull Location location, @NotNull ItemStack itemStack, @NotNull ItemSpawnReason itemSpawnReason) { + if (itemStack.getType() == Material.AIR || location.getWorld() == null) { + return null; + } + + // We can't get the item until we spawn it and we want to make it cancellable, so we have a custom event. + McMMOItemSpawnEvent event = new McMMOItemSpawnEvent(location, itemStack, itemSpawnReason, player); + mcMMO.p.getServer().getPluginManager().callEvent(event); + + if (event.isCancelled()) { + return null; + } + + return location.getWorld().dropItem(location, itemStack); + } + + /** + * Drop an item at a given location. + * + * @param location The location to drop the item at + * @param itemStack The item to drop + * @param itemSpawnReason the reason for the item drop + * @return Dropped Item entity or null if invalid or cancelled + */ + public static @Nullable Item spawnItemNaturally(@Nullable Player player, @NotNull Location location, @NotNull ItemStack itemStack, @NotNull ItemSpawnReason itemSpawnReason) { + if (itemStack.getType() == Material.AIR || location.getWorld() == null) { + return null; + } + + // We can't get the item until we spawn it and we want to make it cancellable, so we have a custom event. + McMMOItemSpawnEvent event = new McMMOItemSpawnEvent(location, itemStack, itemSpawnReason, player); + mcMMO.p.getServer().getPluginManager().callEvent(event); + + if (event.isCancelled()) { + return null; + } + + return location.getWorld().dropItemNaturally(location, itemStack); + } + + /** + * Drop items at a given location. + * + * @param fromLocation The location to drop the items at + * @param is The items to drop + * @param speed the speed that the item should travel + * @param quantity The amount of items to drop + */ + public static void spawnItemsTowardsLocation(@Nullable Player player, @NotNull Location fromLocation, @NotNull Location toLocation, @NotNull ItemStack is, int quantity, double speed, @NotNull ItemSpawnReason itemSpawnReason) { + for (int i = 0; i < quantity; i++) { + spawnItemTowardsLocation(player, fromLocation, toLocation, is, speed, itemSpawnReason); + } + } + + /** + * Drop an item at a given location. + * This method is fairly expensive as it creates clones of everything passed to itself since they are mutable objects + * + * @param fromLocation The location to drop the item at + * @param toLocation The location the item will travel towards + * @param itemToSpawn The item to spawn + * @param speed the speed that the item should travel + * @return Dropped Item entity or null if invalid or cancelled + */ + public static @Nullable Item spawnItemTowardsLocation(@Nullable Player player, @NotNull Location fromLocation, @NotNull Location toLocation, @NotNull ItemStack itemToSpawn, double speed, @NotNull ItemSpawnReason itemSpawnReason) { + if (itemToSpawn.getType() == Material.AIR) { + return null; + } + + //Work with fresh copies of everything + ItemStack clonedItem = itemToSpawn.clone(); + Location spawnLocation = fromLocation.clone(); + Location targetLocation = toLocation.clone(); + + if (spawnLocation.getWorld() == null) + return null; + + // We can't get the item until we spawn it and we want to make it cancellable, so we have a custom event. + McMMOItemSpawnEvent event = new McMMOItemSpawnEvent(spawnLocation, clonedItem, itemSpawnReason, player); + mcMMO.p.getServer().getPluginManager().callEvent(event); + + //Something cancelled the event so back out + if (event.isCancelled()) { + return null; + } + + //Use the item from the event + Item spawnedItem = spawnLocation.getWorld().dropItem(spawnLocation, clonedItem); + Vector vecFrom = spawnLocation.clone().toVector().clone(); + Vector vecTo = targetLocation.clone().toVector().clone(); + + //Vector which is pointing towards out target location + Vector direction = vecTo.subtract(vecFrom).normalize(); + + //Modify the speed of the vector + direction = direction.multiply(speed); + spawnedItem.setVelocity(direction); + return spawnedItem; + } + + public static void spawnItemsFromCollection(@NotNull Player player, @NotNull Location location, @NotNull Collection drops, @NotNull ItemSpawnReason itemSpawnReason) { + for (ItemStack drop : drops) { + spawnItem(player, location, drop, itemSpawnReason); + } + } + + /** + * Drops only the first n items in a collection + * Size should always be a positive integer above 0 + * + * @param location target drop location + * @param drops collection to iterate over + * @param sizeLimit the number of drops to process + */ + public static void spawnItemsFromCollection(@Nullable Player player, @NotNull Location location, @NotNull Collection drops, @NotNull ItemSpawnReason itemSpawnReason, int sizeLimit) { + ItemStack[] arrayDrops = drops.toArray(new ItemStack[0]); + + for(int i = 0; i < sizeLimit-1; i++) { + spawnItem(player, location, arrayDrops[i], itemSpawnReason); + } + } + + /** + * Spawn items form a collection if conditions are met. + * Each item is tested against the condition and spawned if it passes. + * + * @param potentialItemDrops The collection of items to iterate over, each one is tested and spawned if the + * predicate is true + * @param itemSpawnReason The reason for the item drop + * @param spawnLocation The location to spawn the item at + * @param predicate The predicate to test the item against + * @param player The player to spawn the item for + */ + public static void spawnItem(@NotNull Collection potentialItemDrops, + @NotNull ItemSpawnReason itemSpawnReason, + @NotNull Location spawnLocation, + @NotNull Predicate predicate, + @NotNull Player player) { + for (ItemStack drop : potentialItemDrops) { + spawnItem(drop, itemSpawnReason, spawnLocation, predicate, player); + } + } } diff --git a/src/main/java/com/gmail/nossr50/util/Misc.java b/src/main/java/com/gmail/nossr50/util/Misc.java index 167b70596..0f31bd77f 100644 --- a/src/main/java/com/gmail/nossr50/util/Misc.java +++ b/src/main/java/com/gmail/nossr50/util/Misc.java @@ -1,26 +1,19 @@ package com.gmail.nossr50.util; -import com.gmail.nossr50.api.ItemSpawnReason; import com.gmail.nossr50.datatypes.player.McMMOPlayer; -import com.gmail.nossr50.events.items.McMMOItemSpawnEvent; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.runnables.player.PlayerProfileLoadingTask; import com.gmail.nossr50.util.player.UserManager; import com.google.common.collect.ImmutableSet; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.block.BlockState; import org.bukkit.entity.*; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collection; import java.util.Locale; import java.util.Random; import java.util.Set; -import java.util.function.Predicate; public final class Misc { private static final @NotNull Random random = new Random(); @@ -107,189 +100,6 @@ public final class Misc { return blockState.getLocation().add(0.5, 0.5, 0.5); } - public static void spawnItemsFromCollection(@NotNull Player player, @NotNull Location location, @NotNull Collection drops, @NotNull ItemSpawnReason itemSpawnReason) { - for (ItemStack drop : drops) { - spawnItem(player, location, drop, itemSpawnReason); - } - } - - /** - * Drops only the first n items in a collection - * Size should always be a positive integer above 0 - * - * @param location target drop location - * @param drops collection to iterate over - * @param sizeLimit the number of drops to process - */ - public static void spawnItemsFromCollection(@Nullable Player player, @NotNull Location location, @NotNull Collection drops, @NotNull ItemSpawnReason itemSpawnReason, int sizeLimit) { - ItemStack[] arrayDrops = drops.toArray(new ItemStack[0]); - - for(int i = 0; i < sizeLimit-1; i++) { - spawnItem(player, location, arrayDrops[i], itemSpawnReason); - } - } - - /** - * Spawn items form a collection if conditions are met. - * Each item is tested against the condition and spawned if it passes. - * - * @param potentialItemDrops The collection of items to iterate over, each one is tested and spawned if the - * predicate is true - * @param itemSpawnReason The reason for the item drop - * @param spawnLocation The location to spawn the item at - * @param predicate The predicate to test the item against - * @param player The player to spawn the item for - */ - public static void spawnItem(@NotNull Collection potentialItemDrops, - @NotNull ItemSpawnReason itemSpawnReason, - @NotNull Location spawnLocation, - @NotNull Predicate predicate, - @NotNull Player player) { - for (ItemStack drop : potentialItemDrops) { - spawnItem(drop, itemSpawnReason, spawnLocation, predicate, player); - } - } - - /** - * Spawn item if conditions are met. - * - * @param potentialItemSpawn The item to spawn if conditions are met - * @param itemSpawnReason The reason for the item drop - * @param spawnLocation The location to spawn the item at - * @param predicate The predicate to test the item against - * @param player The player to spawn the item for - */ - public static void spawnItem(@NotNull ItemStack potentialItemSpawn, - @NotNull ItemSpawnReason itemSpawnReason, - @NotNull Location spawnLocation, - @NotNull Predicate predicate, - @NotNull Player player) { - if (predicate.test(potentialItemSpawn.getType().getKey().getKey())) { - spawnItem(player, spawnLocation, potentialItemSpawn, itemSpawnReason); - } - } - - /** - * Drop items at a given location. - * - * @param location The location to drop the items at - * @param is The items to drop - * @param quantity The amount of items to drop - */ - public static void spawnItems(@Nullable Player player, @NotNull Location location, @NotNull ItemStack is, int quantity, @NotNull ItemSpawnReason itemSpawnReason) { - for (int i = 0; i < quantity; i++) { - spawnItem(player, location, is, itemSpawnReason); - } - } - - /** - * Drop an item at a given location. - * - * @param location The location to drop the item at - * @param itemStack The item to drop - * @param itemSpawnReason the reason for the item drop - * @return Dropped Item entity or null if invalid or cancelled - */ - public static @Nullable Item spawnItem(@Nullable Player player, @NotNull Location location, @NotNull ItemStack itemStack, @NotNull ItemSpawnReason itemSpawnReason) { - if (itemStack.getType() == Material.AIR || location.getWorld() == null) { - return null; - } - - // We can't get the item until we spawn it and we want to make it cancellable, so we have a custom event. - McMMOItemSpawnEvent event = new McMMOItemSpawnEvent(location, itemStack, itemSpawnReason, player); - mcMMO.p.getServer().getPluginManager().callEvent(event); - - if (event.isCancelled()) { - return null; - } - - return location.getWorld().dropItem(location, itemStack); - } - - /** - * Drop an item at a given location. - * - * @param location The location to drop the item at - * @param itemStack The item to drop - * @param itemSpawnReason the reason for the item drop - * @return Dropped Item entity or null if invalid or cancelled - */ - public static @Nullable Item spawnItemNaturally(@Nullable Player player, @NotNull Location location, @NotNull ItemStack itemStack, @NotNull ItemSpawnReason itemSpawnReason) { - if (itemStack.getType() == Material.AIR || location.getWorld() == null) { - return null; - } - - // We can't get the item until we spawn it and we want to make it cancellable, so we have a custom event. - McMMOItemSpawnEvent event = new McMMOItemSpawnEvent(location, itemStack, itemSpawnReason, player); - mcMMO.p.getServer().getPluginManager().callEvent(event); - - if (event.isCancelled()) { - return null; - } - - return location.getWorld().dropItemNaturally(location, itemStack); - } - - /** - * Drop items at a given location. - * - * @param fromLocation The location to drop the items at - * @param is The items to drop - * @param speed the speed that the item should travel - * @param quantity The amount of items to drop - */ - public static void spawnItemsTowardsLocation(@Nullable Player player, @NotNull Location fromLocation, @NotNull Location toLocation, @NotNull ItemStack is, int quantity, double speed, @NotNull ItemSpawnReason itemSpawnReason) { - for (int i = 0; i < quantity; i++) { - spawnItemTowardsLocation(player, fromLocation, toLocation, is, speed, itemSpawnReason); - } - } - - /** - * Drop an item at a given location. - * This method is fairly expensive as it creates clones of everything passed to itself since they are mutable objects - * - * @param fromLocation The location to drop the item at - * @param toLocation The location the item will travel towards - * @param itemToSpawn The item to spawn - * @param speed the speed that the item should travel - * @return Dropped Item entity or null if invalid or cancelled - */ - public static @Nullable Item spawnItemTowardsLocation(@Nullable Player player, @NotNull Location fromLocation, @NotNull Location toLocation, @NotNull ItemStack itemToSpawn, double speed, @NotNull ItemSpawnReason itemSpawnReason) { - if (itemToSpawn.getType() == Material.AIR) { - return null; - } - - //Work with fresh copies of everything - ItemStack clonedItem = itemToSpawn.clone(); - Location spawnLocation = fromLocation.clone(); - Location targetLocation = toLocation.clone(); - - if (spawnLocation.getWorld() == null) - return null; - - // We can't get the item until we spawn it and we want to make it cancellable, so we have a custom event. - McMMOItemSpawnEvent event = new McMMOItemSpawnEvent(spawnLocation, clonedItem, itemSpawnReason, player); - mcMMO.p.getServer().getPluginManager().callEvent(event); - - //Something cancelled the event so back out - if (event.isCancelled()) { - return null; - } - - //Use the item from the event - Item spawnedItem = spawnLocation.getWorld().dropItem(spawnLocation, clonedItem); - Vector vecFrom = spawnLocation.clone().toVector().clone(); - Vector vecTo = targetLocation.clone().toVector().clone(); - - //Vector which is pointing towards out target location - Vector direction = vecTo.subtract(vecFrom).normalize(); - - //Modify the speed of the vector - direction = direction.multiply(speed); - spawnedItem.setVelocity(direction); - return spawnedItem; - } - public static void profileCleanup(@NotNull String playerName) { Player player = mcMMO.p.getServer().getPlayerExact(playerName);