From 5a1442f13af7cda216b45646f0e0fdf612cde6de Mon Sep 17 00:00:00 2001 From: TheBusyBiscuit Date: Thu, 8 Jul 2021 11:17:56 +0200 Subject: [PATCH] Added SlimefunItemSpawnEvent and ItemSpawnReason This allows other plugins to provide compatibility in some places --- CHANGELOG.md | 1 + .../api/events/SlimefunItemSpawnEvent.java | 111 ++++++++++++++++++ .../slimefun4/api/items/ItemSpawnReason.java | 62 ++++++++++ .../core/networks/cargo/CargoNetworkTask.java | 9 +- .../items/altar/AncientPedestal.java | 28 ++--- .../items/seasonal/ChristmasPresent.java | 4 +- .../items/seasonal/EasterEgg.java | 5 +- .../implementation/items/tools/GoldPan.java | 5 +- .../items/tools/PickaxeOfContainment.java | 10 +- .../listeners/AutoCrafterListener.java | 39 +++--- .../slimefun4/utils/SlimefunUtils.java | 57 +++++++++ 11 files changed, 293 insertions(+), 38 deletions(-) create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunItemSpawnEvent.java create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/api/items/ItemSpawnReason.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 43a2783d0..d8a2ef53d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ * Deepslate ores can now be doubled using an Ore Crusher * Tridents can now be crafted * The Industrial Miner can now mine up to the minimum world limit (previously only until y=0) +* (API) Added SlimefunItemSpawnEvent and ItemSpawnReason #### Changes diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunItemSpawnEvent.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunItemSpawnEvent.java new file mode 100644 index 000000000..27f544e7e --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunItemSpawnEvent.java @@ -0,0 +1,111 @@ +package io.github.thebusybiscuit.slimefun4.api.events; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; + +import org.apache.commons.lang.Validate; +import org.bukkit.Location; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.inventory.ItemStack; + +import io.github.thebusybiscuit.slimefun4.api.items.ItemSpawnReason; + +/** + * This {@link Event} is fired whenever slimefun drops an {@link ItemStack}. + * Creating a custom {@link Event} for this allows other plugins to provide + * compatibility with auto-pickup options or similar. + * + * @author TheBusyBiscuit + * + * @see ItemSpawnReason + */ +public class SlimefunItemSpawnEvent extends Event implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + + private Location location; + private ItemStack itemStack; + private boolean cancelled; + private final ItemSpawnReason itemSpawnReason; + + @ParametersAreNonnullByDefault + public SlimefunItemSpawnEvent(Location location, ItemStack itemStack, ItemSpawnReason itemSpawnReason) { + this.location = location; + this.itemStack = itemStack; + this.itemSpawnReason = itemSpawnReason; + this.cancelled = false; + } + + /** + * This returns the {@link ItemSpawnReason} why we dropped an {@link ItemStack}. + * + * @return the {@link ItemSpawnReason}. + */ + public @Nonnull ItemSpawnReason getItemSpawnReason() { + return itemSpawnReason; + } + + /** + * This returns the {@link Location} where we will drop the item. + * + * @return The {@link Location} where the item will be dropped + */ + public @Nonnull Location getLocation() { + return location; + } + + /** + * This sets the {@link Location} on where to drop this item. + * + * @param location + * The {@link Location} where to drop the {@link ItemStack} + */ + public void setLocation(@Nonnull Location location) { + Validate.notNull(location, "The Location cannot be null!"); + + this.location = location; + } + + /** + * This returns the {@link ItemStack} that will be dropped. + * + * @return The {@link ItemStack} that will be dropped + */ + public @Nonnull ItemStack getItemStack() { + return itemStack; + } + + /** + * This method sets the {@link ItemStack} that should be dropped. + * + * @param itemStack + * The {@link ItemStack} to drop + */ + public void setItemStack(@Nonnull ItemStack itemStack) { + Validate.notNull(itemStack, "Cannot drop null."); + Validate.isTrue(!itemStack.getType().isAir(), "Cannot drop air."); + + this.itemStack = itemStack; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + public static @Nonnull HandlerList getHandlerList() { + return handlers; + } + + @Override + public @Nonnull HandlerList getHandlers() { + return getHandlerList(); + } +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/ItemSpawnReason.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/ItemSpawnReason.java new file mode 100644 index 000000000..554bc6ad5 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/ItemSpawnReason.java @@ -0,0 +1,62 @@ +package io.github.thebusybiscuit.slimefun4.api.items; + +import org.bukkit.block.Block; +import org.bukkit.inventory.ItemStack; + +import io.github.thebusybiscuit.slimefun4.api.events.SlimefunItemSpawnEvent; +import io.github.thebusybiscuit.slimefun4.core.networks.cargo.CargoNet; +import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientPedestal; +import io.github.thebusybiscuit.slimefun4.implementation.items.seasonal.ChristmasPresent; +import io.github.thebusybiscuit.slimefun4.implementation.items.seasonal.EasterEgg; +import io.github.thebusybiscuit.slimefun4.implementation.items.tools.GoldPan; +import io.github.thebusybiscuit.slimefun4.implementation.items.tools.PickaxeOfContainment; + +/** + * This enum holds the different reasons as to why we may need to spawn an item. + * + * @author TheBusyBiscuit + * + * @see SlimefunItemSpawnEvent + * + */ +public enum ItemSpawnReason { + + /** + * The item is spawned on top of an {@link AncientPedestal}. + */ + ANCIENT_PEDESTAL_PLACE_ITEM, + + /** + * This {@link ItemStack} is dropped as a result of the {@link PickaxeOfContainment} + * breaking a monster spawner. + */ + BROKEN_SPAWNER_DROP, + + /** + * The {@link ItemStack} is dropped as the result of a {@link CargoNet} + * overflowing. + */ + CARGO_OVERFLOW, + + /** + * THe {@link ItemStack} is dropped as the result of an opened {@link ChristmasPresent}. + */ + CHRISTMAS_PRESENT_OPENED, + + /** + * THe {@link ItemStack} is dropped as the result of an opened {@link EasterEgg}. + */ + EASTER_EGG_OPENED, + + /** + * The {@link ItemStack} is dropped as the result of a {@link GoldPan} being used + * on a {@link Block} which yields drops. + */ + GOLD_PAN_USE, + + /** + * Other reasons we did not account for. + */ + MISC; + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoNetworkTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoNetworkTask.java index 4d835adf9..176c46de5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoNetworkTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoNetworkTask.java @@ -15,16 +15,19 @@ import java.util.logging.Level; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import io.github.thebusybiscuit.cscorelib2.blocks.BlockPosition; +import io.github.thebusybiscuit.slimefun4.api.items.ItemSpawnReason; import io.github.thebusybiscuit.slimefun4.core.networks.NetworkManager; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; +import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper; + import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.api.BlockStorage; @@ -140,7 +143,7 @@ class CargoNetworkTask implements Runnable { if (rest != null && !manager.isItemDeletionEnabled()) { // If the item still couldn't be inserted, simply drop it on the ground - inputTarget.getWorld().dropItem(inputTarget.getLocation().add(0, 1, 0), rest); + SlimefunUtils.spawnItem(inputTarget.getLocation().add(0, 1, 0), rest, ItemSpawnReason.CARGO_OVERFLOW); } } } else { @@ -150,7 +153,7 @@ class CargoNetworkTask implements Runnable { if (menu.getItemInSlot(previousSlot) == null) { menu.replaceExistingItem(previousSlot, item); } else if (!manager.isItemDeletionEnabled()) { - inputTarget.getWorld().dropItem(inputTarget.getLocation().add(0, 1, 0), item); + SlimefunUtils.spawnItem(inputTarget.getLocation().add(0, 1, 0), item, ItemSpawnReason.CARGO_OVERFLOW); } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/altar/AncientPedestal.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/altar/AncientPedestal.java index a302e2dae..085678fd4 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/altar/AncientPedestal.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/altar/AncientPedestal.java @@ -21,6 +21,7 @@ import org.bukkit.util.Vector; import io.github.thebusybiscuit.cscorelib2.chat.ChatColors; import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils; import io.github.thebusybiscuit.cscorelib2.item.CustomItem; +import io.github.thebusybiscuit.slimefun4.api.items.ItemSpawnReason; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockDispenseHandler; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; @@ -57,8 +58,7 @@ public class AncientPedestal extends SimpleSlimefunItem { addItemHandler(onBreak()); } - @Nonnull - private BlockBreakHandler onBreak() { + private @Nonnull BlockBreakHandler onBreak() { return new SimpleBlockBreakHandler() { @Override @@ -79,12 +79,11 @@ public class AncientPedestal extends SimpleSlimefunItem { } @Override - public BlockDispenseHandler getItemHandler() { + public @Nonnull BlockDispenseHandler getItemHandler() { return (e, d, block, machine) -> e.setCancelled(true); } - @Nonnull - public Optional getPlacedItem(@Nonnull Block pedestal) { + public @Nonnull Optional getPlacedItem(@Nonnull Block pedestal) { Location l = pedestal.getLocation().add(0.5, 1.2, 0.5); for (Entity n : l.getWorld().getNearbyEntities(l, 0.5, 0.5, 0.5, this::testItem)) { @@ -107,8 +106,7 @@ public class AncientPedestal extends SimpleSlimefunItem { } } - @Nonnull - public ItemStack getOriginalItemStack(@Nonnull Item item) { + public @Nonnull ItemStack getOriginalItemStack(@Nonnull Item item) { ItemStack stack = item.getItemStack().clone(); String customName = item.getCustomName(); @@ -142,12 +140,14 @@ public class AncientPedestal extends SimpleSlimefunItem { ItemUtils.consumeItem(hand, false); } - Item entity = b.getWorld().dropItem(b.getLocation().add(0.5, 1.2, 0.5), displayItem); - entity.setVelocity(new Vector(0, 0.1, 0)); - entity.setCustomNameVisible(true); - entity.setCustomName(nametag); - SlimefunUtils.markAsNoPickup(entity, "altar_item"); - p.playSound(b.getLocation(), Sound.ENTITY_ITEM_PICKUP, 0.3F, 0.3F); - } + Item entity = SlimefunUtils.spawnItem(b.getLocation().add(0.5, 1.2, 0.5), displayItem, ItemSpawnReason.ANCIENT_PEDESTAL_PLACE_ITEM); + if (entity != null) { + entity.setVelocity(new Vector(0, 0.1, 0)); + entity.setCustomNameVisible(true); + entity.setCustomName(nametag); + SlimefunUtils.markAsNoPickup(entity, "altar_item"); + p.playSound(b.getLocation(), Sound.ENTITY_ITEM_PICKUP, 0.3F, 0.3F); + } + } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/seasonal/ChristmasPresent.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/seasonal/ChristmasPresent.java index 54cace44f..75859e0f4 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/seasonal/ChristmasPresent.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/seasonal/ChristmasPresent.java @@ -10,10 +10,12 @@ import org.bukkit.block.Block; import org.bukkit.inventory.ItemStack; import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils; +import io.github.thebusybiscuit.slimefun4.api.items.ItemSpawnReason; import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable; import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler; import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem; import io.github.thebusybiscuit.slimefun4.utils.FireworkUtils; +import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; @@ -54,7 +56,7 @@ public class ChristmasPresent extends SimpleSlimefunItem impleme Block b = block.getRelative(e.getClickedFace()); ItemStack gift = gifts[ThreadLocalRandom.current().nextInt(gifts.length)].clone(); - b.getWorld().dropItemNaturally(b.getLocation(), gift); + SlimefunUtils.spawnItem(b.getLocation(), gift, ItemSpawnReason.CHRISTMAS_PRESENT_OPENED, true); }); }; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/seasonal/EasterEgg.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/seasonal/EasterEgg.java index 6854e5add..7741a8a4d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/seasonal/EasterEgg.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/seasonal/EasterEgg.java @@ -10,9 +10,12 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils; +import io.github.thebusybiscuit.slimefun4.api.items.ItemSpawnReason; import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler; import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem; import io.github.thebusybiscuit.slimefun4.utils.FireworkUtils; +import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; + import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; @@ -51,7 +54,7 @@ public class EasterEgg extends SimpleSlimefunItem { } FireworkUtils.launchRandom(p, 2); - p.getWorld().dropItemNaturally(p.getLocation(), gifts[ThreadLocalRandom.current().nextInt(gifts.length)].clone()); + SlimefunUtils.spawnItem(p.getLocation(), gifts[ThreadLocalRandom.current().nextInt(gifts.length)].clone(), ItemSpawnReason.EASTER_EGG_OPENED, true); }; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/GoldPan.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/GoldPan.java index f55c6444f..9038123eb 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/GoldPan.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/GoldPan.java @@ -17,6 +17,7 @@ import org.bukkit.inventory.ItemStack; import io.github.thebusybiscuit.cscorelib2.collections.RandomizedSet; import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; +import io.github.thebusybiscuit.slimefun4.api.items.ItemSpawnReason; import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem; import io.github.thebusybiscuit.slimefun4.core.handlers.EntityInteractHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler; @@ -26,6 +27,8 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunIte import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.ElectricGoldPan; import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.AutomatedPanningMachine; import io.github.thebusybiscuit.slimefun4.implementation.settings.GoldPanDrop; +import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; + import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; @@ -133,7 +136,7 @@ public class GoldPan extends SimpleSlimefunItem implements Recip // Make sure that the randomly selected item is not air if (output.getType() != Material.AIR) { - b.getWorld().dropItemNaturally(b.getLocation(), output.clone()); + SlimefunUtils.spawnItem(b.getLocation(), output.clone(), ItemSpawnReason.GOLD_PAN_USE, true); } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/PickaxeOfContainment.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/PickaxeOfContainment.java index 8bca53ecc..0d68274bc 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/PickaxeOfContainment.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/PickaxeOfContainment.java @@ -10,13 +10,16 @@ import org.bukkit.block.CreatureSpawner; import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; +import io.github.thebusybiscuit.slimefun4.api.items.ItemSpawnReason; import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem; import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.AbstractMonsterSpawner; import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.BrokenSpawner; import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.RepairedSpawner; +import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.papermc.lib.PaperLib; + import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.api.BlockStorage; @@ -41,13 +44,13 @@ public class PickaxeOfContainment extends SimpleSlimefunItem { } @Override - public ToolUseHandler getItemHandler() { + public @Nonnull ToolUseHandler getItemHandler() { return (e, tool, fortune, drops) -> { Block b = e.getBlock(); if (b.getType() == Material.SPAWNER) { ItemStack spawner = breakSpawner(b); - b.getLocation().getWorld().dropItemNaturally(b.getLocation(), spawner); + SlimefunUtils.spawnItem(b.getLocation(), spawner, ItemSpawnReason.BROKEN_SPAWNER_DROP, true); e.setExpToDrop(0); e.setDropItems(false); @@ -55,8 +58,7 @@ public class PickaxeOfContainment extends SimpleSlimefunItem { }; } - @Nonnull - private ItemStack breakSpawner(@Nonnull Block b) { + private @Nonnull ItemStack breakSpawner(@Nonnull Block b) { AbstractMonsterSpawner spawner; /** diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AutoCrafterListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AutoCrafterListener.java index 661a489f6..73d5b66fb 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AutoCrafterListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AutoCrafterListener.java @@ -2,7 +2,6 @@ package io.github.thebusybiscuit.slimefun4.implementation.listeners; import java.util.Optional; -import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; import org.bukkit.GameRule; @@ -20,7 +19,9 @@ import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.items.autocrafters.AbstractAutoCrafter; import io.github.thebusybiscuit.slimefun4.implementation.items.autocrafters.EnhancedAutoCrafter; +import io.github.thebusybiscuit.slimefun4.implementation.items.autocrafters.VanillaAutoCrafter; import io.github.thebusybiscuit.slimefun4.implementation.items.electric.gadgets.Multimeter; + import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; /** @@ -30,6 +31,9 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; * This {@link Listener} resolves that issue. * * @author TheBusyBiscuit + * @author LilBC + * + * @see VanillaAutoCrafter * @see EnhancedAutoCrafter */ public class AutoCrafterListener implements Listener { @@ -39,15 +43,6 @@ public class AutoCrafterListener implements Listener { plugin.getServer().getPluginManager().registerEvents(this, plugin); } - private boolean hasUnlockedRecipe(@Nonnull Player p, @Nonnull ItemStack item) { - for (Recipe recipe : SlimefunPlugin.getMinecraftRecipeService().getRecipesFor(item)) { - if (recipe instanceof Keyed && !p.hasDiscoveredRecipe(((Keyed) recipe).getKey())) { - return false; - } - } - return true; - } - @EventHandler public void onInteract(PlayerRightClickEvent e) { Optional clickedBlock = e.getClickedBlock(); @@ -74,10 +69,15 @@ public class AutoCrafterListener implements Listener { // Prevent blocks from being placed, food from being eaten, etc... e.cancel(); - // Check if the recipe of the item is disabled. - if (e.getPlayer().getWorld().getGameRuleValue(GameRule.DO_LIMITED_CRAFTING) && !hasUnlockedRecipe(e.getPlayer(), e.getItem())) { - SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.auto-crafting.recipe-unavailable"); - return; + // Check for the "doLimitedCrafting" gamerule when using a Vanilla Auto-Crafter + if (block instanceof VanillaAutoCrafter) { + boolean doLimitedCrafting = e.getPlayer().getWorld().getGameRuleValue(GameRule.DO_LIMITED_CRAFTING); + + // Check if the recipe of the item is disabled. + if (doLimitedCrafting && !hasUnlockedRecipe(e.getPlayer(), e.getItem())) { + SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.auto-crafting.recipe-unavailable"); + return; + } } // Fixes 2896 - Forward the interaction before items get handled. @@ -91,4 +91,15 @@ public class AutoCrafterListener implements Listener { } } } + + @ParametersAreNonnullByDefault + private boolean hasUnlockedRecipe(Player p, ItemStack item) { + for (Recipe recipe : SlimefunPlugin.getMinecraftRecipeService().getRecipesFor(item)) { + if (recipe instanceof Keyed && !p.hasDiscoveredRecipe(((Keyed) recipe).getKey())) { + return false; + } + } + + return true; + } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java index 75d376d36..a0367550d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java @@ -8,6 +8,7 @@ import java.util.Optional; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; import org.apache.commons.lang.Validate; import org.bukkit.ChatColor; @@ -27,13 +28,16 @@ import org.bukkit.persistence.PersistentDataType; import io.github.thebusybiscuit.cscorelib2.item.ImmutableItemMeta; import io.github.thebusybiscuit.cscorelib2.skull.SkullItem; import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; +import io.github.thebusybiscuit.slimefun4.api.events.SlimefunItemSpawnEvent; import io.github.thebusybiscuit.slimefun4.api.exceptions.PrematureCodeException; +import io.github.thebusybiscuit.slimefun4.api.items.ItemSpawnReason; import io.github.thebusybiscuit.slimefun4.core.attributes.Radioactive; import io.github.thebusybiscuit.slimefun4.core.attributes.Soulbound; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientPedestal; import io.github.thebusybiscuit.slimefun4.implementation.tasks.CapacitorTextureUpdateTask; import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper; + import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; @@ -403,4 +407,57 @@ public final class SlimefunUtils { } } + /** + * Helper method to spawn an {@link ItemStack}. + * This method automatically calls a {@link SlimefunItemSpawnEvent} to allow + * other plugins to catch the item being dropped. + * + * @param loc + * The {@link Location} where to drop the item + * @param item + * The {@link ItemStack} to drop + * @param reason + * The {@link ItemSpawnReason} why the item is being dropped + * @param addRandomOffset + * Whether a random offset should be added (see {@link World#dropItemNaturally(Location, ItemStack)}) + * + * @return The dropped {@link Item} (or null if the {@link SlimefunItemSpawnEvent} was cancelled) + */ + @ParametersAreNonnullByDefault + public static @Nullable Item spawnItem(Location loc, ItemStack item, ItemSpawnReason reason, boolean addRandomOffset) { + SlimefunItemSpawnEvent event = new SlimefunItemSpawnEvent(loc, item, reason); + SlimefunPlugin.instance().getServer().getPluginManager().callEvent(event); + + if (!event.isCancelled()) { + World world = event.getLocation().getWorld(); + + if (addRandomOffset) { + return world.dropItemNaturally(event.getLocation(), event.getItemStack()); + } else { + return world.dropItem(event.getLocation(), event.getItemStack()); + } + } else { + return null; + } + } + + /** + * Helper method to spawn an {@link ItemStack}. + * This method automatically calls a {@link SlimefunItemSpawnEvent} to allow + * other plugins to catch the item being dropped. + * + * @param loc + * The {@link Location} where to drop the item + * @param item + * The {@link ItemStack} to drop + * @param reason + * The {@link ItemSpawnReason} why the item is being dropped + * + * @return The dropped {@link Item} (or null if the {@link SlimefunItemSpawnEvent} was cancelled) + */ + @ParametersAreNonnullByDefault + public static @Nullable Item spawnItem(Location loc, ItemStack item, ItemSpawnReason reason) { + return spawnItem(loc, item, reason, false); + } + }