From 39fe3121f8d18fa8b6b2a3d50812f8a166527bf2 Mon Sep 17 00:00:00 2001 From: ybw0014 Date: Wed, 22 Nov 2023 21:32:29 -0500 Subject: [PATCH] Merge upstream (#44) * e2e testing initial * Setup matrix * Download tester * Jeff's changes * capitalized Chosen * Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.1 * fix breaking sf block with not unlocked item duping contents (#3976) * [CI skip] Update actions/setup-java action to v3.13.0 * [CI skip] Update dependency me.clip:placeholderapi to v2.11.4 * [CI skip] Update actions/checkout action to v4 * [CI skip] Update dependency com.github.LoneDev6:itemsadder-api to v3.5.0c-r5 * [CI skip] Update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.6.0 * [CI skip] Update dependency org.sonarsource.scanner.maven:sonar-maven-plugin to v3.10.0.2594 * [CI skip] Update dependency com.sk89q.worldedit:worldedit-core to v7.2.16 * [CI skip] Update dependency com.sk89q.worldedit:worldedit-bukkit to v7.2.16 * [CI skip] Update dependency com.gmail.nossr50.mcMMO:mcMMO to v2.1.224 * [CI skip] Update dependency org.mockito:mockito-core to v5.6.0 * updated dough version (#3991) * [CI skip] Update dependency com.github.LoneDev6:itemsadder-api to v3.6.1 * [CI skip] Update dependency com.sk89q.worldedit:worldedit-core to v7.2.17 * [CI skip] Update dependency com.sk89q.worldedit:worldedit-bukkit to v7.2.17 * [CI skip] Update dependency com.gmail.nossr50.mcMMO:mcMMO to v2.1.225 * [CI skip] Update dependency org.jacoco:jacoco-maven-plugin to v0.8.11 * [CI skip] Update actions/checkout action to v4.1.1 * [CI skip] Update thollander/actions-comment-pull-request action to v2.4.3 * [CI skip] Update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.2.1 * [CI skip] Update dependency me.clip:placeholderapi to v2.11.5 * Update .github/workflows/e2e-testing.yml * Update .github/workflows/e2e-testing.yml * Update .github/workflows/e2e-testing.yml * Update .github/workflows/e2e-testing.yml * Add MultiBlockCraftEvent (Updated version of #3439) (#3928) * fix taking damage on head collision while wearing elytra cap (#3760) * Remove Lore Check from Slimefun Guide (#3969) * don't consume bookbinder inputs if the output is worse than the input (#3925) Co-authored-by: Jeroen * Update .github/workflows/e2e-testing.yml * Update .github/workflows/e2e-testing.yml * fix heads showing as steve (#4027) * fix: clean up issues after merging * chore(style): apply code style --------- Co-authored-by: Jeffrey Co-authored-by: Daniel Walsh Co-authored-by: iTwins Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jeroen <48769316+iTwins@users.noreply.github.com> Co-authored-by: TheBusyBiscuit Co-authored-by: J3fftw <44972470+J3fftw1@users.noreply.github.com> Co-authored-by: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Co-authored-by: Jeroen Co-authored-by: Alessio Colombo <37039432+Sfiguz7@users.noreply.github.com> --- .github/workflows/e2e-testing.yml | 71 +++++++++++ .../api/events/MultiBlockCraftEvent.java | 118 ++++++++++++++++++ .../machines/enchanting/BookBinder.java | 25 ++++ .../items/multiblocks/AbstractSmeltery.java | 8 +- .../items/multiblocks/ArmorForge.java | 8 +- .../multiblocks/AutomatedPanningMachine.java | 16 ++- .../items/multiblocks/Compressor.java | 10 +- .../multiblocks/EnhancedCraftingTable.java | 8 +- .../items/multiblocks/GrindStone.java | 10 +- .../items/multiblocks/Juicer.java | 10 +- .../items/multiblocks/MagicWorkbench.java | 8 +- .../items/multiblocks/OreCrusher.java | 8 +- .../items/multiblocks/OreWasher.java | 34 +++-- .../items/multiblocks/PressureChamber.java | 10 +- .../items/multiblocks/TableSaw.java | 11 +- .../listeners/ElytraImpactListener.java | 56 ++++++--- .../listeners/SlimefunGuideListener.java | 2 +- 17 files changed, 365 insertions(+), 48 deletions(-) create mode 100644 .github/workflows/e2e-testing.yml create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/api/events/MultiBlockCraftEvent.java diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml new file mode 100644 index 0000000000..1033765601 --- /dev/null +++ b/.github/workflows/e2e-testing.yml @@ -0,0 +1,71 @@ +name: End to End Testing + +on: + workflow_call: + inputs: + artifact-name: + description: 'Slimefun artifact name' + required: true + type: string + +jobs: + e2e-testing: + name: End to End Testing + runs-on: ubuntu-latest + timeout-minutes: 5 + + strategy: + matrix: + include: + - mcVersion: '1.16.5' + javaVersion: '16' + - mcVersion: '1.17.1' + javaVersion: '17' + - mcVersion: '1.18.2' + javaVersion: '18' + - mcVersion: '1.19.4' + javaVersion: '19' + - mcVersion: '1.20.1' + javaVersion: '20' + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up JDK + uses: actions/setup-java@v3.11.0 + with: + distribution: temurin + java-version: ${{ matrix.javaVersion }} + java-package: jdk + architecture: x64 + + - name: Setup server + run: | + echo 'eula=true' > eula.txt + mkdir plugins + + - name: Download ${{ matrix.mcVersion }} Paper + run: | + VERSION="${{ matrix.mcVersion }}" + BUILD_JAR=$(curl -s "https://api.papermc.io/v2/projects/paper/versions/$VERSION/builds" \ + | jq '.builds[-1] | "\(.build) \(.downloads.application.name)"' -r) + BUILD=$(echo "$BUILD_JAR" | awk '{print $1}') + JAR_FILE=$(echo "$BUILD_JAR" | awk '{print $2}') + curl -o paper.jar \ + "https://api.papermc.io/v2/projects/paper/versions/$VERSION/builds/$BUILD/downloads/$JAR_FILE" + + - name: Download Slimefun + uses: actions/download-artifact@v3 + with: + name: ${{ inputs.artifact-name }} + path: plugins/ + + - name: Download e2e-tester + run: | + curl -o e2e-tester.jar https://preview-builds.walshy.dev/download/e2e-tester/main/latest + mv e2e-tester.jar plugins/e2e-tester.jar + + - name: Run server + run: | + java -jar paper.jar --nogui diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/MultiBlockCraftEvent.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/MultiBlockCraftEvent.java new file mode 100644 index 0000000000..3063589a95 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/MultiBlockCraftEvent.java @@ -0,0 +1,118 @@ +package io.github.thebusybiscuit.slimefun4.api.events; + +import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlockMachine; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.bukkit.inventory.ItemStack; + +/** + * This {@link Event} is called when a {@link Player} crafts an item using a {@link MultiBlockMachine}. + * Unlike the {@link MultiBlockInteractEvent}, this event only fires if an output to a craft is expected. + * If this event is cancelled, ingredients will not be consumed and no output item results. + * + * @author char321 + * @author JustAHuman + */ +public class MultiBlockCraftEvent extends PlayerEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + + private final MultiBlockMachine machine; + private final ItemStack[] input; + private ItemStack output; + private boolean cancelled; + + /** + * Creates a new {@link MultiBlockCraftEvent}. + * + * @param p The player that crafts using a multiblock + * @param machine The multiblock machine used to craft + * @param input The input items of the craft + * @param output The resulting item of the craft + */ + @ParametersAreNonnullByDefault + public MultiBlockCraftEvent(Player p, MultiBlockMachine machine, ItemStack[] input, ItemStack output) { + super(p); + this.machine = machine; + this.input = input; + this.output = output; + } + + /** + * Creates a new {@link MultiBlockCraftEvent}. + * + * @param p The player that crafts using a multiblock + * @param machine The multiblock machine used to craft + * @param input The input item of the craft + * @param output The resulting item of the craft + */ + @ParametersAreNonnullByDefault + public MultiBlockCraftEvent(Player p, MultiBlockMachine machine, ItemStack input, ItemStack output) { + this(p, machine, new ItemStack[] {input}, output); + } + + /** + * Gets the machine that was used to craft. + * + * @return The {@link MultiBlockMachine} used to craft. + */ + public @Nonnull MultiBlockMachine getMachine() { + return machine; + } + + /** + * Gets the input of the craft. + * + * @return The {@link ItemStack ItemStack[]} input that is used in the craft. + */ + public @Nonnull ItemStack[] getInput() { + return input; + } + + /** + * Gets the output of the craft. + * + * @return The {@link ItemStack} output that results from the craft. + */ + public @Nonnull ItemStack getOutput() { + return output; + } + + /** + * Sets the output of the craft. Keep in mind that this overwrites any existing output. + * + * @param output + * The new item for the event to produce. + * + * @return The previous {@link ItemStack} output that was replaced. + */ + public @Nullable ItemStack setOutput(@Nullable ItemStack output) { + ItemStack oldOutput = this.output; + this.output = output; + return oldOutput; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + public static @Nonnull HandlerList getHandlerList() { + return handlers; + } + + @Override + public @Nonnull HandlerList getHandlers() { + return getHandlerList(); + } +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/enchanting/BookBinder.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/enchanting/BookBinder.java index 824e4608ba..07cf5628d5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/enchanting/BookBinder.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/enchanting/BookBinder.java @@ -56,6 +56,10 @@ protected MachineRecipe findNextRecipe(BlockMenu menu) { // Just return if no enchantments exist. This shouldn't ever happen. :NotLikeThis: if (enchantments.size() > 0) { + if (hasIllegalEnchants(storedItemEnchantments) || hasIllegalEnchants(storedTargetEnchantments)) { + return null; + } + ItemStack book = new ItemStack(Material.ENCHANTED_BOOK); EnchantmentStorageMeta enchantMeta = (EnchantmentStorageMeta) book.getItemMeta(); @@ -70,6 +74,12 @@ protected MachineRecipe findNextRecipe(BlockMenu menu) { return null; } + // If the output is the same as one of the inputs: don't consume items + if (enchantMeta.getStoredEnchants().equals(storedItemEnchantments) + || enchantMeta.getStoredEnchants().equals(storedTargetEnchantments)) { + return null; + } + book.setItemMeta(enchantMeta); MachineRecipe recipe = new MachineRecipe( @@ -99,6 +109,21 @@ private boolean isCompatible(@Nullable ItemStack item) { return item != null && item.getType() == Material.ENCHANTED_BOOK; } + private boolean hasIllegalEnchants(@Nullable Map enchantments) { + if (enchantments == null) { + return false; + } + + for (Map.Entry entry : enchantments.entrySet()) { + if (bypassVanillaMaxLevel.getValue() && entry.getValue() > customMaxLevel.getValue() + || !bypassVanillaMaxLevel.getValue() + && entry.getValue() > entry.getKey().getMaxLevel()) { + return true; + } + } + return false; + } + @Override public ItemStack getProgressBar() { return new ItemStack(Material.IRON_CHESTPLATE); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/AbstractSmeltery.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/AbstractSmeltery.java index ce89f51820..af55819166 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/AbstractSmeltery.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/AbstractSmeltery.java @@ -1,6 +1,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks; import io.github.bakedlibs.dough.inventory.InvUtils; +import io.github.thebusybiscuit.slimefun4.api.events.MultiBlockCraftEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; @@ -11,6 +12,7 @@ import io.papermc.lib.PaperLib; import java.util.List; import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -46,12 +48,14 @@ public void onInteract(Player p, Block b) { if (canCraft(inv, inputs, i)) { ItemStack output = RecipeType.getRecipeOutputList(this, inputs.get(i)).clone(); + MultiBlockCraftEvent event = new MultiBlockCraftEvent(p, this, inputs.get(i), output); - if (SlimefunUtils.canPlayerUseItem(p, output, true)) { + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled() && SlimefunUtils.canPlayerUseItem(p, output, true)) { Inventory outputInv = findOutputInventory(output, possibleDispenser, inv); if (outputInv != null) { - craft(p, b, inv, inputs.get(i), output, outputInv); + craft(p, b, inv, inputs.get(i), event.getOutput(), outputInv); } else { Slimefun.getLocalization().sendMessage(p, "machines.full-inventory", true); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/ArmorForge.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/ArmorForge.java index a61d5a37e9..c2b045439f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/ArmorForge.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/ArmorForge.java @@ -2,6 +2,7 @@ import io.github.bakedlibs.dough.items.CustomItemStack; import io.github.bakedlibs.dough.items.ItemUtils; +import io.github.thebusybiscuit.slimefun4.api.events.MultiBlockCraftEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; @@ -11,6 +12,7 @@ import io.papermc.lib.PaperLib; import java.util.List; import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -54,9 +56,11 @@ public void onInteract(Player p, Block b) { if (isCraftable(inv, input)) { ItemStack output = RecipeType.getRecipeOutputList(this, input).clone(); + MultiBlockCraftEvent event = new MultiBlockCraftEvent(p, this, input, output); - if (SlimefunUtils.canPlayerUseItem(p, output, true)) { - craft(p, output, inv, possibleDispenser); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled() && SlimefunUtils.canPlayerUseItem(p, output, true)) { + craft(p, event.getOutput(), inv, possibleDispenser); } return; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/AutomatedPanningMachine.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/AutomatedPanningMachine.java index 574b128671..7b5e9a1c96 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/AutomatedPanningMachine.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/AutomatedPanningMachine.java @@ -2,6 +2,7 @@ import io.github.bakedlibs.dough.items.ItemUtils; import io.github.bakedlibs.dough.scheduling.TaskQueue; +import io.github.thebusybiscuit.slimefun4.api.events.MultiBlockCraftEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlockMachine; @@ -16,6 +17,7 @@ import java.util.Optional; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.GameMode; import org.bukkit.Material; @@ -85,6 +87,14 @@ public void onInteract(Player p, Block b) { return; } + MultiBlockCraftEvent event = new MultiBlockCraftEvent(p, this, input, output); + + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + + ItemStack finalOutput = event.getOutput(); if (p.getGameMode() != GameMode.CREATIVE) { ItemUtils.consumeItem(input, false); } @@ -94,13 +104,13 @@ public void onInteract(Player p, Block b) { queue.thenRepeatEvery(20, 5, () -> b.getWorld() .playEffect(b.getRelative(BlockFace.DOWN).getLocation(), Effect.STEP_SOUND, material)); queue.thenRun(20, () -> { - if (output.getType() != Material.AIR) { + if (finalOutput.getType() != Material.AIR) { Optional outputChest = OutputChest.findOutputChestFor(b.getRelative(BlockFace.DOWN), output); if (outputChest.isPresent()) { - outputChest.get().addItem(output.clone()); + outputChest.get().addItem(finalOutput.clone()); } else { - b.getWorld().dropItemNaturally(b.getLocation(), output.clone()); + b.getWorld().dropItemNaturally(b.getLocation(), finalOutput.clone()); } SoundEffect.AUTOMATED_PANNING_MACHINE_SUCCESS_SOUND.playAt(b); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/Compressor.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/Compressor.java index f757c51c69..e9384e0545 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/Compressor.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/Compressor.java @@ -1,6 +1,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks; import io.github.bakedlibs.dough.items.CustomItemStack; +import io.github.thebusybiscuit.slimefun4.api.events.MultiBlockCraftEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; @@ -14,6 +15,7 @@ import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -77,13 +79,19 @@ public void onInteract(Player p, Block b) { if (recipeInput != null && SlimefunUtils.isItemSimilar(item, recipeInput, true)) { ItemStack output = RecipeType.getRecipeOutput(this, recipeInput); Inventory outputInv = findOutputInventory(output, dispBlock, inv); + MultiBlockCraftEvent event = new MultiBlockCraftEvent(p, this, item, output); + + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } if (outputInv != null) { ItemStack removing = item.clone(); removing.setAmount(recipeInput.getAmount()); inv.removeItem(removing); - craft(p, output, dispBlock, inv); + craft(p, event.getOutput(), dispBlock, inv); } else { Slimefun.getLocalization().sendMessage(p, "machines.full-inventory", true); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/EnhancedCraftingTable.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/EnhancedCraftingTable.java index 797ead74c2..7c3fa933a6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/EnhancedCraftingTable.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/EnhancedCraftingTable.java @@ -1,6 +1,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks; import io.github.bakedlibs.dough.items.ItemUtils; +import io.github.thebusybiscuit.slimefun4.api.events.MultiBlockCraftEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; @@ -12,6 +13,7 @@ import io.papermc.lib.PaperLib; import java.util.List; import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -55,9 +57,11 @@ public void onInteract(Player p, Block b) { if (isCraftable(inv, input)) { ItemStack output = RecipeType.getRecipeOutputList(this, input).clone(); + MultiBlockCraftEvent event = new MultiBlockCraftEvent(p, this, input, output); - if (SlimefunUtils.canPlayerUseItem(p, output, true)) { - craft(inv, possibleDispenser, p, b, output); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled() && SlimefunUtils.canPlayerUseItem(p, output, true)) { + craft(inv, possibleDispenser, p, b, event.getOutput()); } return; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/GrindStone.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/GrindStone.java index 9a98351aeb..680708ebe5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/GrindStone.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/GrindStone.java @@ -2,6 +2,7 @@ import io.github.bakedlibs.dough.items.CustomItemStack; import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; +import io.github.thebusybiscuit.slimefun4.api.events.MultiBlockCraftEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; @@ -15,6 +16,7 @@ import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -137,12 +139,18 @@ public void onInteract(Player p, Block b) { if (convert != null && SlimefunUtils.isItemSimilar(current, convert, true)) { ItemStack output = RecipeType.getRecipeOutput(this, convert); Inventory outputInv = findOutputInventory(output, possibleDispenser, inv); + MultiBlockCraftEvent event = new MultiBlockCraftEvent(p, this, current, output); + + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } if (outputInv != null) { ItemStack removing = current.clone(); removing.setAmount(1); inv.removeItem(removing); - outputInv.addItem(output); + outputInv.addItem(event.getOutput()); SoundEffect.GRIND_STONE_INTERACT_SOUND.playAt(b); } else { Slimefun.getLocalization().sendMessage(p, "machines.full-inventory", true); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/Juicer.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/Juicer.java index 2ba5f35b5a..31625e4247 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/Juicer.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/Juicer.java @@ -1,6 +1,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks; import io.github.bakedlibs.dough.items.CustomItemStack; +import io.github.thebusybiscuit.slimefun4.api.events.MultiBlockCraftEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; @@ -14,6 +15,7 @@ import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; import org.bukkit.block.Block; @@ -73,12 +75,18 @@ public void onInteract(Player p, Block b) { if (convert != null && SlimefunUtils.isItemSimilar(current, convert, true)) { ItemStack adding = RecipeType.getRecipeOutput(this, convert); Inventory outputInv = findOutputInventory(adding, possibleDispenser, inv); + MultiBlockCraftEvent event = new MultiBlockCraftEvent(p, this, current, adding); + + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } if (outputInv != null) { ItemStack removing = current.clone(); removing.setAmount(1); inv.removeItem(removing); - outputInv.addItem(adding); + outputInv.addItem(event.getOutput()); SoundEffect.JUICER_USE_SOUND.playAt(b); // Not changed since this is supposed to be a natural sound. diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/MagicWorkbench.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/MagicWorkbench.java index 89de2281c5..f175630c9d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/MagicWorkbench.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/MagicWorkbench.java @@ -1,6 +1,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks; import io.github.bakedlibs.dough.items.CustomItemStack; +import io.github.thebusybiscuit.slimefun4.api.events.MultiBlockCraftEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; @@ -12,6 +13,7 @@ import io.papermc.lib.PaperLib; import java.util.List; import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; import org.bukkit.block.Block; @@ -62,9 +64,11 @@ public void onInteract(Player p, Block b) { if (isCraftable(inv, input)) { ItemStack output = RecipeType.getRecipeOutputList(this, input).clone(); + MultiBlockCraftEvent event = new MultiBlockCraftEvent(p, this, input, output); - if (SlimefunUtils.canPlayerUseItem(p, output, true)) { - craft(inv, possibleDispener, p, b, output); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled() && SlimefunUtils.canPlayerUseItem(p, output, true)) { + craft(inv, possibleDispener, p, b, event.getOutput()); } return; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/OreCrusher.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/OreCrusher.java index 859880cb31..91020690ee 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/OreCrusher.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/OreCrusher.java @@ -2,6 +2,7 @@ import io.github.bakedlibs.dough.items.CustomItemStack; import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; +import io.github.thebusybiscuit.slimefun4.api.events.MultiBlockCraftEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; @@ -17,6 +18,7 @@ import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; import org.bukkit.block.Block; @@ -199,13 +201,15 @@ public void onInteract(Player p, Block b) { if (convert != null && SlimefunUtils.isItemSimilar(current, convert, true)) { ItemStack adding = RecipeType.getRecipeOutput(this, convert); Inventory outputInv = findOutputInventory(adding, possibleDispenser, inv); + MultiBlockCraftEvent event = new MultiBlockCraftEvent(p, this, current, adding); - if (SlimefunUtils.canPlayerUseItem(p, adding, true)) { + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled() && SlimefunUtils.canPlayerUseItem(p, adding, true)) { if (outputInv != null) { ItemStack removing = current.clone(); removing.setAmount(convert.getAmount()); inv.removeItem(removing); - outputInv.addItem(adding); + outputInv.addItem(event.getOutput()); p.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, 1); } else { Slimefun.getLocalization().sendMessage(p, "machines.full-inventory", true); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/OreWasher.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/OreWasher.java index 61498aff51..9ccf8105df 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/OreWasher.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/OreWasher.java @@ -1,5 +1,6 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks; +import io.github.thebusybiscuit.slimefun4.api.events.MultiBlockCraftEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlockMachine; @@ -10,10 +11,10 @@ import io.papermc.lib.PaperLib; import java.util.List; import java.util.concurrent.ThreadLocalRandom; -import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; import org.bukkit.block.Block; @@ -85,8 +86,8 @@ protected void registerDefaultRecipes(List recipes) { } @Override - public List getDisplayRecipes() { - return recipes.stream().map(items -> items[0]).collect(Collectors.toList()); + public @Nonnull List getDisplayRecipes() { + return recipes.stream().map(items -> items[0]).toList(); } @Override @@ -94,15 +95,14 @@ public void onInteract(Player p, Block b) { Block dispBlock = b.getRelative(BlockFace.UP); BlockState state = PaperLib.getBlockState(dispBlock, false).getState(); - if (state instanceof Dispenser) { - Dispenser disp = (Dispenser) state; + if (state instanceof Dispenser disp) { Inventory inv = disp.getInventory(); for (ItemStack input : inv.getContents()) { if (input != null) { if (SlimefunUtils.isItemSimilar(input, SlimefunItems.SIFTED_ORE, true)) { ItemStack output = getRandomDust(); - Inventory outputInv = null; + Inventory outputInv; if (!legacyMode) { /* @@ -120,7 +120,12 @@ public void onInteract(Player p, Block b) { outputInv = findOutputInventory(output, dispBlock, inv); } - removeItem(p, b, inv, outputInv, input, output, 1); + MultiBlockCraftEvent event = new MultiBlockCraftEvent(p, this, input, output); + if (event.isCancelled()) { + return; + } + + removeItem(p, b, inv, outputInv, input, event.getOutput(), 1); if (outputInv != null) { outputInv.addItem(SlimefunItems.STONE_CHUNK); @@ -131,14 +136,25 @@ public void onInteract(Player p, Block b) { ItemStack output = SlimefunItems.SALT; Inventory outputInv = findOutputInventory(output, dispBlock, inv); - removeItem(p, b, inv, outputInv, input, output, 2); + MultiBlockCraftEvent event = new MultiBlockCraftEvent(p, this, input, output); + if (event.isCancelled()) { + return; + } + + removeItem(p, b, inv, outputInv, input, event.getOutput(), 2); return; } else if (SlimefunUtils.isItemSimilar(input, SlimefunItems.PULVERIZED_ORE, true)) { ItemStack output = SlimefunItems.PURE_ORE_CLUSTER; Inventory outputInv = findOutputInventory(output, dispBlock, inv); + MultiBlockCraftEvent event = new MultiBlockCraftEvent(p, this, input, output); + + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } - removeItem(p, b, inv, outputInv, input, output, 1); + removeItem(p, b, inv, outputInv, input, event.getOutput(), 1); return; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/PressureChamber.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/PressureChamber.java index c4ba4d5c54..22c96fe511 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/PressureChamber.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/PressureChamber.java @@ -1,6 +1,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks; import io.github.bakedlibs.dough.items.CustomItemStack; +import io.github.thebusybiscuit.slimefun4.api.events.MultiBlockCraftEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; @@ -13,6 +14,7 @@ import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; import org.bukkit.block.Block; @@ -62,13 +64,19 @@ public void onInteract(Player p, Block b) { if (convert != null && SlimefunUtils.isItemSimilar(current, convert, true)) { ItemStack output = RecipeType.getRecipeOutput(this, convert); Inventory outputInv = findOutputInventory(output, possibleDispenser, inv); + MultiBlockCraftEvent event = new MultiBlockCraftEvent(p, this, current, output); + + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } if (outputInv != null) { ItemStack removing = current.clone(); removing.setAmount(convert.getAmount()); inv.removeItem(removing); - craft(p, b, output, inv, possibleDispenser); + craft(p, b, event.getOutput(), inv, possibleDispenser); } else { Slimefun.getLocalization().sendMessage(p, "machines.full-inventory", true); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/TableSaw.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/TableSaw.java index eae941a80a..80d758177e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/TableSaw.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/TableSaw.java @@ -1,6 +1,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks; import io.github.bakedlibs.dough.items.ItemUtils; +import io.github.thebusybiscuit.slimefun4.api.events.MultiBlockCraftEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; @@ -14,6 +15,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.GameMode; import org.bukkit.Material; @@ -125,11 +127,18 @@ public void onInteract(@Nonnull Player p, @Nonnull Block b) { return; } + MultiBlockCraftEvent event = new MultiBlockCraftEvent(p, this, item, output); + + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + if (p.getGameMode() != GameMode.CREATIVE) { ItemUtils.consumeItem(item, true); } - outputItems(b, output); + outputItems(b, event.getOutput()); b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, item.getType()); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ElytraImpactListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ElytraImpactListener.java index 11cd5a557f..2d8fdfdc4f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ElytraImpactListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ElytraImpactListener.java @@ -7,59 +7,75 @@ import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import io.github.thebusybiscuit.slimefun4.implementation.items.armor.ElytraCap; import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece; +import java.util.HashSet; import java.util.Optional; +import java.util.Set; +import java.util.UUID; import javax.annotation.Nonnull; import org.bukkit.Sound; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityToggleGlideEvent; /** * The {@link Listener} for the {@link ElytraCap}. * * @author Seggan + * @author J3fftw1 * * @see ElytraCap */ public class ElytraImpactListener implements Listener { + private final Set gliding = new HashSet<>(); + public ElytraImpactListener(@Nonnull Slimefun plugin) { plugin.getServer().getPluginManager().registerEvents(this, plugin); } + @EventHandler + public void onGlideToggle(EntityToggleGlideEvent event) { + Entity entity = event.getEntity(); + if (entity instanceof Player player && player.isGliding()) { + UUID uuid = player.getUniqueId(); + gliding.add(uuid); + } + // We tick 1 tick later because the player is being toggled of at the same tick as it takes damage. + Slimefun.instance().getServer().getScheduler().runTaskLater(Slimefun.instance(), gliding::clear, 1); + } + @EventHandler public void onPlayerCrash(EntityDamageEvent e) { - if (!(e.getEntity() instanceof Player)) { + if (!(e.getEntity() instanceof Player p)) { // We only wanna handle damaged Players return; } - if (e.getCause() == DamageCause.FALL || e.getCause() == DamageCause.FLY_INTO_WALL) { - Player p = (Player) e.getEntity(); - - if (p.isGliding()) { - Optional optional = PlayerProfile.find(p); + if ((e.getCause() == DamageCause.FALL || e.getCause() == DamageCause.FLY_INTO_WALL) + && (p.isGliding() || gliding.contains(p.getUniqueId()))) { + Optional optional = PlayerProfile.find(p); - if (!optional.isPresent()) { - PlayerProfile.request(p); - return; - } + if (!optional.isPresent()) { + PlayerProfile.request(p); + return; + } - PlayerProfile profile = optional.get(); - Optional helmet = profile.getArmor()[0].getItem(); + PlayerProfile profile = optional.get(); + Optional helmet = profile.getArmor()[3].getItem(); - if (helmet.isPresent()) { - SlimefunItem item = helmet.get(); + if (helmet.isPresent()) { + SlimefunItem item = helmet.get(); - if (item.canUse(p, true) && profile.hasFullProtectionAgainst(ProtectionType.FLYING_INTO_WALL)) { - e.setDamage(0); - p.playSound(p.getLocation(), Sound.BLOCK_STONE_HIT, 20, 1); + if (item.canUse(p, true) && profile.hasFullProtectionAgainst(ProtectionType.FLYING_INTO_WALL)) { + e.setDamage(0); + p.playSound(p.getLocation(), Sound.BLOCK_STONE_HIT, 20, 1); - if (item instanceof DamageableItem damageableItem) { - damageableItem.damageItem(p, p.getInventory().getHelmet()); - } + if (item instanceof DamageableItem damageableItem) { + damageableItem.damageItem(p, p.getInventory().getHelmet()); } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunGuideListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunGuideListener.java index 99dea640a6..0cdf2329e5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunGuideListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunGuideListener.java @@ -83,7 +83,7 @@ private void openGuide(Player p, PlayerRightClickEvent e, SlimefunGuideMode layo @ParametersAreNonnullByDefault private Result tryOpenGuide(Player p, PlayerRightClickEvent e, SlimefunGuideMode layout) { ItemStack item = e.getItem(); - if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(layout), true, false)) { + if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(layout), false, false)) { if (!Slimefun.getWorldSettingsService().isWorldEnabled(p.getWorld())) { Slimefun.getLocalization().sendMessage(p, "messages.disabled-item", true);