|
@@ -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<String> 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<ItemStack> 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<ItemStack> 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 <ItemStack> potentialItemDrops,
|
|
|
+ @NotNull ItemSpawnReason itemSpawnReason,
|
|
|
+ @NotNull Location spawnLocation,
|
|
|
+ @NotNull Predicate<String> predicate,
|
|
|
+ @NotNull Player player) {
|
|
|
+ for (ItemStack drop : potentialItemDrops) {
|
|
|
+ spawnItem(drop, itemSpawnReason, spawnLocation, predicate, player);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|