package de.flo56958.minetinker.utils.data; import de.flo56958.minetinker.MineTinker; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.block.Block; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.EntityType; import org.bukkit.entity.ExperienceOrb; import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockDropItemEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Random; import java.util.stream.Collectors; public class DataHandler { public static <T, Z> boolean hasTag(@NotNull ItemStack item, @NotNull String key, PersistentDataType<T, Z> dataType, boolean useMinecraft) { ItemMeta meta = item.getItemMeta(); if (meta == null) return false; PersistentDataContainer container = meta.getPersistentDataContainer(); return container.has((useMinecraft ? NamespacedKey.minecraft(key) : new NamespacedKey(MineTinker.getPlugin(), key)), dataType); } public static <T, Z> void setTag(@NotNull ItemStack item, @NotNull String key, Z value, PersistentDataType<T, Z> dataType, boolean useMinecraft) { ItemMeta meta = item.getItemMeta(); if (meta == null) return; PersistentDataContainer container = meta.getPersistentDataContainer(); container.set((useMinecraft ? NamespacedKey.minecraft(key) : new NamespacedKey(MineTinker.getPlugin(), key)), dataType, value); item.setItemMeta(meta); } public static <T, Z> @Nullable Z getTag(@NotNull ItemStack item, @NotNull String key, PersistentDataType<T, Z> dataType, boolean useMinecraft) { ItemMeta meta = item.getItemMeta(); if (meta == null) return null; PersistentDataContainer container = meta.getPersistentDataContainer(); return container.get((useMinecraft ? NamespacedKey.minecraft(key) : new NamespacedKey(MineTinker.getPlugin(), key)), dataType); } public static void removeTag(@NotNull ItemStack item, @NotNull String key, boolean useMinecraft) { ItemMeta meta = item.getItemMeta(); if (meta == null) return; PersistentDataContainer container = meta.getPersistentDataContainer(); container.remove((useMinecraft ? NamespacedKey.minecraft(key) : new NamespacedKey(MineTinker.getPlugin(), key))); item.setItemMeta(meta); } public static boolean playerBreakBlock(@NotNull Player player, Block block, @NotNull ItemStack itemStack) { //Trigger BlockBreakEvent BlockBreakEvent breakEvent = new BlockBreakEvent(block, player); ItemMeta meta = itemStack.getItemMeta(); if (meta != null && !meta.hasEnchant(Enchantment.SILK_TOUCH)) breakEvent.setExpToDrop(calculateExp(block.getType())); Bukkit.getPluginManager().callEvent(breakEvent); //Check if Event got cancelled and if not destroy the block and check if the player can successfully break the blocks (incl. drops) //Block#breakNaturally(ItemStack itemStack) can not be used as it drops Items itself (without Event and we don't want that) if (!breakEvent.isCancelled()) { //Get all drops to drop Collection<ItemStack> items = block.getDrops(itemStack); //Set Block to Material.AIR (effectively breaks the Block) block.setType(Material.AIR); //TODO: Play Sound? //Check if items need to be dropped if (breakEvent.isDropItems()) { List<Item> itemEntities = items.stream() .map(entry -> player.getWorld().dropItemNaturally(block.getLocation(), entry)) //World#spawnEntity() does not work for Items .collect(Collectors.toList()); //Trigger BlockDropItemEvent (internally also used for Directing) BlockDropItemEvent event = new BlockDropItemEvent(block, block.getState(), player, new ArrayList<>(itemEntities)); Bukkit.getPluginManager().callEvent(event); //check if Event got cancelled if (!event.isCancelled()) { //Remove all drops that should be dropped itemEntities.removeIf(element -> event.getItems().contains(element)); } itemEntities.forEach(Item::remove); } //Check if Exp needs to be dropped if (breakEvent.getExpToDrop() > 0) { //Spawn Experience Orb ExperienceOrb orb = (ExperienceOrb) player.getWorld().spawnEntity(block.getLocation(), EntityType.EXPERIENCE_ORB); orb.setExperience(breakEvent.getExpToDrop()); } return true; } return false; } private static int calculateExp(Material type) { //TODO: Find better method then hardcoded values switch(type) { case COAL_ORE: //0-2 return new Random().nextInt(3); case DIAMOND_ORE: //3-7 case EMERALD_ORE: return new Random().nextInt(5) + 3; case NETHER_QUARTZ_ORE: //2-5 case LAPIS_ORE: return new Random().nextInt(4) + 2; case REDSTONE_ORE: //1-5 return new Random().nextInt(4) + 1; case SPAWNER: //15-43 return new Random().nextInt(29) + 15; default: return 0; } } }