From f21d28fa3539ba9c847e3f8078496050757b052f Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Fri, 30 Jun 2023 23:59:50 +0200 Subject: [PATCH 001/131] e2e testing initial --- .github/workflows/e2e-testing.yml | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .github/workflows/e2e-testing.yml diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml new file mode 100644 index 0000000000..ebbb01a43c --- /dev/null +++ b/.github/workflows/e2e-testing.yml @@ -0,0 +1,44 @@ +name: End to End Testing + +on: workflow_call + +jobs: + e2e-testing: + + name: End to End Testing + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v3.11.0 + with: + distribution: 'adopt' + java-version: '17' + java-package: jdk + architecture: x64 + + - name: Download latest paper + run: | + VERSION=$(curl -s https://api.papermc.io/v2/projects/paper | jq '.versions[-1]' -r) + 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: Setup server + run: | + echo 'eula=true' > eula.txt + mkdir plugins + + - uses: actions/download-artifact@v3 + with: + name: slimefun-${{ github.event.number }} + path: plugins/ + + - name: Run server + run: | + java -jar paper.jar --nogui From c579d87aeed2532504c9c38a0b65bed4fc337626 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Sun, 2 Jul 2023 12:09:51 +0100 Subject: [PATCH 002/131] Setup matrix --- .github/workflows/e2e-testing.yml | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index ebbb01a43c..57f021ff99 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -9,6 +9,20 @@ jobs: 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 @@ -16,18 +30,20 @@ jobs: - name: Set up JDK 17 uses: actions/setup-java@v3.11.0 with: - distribution: 'adopt' - java-version: '17' + distribution: temurin + java-version: ${{ matrix.javaVersion }} java-package: jdk architecture: x64 - - name: Download latest paper + - name: Download ${{ matrix.mcVersion }} Paper run: | - VERSION=$(curl -s https://api.papermc.io/v2/projects/paper | jq '.versions[-1]' -r) - BUILD_JAR=$(curl -s "https://api.papermc.io/v2/projects/paper/versions/$VERSION/builds" | jq '.builds[-1] | "\(.build) \(.downloads.application.name)"' -r) + 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" + curl -o paper.jar \ + "https://api.papermc.io/v2/projects/paper/versions/$VERSION/builds/$BUILD/downloads/$JAR_FILE" - name: Setup server run: | From 6d9d0c519688f0e8809c48f561db8493dae73617 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Tue, 4 Jul 2023 23:48:44 +0100 Subject: [PATCH 003/131] Download tester --- .github/workflows/e2e-testing.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index 57f021ff99..192ede827d 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -45,10 +45,14 @@ jobs: curl -o paper.jar \ "https://api.papermc.io/v2/projects/paper/versions/$VERSION/builds/$BUILD/downloads/$JAR_FILE" + - name: Download e2e-tester + run: curl -o e2e-tester.jar https://preview-builds.walshy.dev/download/e2e-tester/main/latest + - name: Setup server run: | echo 'eula=true' > eula.txt mkdir plugins + mv e2e-tester.jar plugins/e2e-tester.jar - uses: actions/download-artifact@v3 with: From 2f56579bc1552bddfec88bab04705e432a4fafb9 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Sun, 16 Jul 2023 22:20:49 +0100 Subject: [PATCH 004/131] Jeff's changes --- .github/workflows/e2e-testing.yml | 30 +++++++++++++++++++----------- .github/workflows/pull-request.yml | 12 +++++++++++- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index 192ede827d..b4adf613f7 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -1,6 +1,12 @@ name: End to End Testing -on: workflow_call +on: + workflow_call: + inputs: + artifact-name: + description: 'Slimefun artifact name' + required: true + type: string jobs: e2e-testing: @@ -35,6 +41,11 @@ jobs: 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 }}" @@ -45,20 +56,17 @@ jobs: curl -o paper.jar \ "https://api.papermc.io/v2/projects/paper/versions/$VERSION/builds/$BUILD/downloads/$JAR_FILE" - - name: Download e2e-tester - run: curl -o e2e-tester.jar https://preview-builds.walshy.dev/download/e2e-tester/main/latest + - name: Download Slimefun + uses: actions/download-artifact@v3 + with: + name: ${{ inputs.artifact-name }} + path: plugins/ - - name: Setup server + - name: Download e2e-tester run: | - echo 'eula=true' > eula.txt - mkdir plugins + curl -o e2e-tester.jar https://preview-builds.walshy.dev/download/e2e-tester/main/latest mv e2e-tester.jar plugins/e2e-tester.jar - - uses: actions/download-artifact@v3 - with: - name: slimefun-${{ github.event.number }} - path: plugins/ - - name: Run server run: | java -jar paper.jar --nogui diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 2c3a31ab8c..9d8a235ec6 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -14,6 +14,8 @@ jobs: setup-preview-build: name: Preview build runs-on: ubuntu-latest + outputs: + short-commit-hash: ${{ steps.env-setup.outputs.SHORT_COMMIT_HASH }} steps: - name: Checkout repository @@ -35,10 +37,12 @@ jobs: restore-keys: ${{ runner.os }}-m2 # Setup for the preview build - - run: | + - id: env-setup + run: | SHORT_COMMIT_HASH=$(git rev-parse --short=8 ${{ github.sha }}) JAR_VERSION="Preview Build #${{ github.event.number }}-$SHORT_COMMIT_HASH" echo "SHORT_COMMIT_HASH=$SHORT_COMMIT_HASH" >> "$GITHUB_ENV" + echo "SHORT_COMMIT_HASH=$SHORT_COMMIT_HASH" >> "$GITHUB_OUTPUT" echo "JAR_VERSION=$JAR_VERSION" >> "$GITHUB_ENV" sed -i "s/4.9-UNOFFICIAL<\/version>/$JAR_VERSION<\/version>/g" pom.xml @@ -50,3 +54,9 @@ jobs: with: name: slimefun-${{ github.event.number }}-${{ env.SHORT_COMMIT_HASH }} path: 'target/Slimefun v${{ env.JAR_VERSION }}.jar' + + call-workflows: + needs: [setup-preview-build] + uses: ./.github/workflows/e2e-testing.yml + with: + artifact-name: slimefun-${{ github.event.number }}-${{ needs.setup-preview-build.outputs.short-commit-hash }} From e71e2c85591082e7332205754f427ab921fe19ae Mon Sep 17 00:00:00 2001 From: Varian Anora Date: Fri, 21 Jul 2023 09:49:51 +0700 Subject: [PATCH 005/131] Add cherry log to android woodcutter --- .../items/androids/WoodcutterAndroid.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java index 8bc33808c1..0133cb3b25 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java @@ -162,6 +162,17 @@ private void replant(@Nonnull Block block) { } } + if (Slimefun.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_20)) { + switch (logType) { + case CHERRY_LOG, + STRIPPED_CHERRY_LOG -> { + saplingType = Material.CHERRY_SAPLING; + soilRequirement = SlimefunTag.DIRT_VARIANTS::isTagged; + } + default -> {} + } + } + if (saplingType != null && soilRequirement != null) { if (soilRequirement.test(block.getRelative(BlockFace.DOWN).getType())) { // Replant the block From cb292aeffe082c6fdfc345ca6e042913c871d37a Mon Sep 17 00:00:00 2001 From: Jeroen Date: Mon, 24 Jul 2023 23:25:25 +0200 Subject: [PATCH 006/131] skip already substituted parts when formatting message --- .../io/github/thebusybiscuit/slimefun4/core/debug/Debug.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/debug/Debug.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/debug/Debug.java index 433ec5e1cd..cf7687dc9f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/debug/Debug.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/debug/Debug.java @@ -106,7 +106,7 @@ public static void log(@Nonnull String test, @Nonnull String msg, @Nonnull Objec while ((i = msg.indexOf('{', i)) != -1 && msg.charAt(i + 1) == '}') { // Substring up to the opening brace `{`, add the variable for this and add the rest of the message msg = msg.substring(0, i) + vars[idx] + msg.substring(i + 2); - idx++; + i += ("" + vars[idx++]).length(); } return msg; From 4398098dec5beaee4917054fc9616373a2acde6c Mon Sep 17 00:00:00 2001 From: Jeroen Date: Fri, 28 Jul 2023 23:05:43 +0200 Subject: [PATCH 007/131] correctly handle sensitive blocks above blocks broken with explosive tool --- .../listeners/BlockListener.java | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index a8dcfc7ccb..96fcbd1f9a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -25,6 +25,7 @@ import org.bukkit.inventory.meta.ItemMeta; import io.github.bakedlibs.dough.protection.Interaction; +import io.github.thebusybiscuit.slimefun4.api.events.ExplosiveToolBreakBlocksEvent; import io.github.thebusybiscuit.slimefun4.api.events.SlimefunBlockBreakEvent; import io.github.thebusybiscuit.slimefun4.api.events.SlimefunBlockPlaceEvent; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; @@ -83,7 +84,7 @@ public void onBlockPlaceExisting(BlockPlaceEvent e) { public void onBlockPlace(BlockPlaceEvent e) { ItemStack item = e.getItemInHand(); SlimefunItem sfItem = SlimefunItem.getByItem(item); - + // TODO: Protection manager is null in testing environment. if (!Slimefun.instance().isUnitTest()) { Slimefun.getProtectionManager().logAction(e.getPlayer(), e.getBlock(), Interaction.BREAK_BLOCK); @@ -141,7 +142,7 @@ public void onBlockBreak(BlockBreakEvent e) { } if (!e.isCancelled()) { - checkForSensitiveBlockAbove(e, item); + checkForSensitiveBlockAbove(e.getPlayer(), e.getBlock(), item); int fortune = getBonusDropsWithFortune(item, e.getBlock()); List drops = new ArrayList<>(); @@ -155,6 +156,13 @@ public void onBlockBreak(BlockBreakEvent e) { } } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onExplosiveToolBlockBreak(ExplosiveToolBreakBlocksEvent e) { + for (Block block : e.getAdditionalBlocks()) { + checkForSensitiveBlockAbove(e.getPlayer(), block, e.getItemInHand()); + } + } + @ParametersAreNonnullByDefault private void callToolHandler(BlockBreakEvent e, ItemStack item, int fortune, List drops) { SlimefunItem tool = SlimefunItem.getByItem(item); @@ -219,14 +227,16 @@ private void dropItems(BlockBreakEvent e, List drops) { * Sensitive {@link Block Blocks} are pressure plates or saplings, which should be broken * when the block beneath is broken as well. * - * @param p + * @param player * The {@link Player} who broke this {@link Block} - * @param b + * @param block * The {@link Block} that was broken + * @param item + * The {@link ItemStack} that was used to break the {@link Block} */ @ParametersAreNonnullByDefault - private void checkForSensitiveBlockAbove(BlockBreakEvent e, ItemStack item) { - Block blockAbove = e.getBlock().getRelative(BlockFace.UP); + private void checkForSensitiveBlockAbove(Player player, Block block, ItemStack item) { + Block blockAbove = block.getRelative(BlockFace.UP); if (SlimefunTag.SENSITIVE_MATERIALS.isTagged(blockAbove.getType())) { SlimefunItem sfItem = BlockStorage.check(blockAbove); @@ -236,9 +246,8 @@ private void checkForSensitiveBlockAbove(BlockBreakEvent e, ItemStack item) { * We create a dummy here to pass onto the BlockBreakHandler. * This will set the correct block context. */ - BlockBreakEvent dummyEvent = new BlockBreakEvent(blockAbove, e.getPlayer()); - List drops = new ArrayList<>(); - drops.addAll(sfItem.getDrops(e.getPlayer())); + BlockBreakEvent dummyEvent = new BlockBreakEvent(blockAbove, player); + List drops = new ArrayList<>(sfItem.getDrops(player)); sfItem.callItemHandler(BlockBreakHandler.class, handler -> handler.onPlayerBreak(dummyEvent, item, drops)); blockAbove.setType(Material.AIR); From baef0381795f71adc903d5a10dd0d6537dd8534a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 6 Aug 2023 23:17:13 +0200 Subject: [PATCH 008/131] [CI skip] Update thollander/actions-comment-pull-request action to v2.4.2 --- .github/workflows/pr-labels.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-labels.yml b/.github/workflows/pr-labels.yml index d6e0720bb2..3b8f8f3ebc 100644 --- a/.github/workflows/pr-labels.yml +++ b/.github/workflows/pr-labels.yml @@ -31,7 +31,7 @@ jobs: api: '🔧 API' compatibility: '🤝 Compatibility' - - uses: thollander/actions-comment-pull-request@v2.4.0 + - uses: thollander/actions-comment-pull-request@v2.4.2 name: Leave a comment about the applied label if: ${{ steps.labeller.outputs.applied != 0 }} with: @@ -40,7 +40,7 @@ jobs: Your Pull Request was automatically labelled as: "${{ steps.labeller.outputs.applied }}" Thank you for contributing to this project! ❤️ - - uses: thollander/actions-comment-pull-request@v2.4.0 + - uses: thollander/actions-comment-pull-request@v2.4.2 name: Leave a comment about our branch naming convention if: ${{ steps.labeller.outputs.applied == 0 }} with: From 0137abadf10feeebd80f4db3c3c62b4859c47446 Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Tue, 8 Aug 2023 17:27:30 +0200 Subject: [PATCH 009/131] fix #3836 --- .../slimefun4/implementation/items/tools/ExplosiveTool.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java index db990c64c9..52c6e44f30 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java @@ -6,6 +6,7 @@ import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; +import dev.lone.itemsadder.api.CustomBlock; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; @@ -172,6 +173,9 @@ private void breakBlock(BlockBreakEvent e, Player p, ItemStack item, Block b, Li b.setType(Material.AIR); BlockStorage.clearBlockInfo(b); } + // Fixes #3836 + } else if (CustomBlock.byAlreadyPlaced(b) != null) { + return; } else { b.breakNaturally(item); } From 53cb0d93dca20be2b6fb85866fa34536466f7f61 Mon Sep 17 00:00:00 2001 From: iTwins Date: Wed, 9 Aug 2023 00:25:02 +0200 Subject: [PATCH 010/131] Fix unable to craft soulbound backpack with woven backpack with id (#3939) --- .../implementation/items/multiblocks/MagicWorkbench.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 029dd66a07..98cebcf884 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 @@ -130,9 +130,9 @@ private Block locateDispenser(Block b) { private boolean isCraftable(Inventory inv, ItemStack[] recipe) { for (int j = 0; j < inv.getContents().length; j++) { - if (!SlimefunUtils.isItemSimilar(inv.getContents()[j], recipe[j], true)) { + if (!SlimefunUtils.isItemSimilar(inv.getContents()[j], recipe[j], true, true, false)) { if (SlimefunItem.getByItem(recipe[j]) instanceof SlimefunBackpack) { - if (!SlimefunUtils.isItemSimilar(inv.getContents()[j], recipe[j], false)) { + if (!SlimefunUtils.isItemSimilar(inv.getContents()[j], recipe[j], false, true, false)) { return false; } } else { From 66feb7f387c5c456189f3c72e6cdb8c44cbecf28 Mon Sep 17 00:00:00 2001 From: iTwins Date: Fri, 11 Aug 2023 23:29:32 +0200 Subject: [PATCH 011/131] change BREAK_BLOCK to PLACE_BLOCK in BlockPlaceEvent --- .../slimefun4/implementation/listeners/BlockListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index a8dcfc7ccb..205f307d5f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -86,7 +86,7 @@ public void onBlockPlace(BlockPlaceEvent e) { // TODO: Protection manager is null in testing environment. if (!Slimefun.instance().isUnitTest()) { - Slimefun.getProtectionManager().logAction(e.getPlayer(), e.getBlock(), Interaction.BREAK_BLOCK); + Slimefun.getProtectionManager().logAction(e.getPlayer(), e.getBlock(), Interaction.PLACE_BLOCK); } if (sfItem != null && !(sfItem instanceof NotPlaceable)) { if (!sfItem.canUse(e.getPlayer(), true)) { From fb9e8c55e842d95906ed59fa628e341f02527a83 Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Mon, 14 Aug 2023 13:00:38 +0200 Subject: [PATCH 012/131] clean up --- .../slimefun4/implementation/items/tools/ExplosiveTool.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java index 52c6e44f30..bd85adc0c6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java @@ -138,7 +138,7 @@ protected boolean canBreak(@Nonnull Player p, @Nonnull Block b) { return false; } else if (!b.getWorld().getWorldBorder().isInside(b.getLocation())) { return false; - } else if (Slimefun.getIntegrations().isCustomBlock(b)) { + } else if (CustomBlock.byAlreadyPlaced(b) != null) { return false; } else { return Slimefun.getProtectionManager().hasPermission(p, b.getLocation(), Interaction.BREAK_BLOCK); @@ -173,9 +173,6 @@ private void breakBlock(BlockBreakEvent e, Player p, ItemStack item, Block b, Li b.setType(Material.AIR); BlockStorage.clearBlockInfo(b); } - // Fixes #3836 - } else if (CustomBlock.byAlreadyPlaced(b) != null) { - return; } else { b.breakNaturally(item); } From 7934a09e1af5685f728469701beff067e35c7953 Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Mon, 14 Aug 2023 13:03:31 +0200 Subject: [PATCH 013/131] changed to == --- .../slimefun4/implementation/items/tools/ExplosiveTool.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java index bd85adc0c6..fab595cdcb 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java @@ -138,7 +138,7 @@ protected boolean canBreak(@Nonnull Player p, @Nonnull Block b) { return false; } else if (!b.getWorld().getWorldBorder().isInside(b.getLocation())) { return false; - } else if (CustomBlock.byAlreadyPlaced(b) != null) { + } else if (CustomBlock.byAlreadyPlaced(b) == null) { return false; } else { return Slimefun.getProtectionManager().hasPermission(p, b.getLocation(), Interaction.BREAK_BLOCK); From 27f4ecbacf0eed8ad105f195ea630d05d5f08bce Mon Sep 17 00:00:00 2001 From: iTwins Date: Fri, 18 Aug 2023 23:55:28 +0200 Subject: [PATCH 014/131] fix getting radiated when not supposed to --- .../slimefun4/api/player/PlayerProfile.java | 17 +++----- .../slimefun4/implementation/Slimefun.java | 2 + .../listeners/JoinListener.java | 43 +++++++++++++++++++ .../tasks/armor/RadiationTask.java | 2 + 4 files changed, 52 insertions(+), 12 deletions(-) create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/JoinListener.java diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java index 29accb9509..2362a91d4a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java @@ -493,24 +493,17 @@ public boolean hasFullProtectionAgainst(@Nonnull ProtectionType type) { for (HashedArmorpiece armorpiece : armor) { Optional armorPiece = armorpiece.getItem(); - - if (!armorPiece.isPresent()) { - setId = null; - } else if (armorPiece.get() instanceof ProtectiveArmor protectedArmor) { - if (setId == null && protectedArmor.isFullSetRequired()) { - setId = protectedArmor.getArmorSetId(); - } - - for (ProtectionType protectionType : protectedArmor.getProtectionTypes()) { + if (armorPiece.isPresent() && armorPiece.get() instanceof ProtectiveArmor protectiveArmor) { + for (ProtectionType protectionType : protectiveArmor.getProtectionTypes()) { if (protectionType == type) { - if (setId == null) { + if (!protectiveArmor.isFullSetRequired()) { return true; - } else if (setId.equals(protectedArmor.getArmorSetId())) { + } else if (setId == null || setId.equals(protectiveArmor.getArmorSetId())) { armorCount++; + setId = protectiveArmor.getArmorSetId(); } } } - } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java index f1fffb2b83..2b8dd78f02 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java @@ -82,6 +82,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.HopperListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.ItemDropListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.ItemPickupListener; +import io.github.thebusybiscuit.slimefun4.implementation.listeners.JoinListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.MiddleClickListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.MiningAndroidListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.MultiBlockListener; @@ -646,6 +647,7 @@ private void registerListeners() { new BeeWingsListener(this, (BeeWings) SlimefunItems.BEE_WINGS.getItem()); new PiglinListener(this); new SmithingTableListener(this); + new JoinListener(this); // Item-specific Listeners new CoolerListener(this, (Cooler) SlimefunItems.COOLER.getItem()); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/JoinListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/JoinListener.java new file mode 100644 index 0000000000..202fe079c0 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/JoinListener.java @@ -0,0 +1,43 @@ +package io.github.thebusybiscuit.slimefun4.implementation.listeners; + +import javax.annotation.Nonnull; + +import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.inventory.ItemStack; + +import io.github.thebusybiscuit.slimefun4.api.items.HashedArmorpiece; +import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; +import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; +import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece; +import io.github.thebusybiscuit.slimefun4.implementation.tasks.armor.RadiationTask; + +/** + * This {@link Listener} caches the armor of the player on join. + * This is mainly for the {@link RadiationTask}. + * + * @author iTwins + */ +public class JoinListener implements Listener { + + public JoinListener(@Nonnull Slimefun plugin) { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @EventHandler + public void onJoin(@Nonnull PlayerJoinEvent e) { + PlayerProfile.get(e.getPlayer(), playerProfile -> { + final ItemStack[] armorContents = e.getPlayer().getInventory().getArmorContents(); + final HashedArmorpiece[] hashedArmorpieces = playerProfile.getArmor(); + for (int i = 0; i < 4; i++) { + if (armorContents[i] != null && armorContents[i].getType() != Material.AIR && SlimefunItem.getByItem(armorContents[i]) instanceof SlimefunArmorPiece sfArmorPiece) { + hashedArmorpieces[i].update(armorContents[i], sfArmorPiece); + } + } + }); + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/armor/RadiationTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/armor/RadiationTask.java index c2b40ae1ed..29ac850805 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/armor/RadiationTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/armor/RadiationTask.java @@ -85,6 +85,8 @@ protected void onPlayerTick(Player p, PlayerProfile profile) { BaseComponent[] components = new ComponentBuilder().append(ChatColors.color(msg)).create(); p.spigot().sendMessage(ChatMessageType.ACTION_BAR, components); } + } else { + RadiationUtils.removeExposure(p, 1); } } From f60896f620e3d367df845bdebf8e1ef68d383746 Mon Sep 17 00:00:00 2001 From: iTwins Date: Sun, 20 Aug 2023 02:37:24 +0200 Subject: [PATCH 015/131] fix geo miner voiding resources --- .../core/machines/MachineOperation.java | 6 +++ .../core/machines/MachineProcessor.java | 37 +++++++-------- .../implementation/items/geo/GEOMiner.java | 46 +++++++++---------- .../operations/MiningOperation.java | 29 +++++++++--- 4 files changed, 69 insertions(+), 49 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineOperation.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineOperation.java index 6ee741882a..67fda66d29 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineOperation.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineOperation.java @@ -57,4 +57,10 @@ default boolean isFinished() { return getRemainingTicks() <= 0; } + /** + * This method is called when a {@link MachineOperation} is interrupted before finishing. + * Implement to specify behaviour that should happen in this case. + */ + default void cancel() {} + } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java index 33ccb4111d..4ccf41192c 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java @@ -6,7 +6,8 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import org.apache.commons.lang.Validate; +import com.google.common.base.Preconditions; + import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.block.Block; @@ -46,7 +47,7 @@ public class MachineProcessor { * The owner of this {@link MachineProcessor}. */ public MachineProcessor(@Nonnull MachineProcessHolder owner) { - Validate.notNull(owner, "The MachineProcessHolder cannot be null."); + Preconditions.checkArgument(owner != null, "The MachineProcessHolder cannot be null."); this.owner = owner; } @@ -93,8 +94,8 @@ public void setProgressBar(@Nullable ItemStack progressBar) { * {@link MachineOperation} has already been started at that {@link Location}. */ public boolean startOperation(@Nonnull Location loc, @Nonnull T operation) { - Validate.notNull(loc, "The location must not be null"); - Validate.notNull(operation, "The operation cannot be null"); + Preconditions.checkArgument(loc != null, "The location must not be null"); + Preconditions.checkArgument(operation != null, "The operation cannot be null"); return startOperation(new BlockPosition(loc), operation); } @@ -111,8 +112,8 @@ public boolean startOperation(@Nonnull Location loc, @Nonnull T operation) { * {@link MachineOperation} has already been started at that {@link Block}. */ public boolean startOperation(@Nonnull Block b, @Nonnull T operation) { - Validate.notNull(b, "The Block must not be null"); - Validate.notNull(operation, "The machine operation cannot be null"); + Preconditions.checkArgument(b != null, "The Block must not be null"); + Preconditions.checkArgument(operation != null, "The machine operation cannot be null"); return startOperation(new BlockPosition(b), operation); } @@ -129,8 +130,8 @@ public boolean startOperation(@Nonnull Block b, @Nonnull T operation) { * {@link MachineOperation} has already been started at that {@link BlockPosition}. */ public boolean startOperation(@Nonnull BlockPosition pos, @Nonnull T operation) { - Validate.notNull(pos, "The BlockPosition must not be null"); - Validate.notNull(operation, "The machine operation cannot be null"); + Preconditions.checkArgument(pos != null, "The BlockPosition must not be null"); + Preconditions.checkArgument(operation != null, "The machine operation cannot be null"); return machines.putIfAbsent(pos, operation) == null; } @@ -144,7 +145,7 @@ public boolean startOperation(@Nonnull BlockPosition pos, @Nonnull T operation) * @return The current {@link MachineOperation} or null. */ public @Nullable T getOperation(@Nonnull Location loc) { - Validate.notNull(loc, "The location cannot be null"); + Preconditions.checkArgument(loc != null, "The location cannot be null"); return getOperation(new BlockPosition(loc)); } @@ -158,15 +159,13 @@ public boolean startOperation(@Nonnull BlockPosition pos, @Nonnull T operation) * @return The current {@link MachineOperation} or null. */ public @Nullable T getOperation(@Nonnull Block b) { - Validate.notNull(b, "The Block cannot be null"); + Preconditions.checkArgument(b != null, "The Block cannot be null"); return getOperation(new BlockPosition(b)); } /** * This returns the current {@link MachineOperation} at that given {@link BlockPosition}. - * We don't need to validate our input here as that is already - * covered in our public methods. * * @param pos * The {@link BlockPosition} at which our machine is located. @@ -174,7 +173,7 @@ public boolean startOperation(@Nonnull BlockPosition pos, @Nonnull T operation) * @return The current {@link MachineOperation} or null. */ public @Nullable T getOperation(@Nonnull BlockPosition pos) { - Validate.notNull(pos, "The BlockPosition must not be null"); + Preconditions.checkArgument(pos != null, "The BlockPosition must not be null"); return machines.get(pos); } @@ -189,7 +188,7 @@ public boolean startOperation(@Nonnull BlockPosition pos, @Nonnull T operation) * {@link MachineOperation} to begin with. */ public boolean endOperation(@Nonnull Location loc) { - Validate.notNull(loc, "The location should not be null"); + Preconditions.checkArgument(loc != null, "The location should not be null"); return endOperation(new BlockPosition(loc)); } @@ -204,7 +203,7 @@ public boolean endOperation(@Nonnull Location loc) { * {@link MachineOperation} to begin with. */ public boolean endOperation(@Nonnull Block b) { - Validate.notNull(b, "The Block should not be null"); + Preconditions.checkArgument(b != null, "The Block should not be null"); return endOperation(new BlockPosition(b)); } @@ -219,7 +218,7 @@ public boolean endOperation(@Nonnull Block b) { * {@link MachineOperation} to begin with. */ public boolean endOperation(@Nonnull BlockPosition pos) { - Validate.notNull(pos, "The BlockPosition cannot be null"); + Preconditions.checkArgument(pos != null, "The BlockPosition cannot be null"); T operation = machines.remove(pos); @@ -231,6 +230,8 @@ public boolean endOperation(@Nonnull BlockPosition pos) { if (operation.isFinished()) { Event event = new AsyncMachineOperationFinishEvent(pos, this, operation); Bukkit.getPluginManager().callEvent(event); + } else { + operation.cancel(); } return true; @@ -240,8 +241,8 @@ public boolean endOperation(@Nonnull BlockPosition pos) { } public void updateProgressBar(@Nonnull BlockMenu inv, int slot, @Nonnull T operation) { - Validate.notNull(inv, "The inventory must not be null."); - Validate.notNull(operation, "The MachineOperation must not be null."); + Preconditions.checkArgument(inv != null, "The inventory must not be null."); + Preconditions.checkArgument(operation != null, "The MachineOperation must not be null."); if (getProgressBar() == null) { // No progress bar, no need to update anything. diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java index e9b5d104ca..184215a2a8 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java @@ -7,7 +7,8 @@ import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; -import org.apache.commons.lang.Validate; +import com.google.common.base.Preconditions; + import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.block.Block; @@ -77,7 +78,7 @@ public GEOMiner(ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeTy } @Override - public MachineProcessor getMachineProcessor() { + public @Nonnull MachineProcessor getMachineProcessor() { return processor; } @@ -121,8 +122,8 @@ public int getSpeed() { * * @return This method will return the current instance of {@link GEOMiner}, so that can be chained. */ - public final GEOMiner setCapacity(int capacity) { - Validate.isTrue(capacity > 0, "The capacity must be greater than zero!"); + public final @Nonnull GEOMiner setCapacity(int capacity) { + Preconditions.checkArgument(capacity > 0, "The capacity must be greater than zero!"); if (getState() == ItemState.UNREGISTERED) { this.energyCapacity = capacity; @@ -140,8 +141,8 @@ public final GEOMiner setCapacity(int capacity) { * * @return This method will return the current instance of {@link GEOMiner}, so that can be chained. */ - public final GEOMiner setProcessingSpeed(int speed) { - Validate.isTrue(speed > 0, "The speed must be greater than zero!"); + public final @Nonnull GEOMiner setProcessingSpeed(int speed) { + Preconditions.checkArgument(speed > 0, "The speed must be greater than zero!"); this.processingSpeed = speed; return this; @@ -155,10 +156,10 @@ public final GEOMiner setProcessingSpeed(int speed) { * * @return This method will return the current instance of {@link GEOMiner}, so that can be chained. */ - public final GEOMiner setEnergyConsumption(int energyConsumption) { - Validate.isTrue(energyConsumption > 0, "The energy consumption must be greater than zero!"); - Validate.isTrue(energyCapacity > 0, "You must specify the capacity before you can set the consumption amount."); - Validate.isTrue(energyConsumption <= energyCapacity, "The energy consumption cannot be higher than the capacity (" + energyCapacity + ')'); + public final @Nonnull GEOMiner setEnergyConsumption(int energyConsumption) { + Preconditions.checkArgument(energyConsumption > 0, "The energy consumption must be greater than zero!"); + Preconditions.checkArgument(energyCapacity > 0, "You must specify the capacity before you can set the consumption amount."); + Preconditions.checkArgument(energyConsumption <= energyCapacity, "The energy consumption cannot be higher than the capacity (" + energyCapacity + ')'); this.energyConsumedPerTick = energyConsumption; return this; @@ -188,19 +189,17 @@ public void register(@Nonnull SlimefunAddon addon) { } } - @Nonnull - private BlockPlaceHandler onBlockPlace() { + private @Nonnull BlockPlaceHandler onBlockPlace() { return new BlockPlaceHandler(false) { @Override - public void onPlayerPlace(BlockPlaceEvent e) { + public void onPlayerPlace(@Nonnull BlockPlaceEvent e) { updateHologram(e.getBlock(), "&7Idling..."); } }; } - @Nonnull - private BlockBreakHandler onBlockBreak() { + private @Nonnull BlockBreakHandler onBlockBreak() { return new SimpleBlockBreakHandler() { @Override @@ -217,21 +216,18 @@ public void onBlockBreak(@Nonnull Block b) { }; } - @Nonnull @Override - public int[] getInputSlots() { + public @Nonnull int[] getInputSlots() { return new int[0]; } - @Nonnull @Override - public int[] getOutputSlots() { + public @Nonnull int[] getOutputSlots() { return OUTPUT_SLOTS; } - @Nonnull @Override - public List getDisplayRecipes() { + public @Nonnull List getDisplayRecipes() { List displayRecipes = new LinkedList<>(); for (GEOResource resource : Slimefun.getRegistry().getGEOResources().values()) { @@ -249,7 +245,7 @@ public List getDisplayRecipes() { } @Override - public EnergyNetComponentType getEnergyComponentType() { + public @Nonnull EnergyNetComponentType getEnergyComponentType() { return EnergyNetComponentType.CONSUMER; } @@ -274,7 +270,7 @@ public boolean onClick(Player p, int slot, ItemStack cursor, ClickAction action) @Override public boolean onClick(InventoryClickEvent e, Player p, int slot, ItemStack cursor, ClickAction action) { - return cursor == null || cursor.getType() == null || cursor.getType() == Material.AIR; + return cursor == null || cursor.getType() == Material.AIR; } }); } @@ -328,7 +324,7 @@ private void start(@Nonnull Block b, @Nonnull BlockMenu inv) { if (resource.isObtainableFromGEOMiner()) { OptionalInt optional = Slimefun.getGPSNetwork().getResourceManager().getSupplies(resource, b.getWorld(), b.getX() >> 4, b.getZ() >> 4); - if (!optional.isPresent()) { + if (optional.isEmpty()) { updateHologram(b, "&4GEO-Scan required!"); return; } @@ -339,7 +335,7 @@ private void start(@Nonnull Block b, @Nonnull BlockMenu inv) { return; } - processor.startOperation(b, new MiningOperation(resource.getItem().clone(), PROCESSING_TIME)); + processor.startOperation(b, new MiningOperation(resource, b, PROCESSING_TIME)); Slimefun.getGPSNetwork().getResourceManager().setSupplies(resource, b.getWorld(), b.getX() >> 4, b.getZ() >> 4, supplies - 1); updateHologram(b, "&7Mining: &r" + resource.getName()); return; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/MiningOperation.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/MiningOperation.java index 2a1201855f..a7dd33395c 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/MiningOperation.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/MiningOperation.java @@ -1,12 +1,18 @@ package io.github.thebusybiscuit.slimefun4.implementation.operations; +import java.util.OptionalInt; + import javax.annotation.Nonnull; -import org.apache.commons.lang.Validate; +import com.google.common.base.Preconditions; + +import org.bukkit.block.Block; import org.bukkit.inventory.ItemStack; import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource; +import io.github.thebusybiscuit.slimefun4.api.geo.ResourceManager; import io.github.thebusybiscuit.slimefun4.core.machines.MachineOperation; +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import io.github.thebusybiscuit.slimefun4.implementation.items.geo.GEOMiner; /** @@ -22,20 +28,24 @@ public class MiningOperation implements MachineOperation { private final ItemStack result; + private final GEOResource resource; + private final Block block; private final int totalTicks; private int currentTicks = 0; - public MiningOperation(@Nonnull ItemStack result, int totalTicks) { - Validate.notNull(result, "The result cannot be null"); - Validate.isTrue(totalTicks >= 0, "The amount of total ticks must be a positive integer or zero, received: " + totalTicks); + public MiningOperation(@Nonnull GEOResource resource, Block block, int totalTicks) { + Preconditions.checkArgument(resource != null, "The resource cannot be null"); + Preconditions.checkArgument(totalTicks >= 0, "The amount of total ticks must be a positive integer or zero, received: " + totalTicks); - this.result = result; + this.resource = resource; + this.result = resource.getItem().clone(); + this.block = block; this.totalTicks = totalTicks; } @Override public void addProgress(int num) { - Validate.isTrue(num > 0, "Progress must be positive."); + Preconditions.checkArgument(num > 0, "Progress must be positive."); currentTicks += num; } @@ -59,4 +69,11 @@ public int getTotalTicks() { return totalTicks; } + @Override + public void cancel() { + ResourceManager resourceManager = Slimefun.getGPSNetwork().getResourceManager(); + OptionalInt supplies = resourceManager.getSupplies(resource, block.getWorld(), block.getX() >> 4, block.getZ() >> 4); + supplies.ifPresent(s -> resourceManager.setSupplies(resource, block.getWorld(), block.getX() >> 4, block.getZ() >> 4, s + 1)); + } + } From 1315e5a8c926d2af3e99b5fc67d9608c83091b1c Mon Sep 17 00:00:00 2001 From: iTwins Date: Sun, 20 Aug 2023 03:42:30 +0200 Subject: [PATCH 016/131] refactored ternary operators --- .../slimefun4/api/geo/ResourceManager.java | 7 ++++--- .../slimefun4/utils/ChatUtils.java | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/geo/ResourceManager.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/geo/ResourceManager.java index d15024440d..3e93255b72 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/geo/ResourceManager.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/geo/ResourceManager.java @@ -28,6 +28,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import io.github.thebusybiscuit.slimefun4.implementation.items.geo.GEOMiner; import io.github.thebusybiscuit.slimefun4.implementation.items.geo.GEOScanner; +import io.github.thebusybiscuit.slimefun4.utils.ChatUtils; import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils; import io.github.thebusybiscuit.slimefun4.utils.HeadTexture; @@ -236,13 +237,13 @@ public void scan(@Nonnull Player p, @Nonnull Block block, int page) { for (int i = page * 28; i < resources.size() && i < (page + 1) * 28; i++) { GEOResource resource = resources.get(i); OptionalInt optional = getSupplies(resource, block.getWorld(), x, z); - int supplies = optional.isPresent() ? optional.getAsInt() : generate(resource, block.getWorld(), x, block.getY(), z); - String suffix = Slimefun.getLocalization().getResourceString(p, supplies == 1 ? "tooltips.unit" : "tooltips.units"); + int supplies = optional.orElse(generate(resource, block.getWorld(), x, block.getY(), z)); + String suffix = Slimefun.getLocalization().getResourceString(p, ChatUtils.checkPlurality("tooltips.unit", supplies)); ItemStack item = new CustomItemStack(resource.getItem(), "&f" + resource.getName(p), "&8\u21E8 &e" + supplies + ' ' + suffix); if (supplies > 1) { - item.setAmount(supplies > item.getMaxStackSize() ? item.getMaxStackSize() : supplies); + item.setAmount(Math.min(supplies, item.getMaxStackSize())); } menu.addItem(index, item, ChestMenuUtils.getEmptyClickHandler()); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChatUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChatUtils.java index e3d7aac4b9..65ed4c8ac5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChatUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChatUtils.java @@ -80,4 +80,21 @@ public static void awaitInput(@Nonnull Player p, @Nonnull Consumer callb return builder.toString(); } + /** + * This method adds an s to a string if the supplied integer is not 1. + * + * @param string + * The string to potentially pluralize + * @param count + * The amount of things + * @return + * string if count is 1 else string + "s" + */ + public static @Nonnull String checkPlurality(@Nonnull String string, int count) { + if (count == 1) { + return string; + } + return string + "s"; + } + } From 54f3530658ac834c1f3a341bf71d053093ddd4de Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Sun, 20 Aug 2023 14:16:55 +0200 Subject: [PATCH 017/131] requested changes --- .../slimefun4/implementation/items/tools/ExplosiveTool.java | 2 +- .../slimefun4/integrations/IntegrationsManager.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java index fab595cdcb..eb1be0bf45 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java @@ -138,7 +138,7 @@ protected boolean canBreak(@Nonnull Player p, @Nonnull Block b) { return false; } else if (!b.getWorld().getWorldBorder().isInside(b.getLocation())) { return false; - } else if (CustomBlock.byAlreadyPlaced(b) == null) { + } else if (Slimefun.getIntegrations().isCustomBlock(b)) { return false; } else { return Slimefun.getProtectionManager().hasPermission(p, b.getLocation(), Interaction.BREAK_BLOCK); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/integrations/IntegrationsManager.java b/src/main/java/io/github/thebusybiscuit/slimefun4/integrations/IntegrationsManager.java index 579e5bfb69..5063884c56 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/integrations/IntegrationsManager.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/integrations/IntegrationsManager.java @@ -6,6 +6,7 @@ import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; +import dev.lone.itemsadder.api.CustomBlock; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Server; @@ -236,7 +237,7 @@ public boolean isEventFaked(@Nonnull Event event) { public boolean isCustomBlock(@Nonnull Block block) { if (isItemsAdderInstalled) { try { - return ItemsAdder.isCustomBlock(block); + return CustomBlock.byAlreadyPlaced(block) != null; } catch (Exception | LinkageError x) { logError("ItemsAdder", x); } From e4bd5b164028722610e0cf1edba26619ea82c631 Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Sun, 20 Aug 2023 14:18:16 +0200 Subject: [PATCH 018/131] removed unused import --- .../slimefun4/implementation/items/tools/ExplosiveTool.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java index eb1be0bf45..db990c64c9 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java @@ -6,7 +6,6 @@ import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; -import dev.lone.itemsadder.api.CustomBlock; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; From 65819d1784d9c41a0a0fd64c669312c6f92eded3 Mon Sep 17 00:00:00 2001 From: iTwins Date: Sun, 20 Aug 2023 16:09:48 +0200 Subject: [PATCH 019/131] don't break MiningOperation, instead create new class --- .../implementation/items/geo/GEOMiner.java | 12 ++--- .../operations/GEOMiningOperation.java | 46 +++++++++++++++++++ .../operations/MiningOperation.java | 30 ++---------- 3 files changed, 57 insertions(+), 31 deletions(-) create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java index 184215a2a8..06f41a17a9 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java @@ -35,7 +35,7 @@ import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import io.github.thebusybiscuit.slimefun4.implementation.handlers.SimpleBlockBreakHandler; -import io.github.thebusybiscuit.slimefun4.implementation.operations.MiningOperation; +import io.github.thebusybiscuit.slimefun4.implementation.operations.GEOMiningOperation; import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils; import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config; @@ -54,7 +54,7 @@ * * @see GEOResource */ -public class GEOMiner extends SlimefunItem implements RecipeDisplayItem, EnergyNetComponent, InventoryBlock, HologramOwner, MachineProcessHolder { +public class GEOMiner extends SlimefunItem implements RecipeDisplayItem, EnergyNetComponent, InventoryBlock, HologramOwner, MachineProcessHolder { private static final int[] BORDER = { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 26, 27, 35, 36, 44, 45, 53 }; private static final int[] OUTPUT_BORDER = { 19, 20, 21, 22, 23, 24, 25, 28, 34, 37, 43, 46, 47, 48, 49, 50, 51, 52 }; @@ -62,7 +62,7 @@ public class GEOMiner extends SlimefunItem implements RecipeDisplayItem, EnergyN private static final int PROCESSING_TIME = 14; - private final MachineProcessor processor = new MachineProcessor<>(this); + private final MachineProcessor processor = new MachineProcessor<>(this); private int energyConsumedPerTick = -1; private int energyCapacity = -1; @@ -78,7 +78,7 @@ public GEOMiner(ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeTy } @Override - public @Nonnull MachineProcessor getMachineProcessor() { + public @Nonnull MachineProcessor getMachineProcessor() { return processor; } @@ -294,7 +294,7 @@ public boolean isSynchronized() { protected void tick(@Nonnull Block b) { BlockMenu inv = BlockStorage.getInventory(b); - MiningOperation operation = processor.getOperation(b); + GEOMiningOperation operation = processor.getOperation(b); if (operation != null) { if (!operation.isFinished()) { @@ -335,7 +335,7 @@ private void start(@Nonnull Block b, @Nonnull BlockMenu inv) { return; } - processor.startOperation(b, new MiningOperation(resource, b, PROCESSING_TIME)); + processor.startOperation(b, new GEOMiningOperation(resource, b, PROCESSING_TIME)); Slimefun.getGPSNetwork().getResourceManager().setSupplies(resource, b.getWorld(), b.getX() >> 4, b.getZ() >> 4, supplies - 1); updateHologram(b, "&7Mining: &r" + resource.getName()); return; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java new file mode 100644 index 0000000000..ee981eac83 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java @@ -0,0 +1,46 @@ +package io.github.thebusybiscuit.slimefun4.implementation.operations; + +import java.util.OptionalInt; + +import javax.annotation.Nonnull; + +import org.bukkit.block.Block; + +import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource; +import io.github.thebusybiscuit.slimefun4.api.geo.ResourceManager; +import io.github.thebusybiscuit.slimefun4.core.machines.MachineOperation; +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; +import io.github.thebusybiscuit.slimefun4.implementation.items.geo.GEOMiner; + +/** + * This {@link MachineOperation} represents a {@link GEOMiner} + * mining a {@link GEOResource}. + * + * @author iTwins + * + * @see GEOMiner + * + */ +public class GEOMiningOperation extends MiningOperation { + + private final GEOResource resource; + private final Block block; + + public GEOMiningOperation(@Nonnull GEOResource resource, @Nonnull Block block, int totalTicks) { + super(resource.getItem().clone(), totalTicks); + this.resource = resource; + this.block = block; + } + + /** + * This returns the {@link GEOResource} back to the chunk + * when the {@link GEOMiningOperation} gets cancelled + */ + @Override + public void cancel() { + ResourceManager resourceManager = Slimefun.getGPSNetwork().getResourceManager(); + OptionalInt supplies = resourceManager.getSupplies(resource, block.getWorld(), block.getX() >> 4, block.getZ() >> 4); + supplies.ifPresent(s -> resourceManager.setSupplies(resource, block.getWorld(), block.getX() >> 4, block.getZ() >> 4, s + 1)); + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/MiningOperation.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/MiningOperation.java index a7dd33395c..83480ce63f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/MiningOperation.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/MiningOperation.java @@ -1,45 +1,32 @@ package io.github.thebusybiscuit.slimefun4.implementation.operations; -import java.util.OptionalInt; - import javax.annotation.Nonnull; import com.google.common.base.Preconditions; -import org.bukkit.block.Block; import org.bukkit.inventory.ItemStack; -import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource; -import io.github.thebusybiscuit.slimefun4.api.geo.ResourceManager; import io.github.thebusybiscuit.slimefun4.core.machines.MachineOperation; -import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; -import io.github.thebusybiscuit.slimefun4.implementation.items.geo.GEOMiner; /** - * This {@link MachineOperation} represents a {@link GEOMiner} - * mining a {@link GEOResource}. + * This {@link MachineOperation} represents an operation + * with no inputs, only a result. * * @author TheBusyBiscuit - * - * @see GEOMiner * */ public class MiningOperation implements MachineOperation { private final ItemStack result; - private final GEOResource resource; - private final Block block; private final int totalTicks; private int currentTicks = 0; - public MiningOperation(@Nonnull GEOResource resource, Block block, int totalTicks) { - Preconditions.checkArgument(resource != null, "The resource cannot be null"); + public MiningOperation(@Nonnull ItemStack result, int totalTicks) { + Preconditions.checkArgument(result != null, "The result cannot be null"); Preconditions.checkArgument(totalTicks >= 0, "The amount of total ticks must be a positive integer or zero, received: " + totalTicks); - this.resource = resource; - this.result = resource.getItem().clone(); - this.block = block; + this.result = result; this.totalTicks = totalTicks; } @@ -69,11 +56,4 @@ public int getTotalTicks() { return totalTicks; } - @Override - public void cancel() { - ResourceManager resourceManager = Slimefun.getGPSNetwork().getResourceManager(); - OptionalInt supplies = resourceManager.getSupplies(resource, block.getWorld(), block.getX() >> 4, block.getZ() >> 4); - supplies.ifPresent(s -> resourceManager.setSupplies(resource, block.getWorld(), block.getX() >> 4, block.getZ() >> 4, s + 1)); - } - } From be3acf3edca66aba8b91a6dd9946f2a697e8f6a4 Mon Sep 17 00:00:00 2001 From: iTwins Date: Sun, 20 Aug 2023 16:46:41 +0200 Subject: [PATCH 020/131] renamed cancel to onCancel --- .../slimefun4/core/machines/MachineOperation.java | 2 +- .../slimefun4/core/machines/MachineProcessor.java | 2 +- .../slimefun4/implementation/operations/GEOMiningOperation.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineOperation.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineOperation.java index 67fda66d29..ff211b4594 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineOperation.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineOperation.java @@ -61,6 +61,6 @@ default boolean isFinished() { * This method is called when a {@link MachineOperation} is interrupted before finishing. * Implement to specify behaviour that should happen in this case. */ - default void cancel() {} + default void onCancel() {} } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java index 4ccf41192c..f8064c5c78 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java @@ -231,7 +231,7 @@ public boolean endOperation(@Nonnull BlockPosition pos) { Event event = new AsyncMachineOperationFinishEvent(pos, this, operation); Bukkit.getPluginManager().callEvent(event); } else { - operation.cancel(); + operation.onCancel(); } return true; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java index ee981eac83..664f4d669a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java @@ -37,7 +37,7 @@ public GEOMiningOperation(@Nonnull GEOResource resource, @Nonnull Block block, i * when the {@link GEOMiningOperation} gets cancelled */ @Override - public void cancel() { + public void onCancel() { ResourceManager resourceManager = Slimefun.getGPSNetwork().getResourceManager(); OptionalInt supplies = resourceManager.getSupplies(resource, block.getWorld(), block.getX() >> 4, block.getZ() >> 4); supplies.ifPresent(s -> resourceManager.setSupplies(resource, block.getWorld(), block.getX() >> 4, block.getZ() >> 4, s + 1)); From 6f194a6249cdf048319bf1ef59106b81b6fcdd1a Mon Sep 17 00:00:00 2001 From: Jeroen <48769316+iTwins@users.noreply.github.com> Date: Fri, 25 Aug 2023 18:14:47 +0200 Subject: [PATCH 021/131] Suggestion: remove empty line Co-authored-by: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> --- .../slimefun4/implementation/operations/GEOMiningOperation.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java index 664f4d669a..912e05e5b2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java @@ -19,7 +19,6 @@ * @author iTwins * * @see GEOMiner - * */ public class GEOMiningOperation extends MiningOperation { From 158167187dc538745eba7405c4b5d18181563e33 Mon Sep 17 00:00:00 2001 From: iTwins Date: Fri, 25 Aug 2023 18:25:12 +0200 Subject: [PATCH 022/131] replaced tags with {@code} tags --- .../io/github/thebusybiscuit/slimefun4/utils/ChatUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChatUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChatUtils.java index 65ed4c8ac5..c5a175d5a5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChatUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChatUtils.java @@ -88,7 +88,7 @@ public static void awaitInput(@Nonnull Player p, @Nonnull Consumer callb * @param count * The amount of things * @return - * string if count is 1 else string + "s" + * {@code string} if {@code count} is 1 else {@code string + "s"} */ public static @Nonnull String checkPlurality(@Nonnull String string, int count) { if (count == 1) { From 98cb08556b0625a45b1d22d5d547b34f53538e00 Mon Sep 17 00:00:00 2001 From: iTwins Date: Fri, 25 Aug 2023 18:39:31 +0200 Subject: [PATCH 023/131] use local variable to avoid accessing array multiple times --- .../slimefun4/implementation/listeners/JoinListener.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/JoinListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/JoinListener.java index 202fe079c0..28d15851bd 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/JoinListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/JoinListener.java @@ -33,8 +33,9 @@ public void onJoin(@Nonnull PlayerJoinEvent e) { final ItemStack[] armorContents = e.getPlayer().getInventory().getArmorContents(); final HashedArmorpiece[] hashedArmorpieces = playerProfile.getArmor(); for (int i = 0; i < 4; i++) { - if (armorContents[i] != null && armorContents[i].getType() != Material.AIR && SlimefunItem.getByItem(armorContents[i]) instanceof SlimefunArmorPiece sfArmorPiece) { - hashedArmorpieces[i].update(armorContents[i], sfArmorPiece); + final ItemStack armorPiece = armorContents[i]; + if (armorPiece != null && armorPiece.getType() != Material.AIR && SlimefunItem.getByItem(armorPiece) instanceof SlimefunArmorPiece sfArmorPiece) { + hashedArmorpieces[i].update(armorPiece, sfArmorPiece); } } }); From b15d7286b32a9b164f61b611a9a90fdeb1a90dc9 Mon Sep 17 00:00:00 2001 From: Skizzles Date: Sat, 26 Aug 2023 02:10:06 -0700 Subject: [PATCH 024/131] Update pom.xml Updates dough to version d3b0997226, this fixes HuskTowns breaking Slimefun4 functionality. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8e4149c4e6..eee000c2b6 100644 --- a/pom.xml +++ b/pom.xml @@ -355,7 +355,7 @@ com.github.baked-libs.dough dough-api - 39856a32c4 + d3b0997226 compile From 150258b7db71309adf642bdb7fb1a227f9178937 Mon Sep 17 00:00:00 2001 From: ybw0014 Date: Sun, 27 Aug 2023 23:44:45 -0400 Subject: [PATCH 025/131] feat: allow sword of beheading drop piglin heads --- .../items/weapons/SwordOfBeheading.java | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java index 42842880cc..ef74985c70 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java @@ -8,6 +8,7 @@ import org.bukkit.Material; import org.bukkit.entity.Creeper; import org.bukkit.entity.Monster; +import org.bukkit.entity.Piglin; import org.bukkit.entity.Player; import org.bukkit.entity.Skeleton; import org.bukkit.entity.WitherSkeleton; @@ -26,7 +27,8 @@ /** * The {@link SwordOfBeheading} is a special kind of sword which allows you to obtain - * {@link Zombie}, {@link Skeleton} and {@link Creeper} skulls when killing the respective {@link Monster}. + * {@link Zombie}, {@link Skeleton}, {@link Creeper} and {@link Piglin} skulls when killing the respective + * {@link Monster}. * Additionally, you can also obtain the head of a {@link Player} by killing them too. * This sword also allows you to have a higher chance of getting the skull of a {@link WitherSkeleton} too. * @@ -41,13 +43,14 @@ public class SwordOfBeheading extends SimpleSlimefunItem { private final ItemSetting chanceSkeleton = new IntRangeSetting(this, "chance.SKELETON", 0, 40, 100); private final ItemSetting chanceWitherSkeleton = new IntRangeSetting(this, "chance.WITHER_SKELETON", 0, 25, 100); private final ItemSetting chanceCreeper = new IntRangeSetting(this, "chance.CREEPER", 0, 40, 100); + private final ItemSetting chancePiglin = new IntRangeSetting(this, "chance.PIGLIN", 0, 40, 100); private final ItemSetting chancePlayer = new IntRangeSetting(this, "chance.PLAYER", 0, 70, 100); @ParametersAreNonnullByDefault public SwordOfBeheading(ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { super(itemGroup, item, recipeType, recipe); - addItemSetting(chanceZombie, chanceSkeleton, chanceWitherSkeleton, chanceCreeper, chancePlayer); + addItemSetting(chanceZombie, chanceSkeleton, chanceWitherSkeleton, chanceCreeper, chancePiglin, chancePlayer); } @Override @@ -56,27 +59,32 @@ public EntityKillHandler getItemHandler() { Random random = ThreadLocalRandom.current(); switch (e.getEntityType()) { - case ZOMBIE: + case ZOMBIE -> { if (random.nextInt(100) < chanceZombie.getValue()) { e.getDrops().add(new ItemStack(Material.ZOMBIE_HEAD)); } - break; - case SKELETON: + } + case SKELETON -> { if (random.nextInt(100) < chanceSkeleton.getValue()) { e.getDrops().add(new ItemStack(Material.SKELETON_SKULL)); } - break; - case CREEPER: + } + case CREEPER -> { if (random.nextInt(100) < chanceCreeper.getValue()) { e.getDrops().add(new ItemStack(Material.CREEPER_HEAD)); } - break; - case WITHER_SKELETON: + } + case WITHER_SKELETON -> { if (random.nextInt(100) < chanceWitherSkeleton.getValue()) { e.getDrops().add(new ItemStack(Material.WITHER_SKELETON_SKULL)); } - break; - case PLAYER: + } + case PIGLIN -> { + if (random.nextInt(100) < chancePiglin.getValue()) { + e.getDrops().add(new ItemStack(Material.PIGLIN_HEAD)); + } + } + case PLAYER -> { if (random.nextInt(100) < chancePlayer.getValue()) { ItemStack skull = new ItemStack(Material.PLAYER_HEAD); @@ -86,9 +94,9 @@ public EntityKillHandler getItemHandler() { e.getDrops().add(skull); } - break; - default: - break; + } + default -> { + } } }; } From 2fd3d0e50c1f849ec175cbaa48436f343a2616be Mon Sep 17 00:00:00 2001 From: ybw0014 Date: Mon, 28 Aug 2023 01:54:01 -0400 Subject: [PATCH 026/131] chore: inline default --- .../implementation/items/weapons/SwordOfBeheading.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java index ef74985c70..17b91d534a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java @@ -95,8 +95,7 @@ public EntityKillHandler getItemHandler() { e.getDrops().add(skull); } } - default -> { - } + default -> {} } }; } From 361c83fd73553341c18c9875cb0e204070aee4a7 Mon Sep 17 00:00:00 2001 From: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Date: Tue, 29 Aug 2023 16:47:29 -0500 Subject: [PATCH 027/131] Add the get optional methods --- .../slimefun4/api/items/SlimefunItem.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java index 0d4b1f12fa..7db2dc5a2d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java @@ -1161,6 +1161,17 @@ public final int hashCode() { return Slimefun.getRegistry().getSlimefunItemIds().get(id); } + /** + * Retrieve a {@link Optional}<{@link SlimefunItem}> by its id. + * + * @param id + * The id of the {@link SlimefunItem} + * @return The {@link Optional}<{@link SlimefunItem}> associated with that id. Empty if non-existent + */ + public static @Nonnull Optional getOptionalById(@Nonnull String id) { + return Optional.ofNullable(getById(id)); + } + /** * Retrieve a {@link SlimefunItem} from an {@link ItemStack}. * @@ -1208,4 +1219,15 @@ public final int hashCode() { return null; } + /** + * Retrieve a {@link Optional}<{@link SlimefunItem}> from an {@link ItemStack}. + * + * @param item + * The {@link ItemStack} to check + * @return The {@link Optional}<{@link SlimefunItem}> associated with this {@link ItemStack} if present, otherwise empty + */ + public @Nonnull Optional getOptionalByItem(@Nullable ItemStack item) { + return Optional.ofNullable(getByItem(item)); + } + } \ No newline at end of file From 25ac1655d6209f2b7390c3c434ac18e10e586072 Mon Sep 17 00:00:00 2001 From: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Date: Tue, 29 Aug 2023 16:56:08 -0500 Subject: [PATCH 028/131] Remove accidental new line --- .../github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java index 6a54669cf8..d3bc8368fd 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java @@ -1202,5 +1202,4 @@ public final int hashCode() { public @Nonnull Optional getOptionalByItem(@Nullable ItemStack item) { return Optional.ofNullable(getByItem(item)); } - } From df479f1d5d62d1b9c25c6908782f97aed4720a40 Mon Sep 17 00:00:00 2001 From: Jeroen <48769316+iTwins@users.noreply.github.com> Date: Wed, 30 Aug 2023 00:10:25 +0200 Subject: [PATCH 029/131] use String.valueOf instead of appending to empty string --- .../io/github/thebusybiscuit/slimefun4/core/debug/Debug.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/debug/Debug.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/debug/Debug.java index cf7687dc9f..50a05c309e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/debug/Debug.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/debug/Debug.java @@ -106,7 +106,7 @@ public static void log(@Nonnull String test, @Nonnull String msg, @Nonnull Objec while ((i = msg.indexOf('{', i)) != -1 && msg.charAt(i + 1) == '}') { // Substring up to the opening brace `{`, add the variable for this and add the rest of the message msg = msg.substring(0, i) + vars[idx] + msg.substring(i + 2); - i += ("" + vars[idx++]).length(); + i += String.valueOf(vars[idx++]).length(); } return msg; From 67af02ce82071e6bd5214548f43bccd508da6b8d Mon Sep 17 00:00:00 2001 From: Phoenix-Starlight <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Tue, 29 Aug 2023 18:20:47 -0700 Subject: [PATCH 030/131] Enforce LF endings automatically (#3946) --- .gitattributes | 2 + .../api/events/SlimefunGuideOpenEvent.java | 208 +++++++------- .../core/attributes/RandomMobDrop.java | 70 ++--- .../core/handlers/RainbowTickHandler.java | 268 +++++++++--------- 4 files changed, 275 insertions(+), 273 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..0be416846f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Automatically normalize line endings (to LF) for all text-based files. +* text=auto eol=lf diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunGuideOpenEvent.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunGuideOpenEvent.java index f4892242a4..ecf46a5311 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunGuideOpenEvent.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunGuideOpenEvent.java @@ -1,104 +1,104 @@ -package io.github.thebusybiscuit.slimefun4.api.events; - -import javax.annotation.Nonnull; - -import org.apache.commons.lang.Validate; -import org.bukkit.entity.Player; -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.core.guide.SlimefunGuideMode; - -/** - * This {@link Event} is called whenever a {@link Player} tries to open the Slimefun Guide book. - * - * @author Linox - * - * @see SlimefunGuideMode - */ -public class SlimefunGuideOpenEvent extends Event implements Cancellable { - - private static final HandlerList handlers = new HandlerList(); - - private final Player player; - private final ItemStack guide; - private SlimefunGuideMode layout; - private boolean cancelled; - - public SlimefunGuideOpenEvent(@Nonnull Player p, @Nonnull ItemStack guide, @Nonnull SlimefunGuideMode layout) { - Validate.notNull(p, "The Player cannot be null"); - Validate.notNull(guide, "Guide cannot be null"); - Validate.notNull(layout, "Layout cannot be null"); - this.player = p; - this.guide = guide; - this.layout = layout; - } - - /** - * This returns the {@link Player} that tries to open - * the Slimefun Guide. - * - * @return The {@link Player} - */ - @Nonnull - public Player getPlayer() { - return player; - } - - /** - * This returns the {@link ItemStack} that {@link Player} - * tries to open the Slimefun Guide with. - * - * @return The {@link ItemStack} - */ - @Nonnull - public ItemStack getGuide() { - return guide; - } - - /** - * This returns the {@link SlimefunGuideMode} of the Slimefun Guide - * that {@link Player} tries to open. - * - * @return The {@link SlimefunGuideMode} - */ - @Nonnull - public SlimefunGuideMode getGuideLayout() { - return layout; - } - - /** - * Changes the {@link SlimefunGuideMode} that was tried to be opened with. - * - * @param layout - * The new {@link SlimefunGuideMode} - */ - public void setGuideLayout(@Nonnull SlimefunGuideMode layout) { - Validate.notNull(layout, "You must specify a layout that is not-null!"); - this.layout = layout; - } - - @Override - public boolean isCancelled() { - return cancelled; - } - - @Override - public void setCancelled(boolean cancel) { - this.cancelled = cancel; - } - - @Nonnull - public static HandlerList getHandlerList() { - return handlers; - } - - @Nonnull - @Override - public HandlerList getHandlers() { - return getHandlerList(); - } - -} +package io.github.thebusybiscuit.slimefun4.api.events; + +import javax.annotation.Nonnull; + +import org.apache.commons.lang.Validate; +import org.bukkit.entity.Player; +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.core.guide.SlimefunGuideMode; + +/** + * This {@link Event} is called whenever a {@link Player} tries to open the Slimefun Guide book. + * + * @author Linox + * + * @see SlimefunGuideMode + */ +public class SlimefunGuideOpenEvent extends Event implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + + private final Player player; + private final ItemStack guide; + private SlimefunGuideMode layout; + private boolean cancelled; + + public SlimefunGuideOpenEvent(@Nonnull Player p, @Nonnull ItemStack guide, @Nonnull SlimefunGuideMode layout) { + Validate.notNull(p, "The Player cannot be null"); + Validate.notNull(guide, "Guide cannot be null"); + Validate.notNull(layout, "Layout cannot be null"); + this.player = p; + this.guide = guide; + this.layout = layout; + } + + /** + * This returns the {@link Player} that tries to open + * the Slimefun Guide. + * + * @return The {@link Player} + */ + @Nonnull + public Player getPlayer() { + return player; + } + + /** + * This returns the {@link ItemStack} that {@link Player} + * tries to open the Slimefun Guide with. + * + * @return The {@link ItemStack} + */ + @Nonnull + public ItemStack getGuide() { + return guide; + } + + /** + * This returns the {@link SlimefunGuideMode} of the Slimefun Guide + * that {@link Player} tries to open. + * + * @return The {@link SlimefunGuideMode} + */ + @Nonnull + public SlimefunGuideMode getGuideLayout() { + return layout; + } + + /** + * Changes the {@link SlimefunGuideMode} that was tried to be opened with. + * + * @param layout + * The new {@link SlimefunGuideMode} + */ + public void setGuideLayout(@Nonnull SlimefunGuideMode layout) { + Validate.notNull(layout, "You must specify a layout that is not-null!"); + this.layout = layout; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + @Nonnull + public static HandlerList getHandlerList() { + return handlers; + } + + @Nonnull + @Override + public HandlerList getHandlers() { + return getHandlerList(); + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/RandomMobDrop.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/RandomMobDrop.java index 9643760391..a0e51fe32d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/RandomMobDrop.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/RandomMobDrop.java @@ -1,35 +1,35 @@ -package io.github.thebusybiscuit.slimefun4.core.attributes; - -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; -import org.bukkit.event.entity.EntityDeathEvent; - -import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; -import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.implementation.items.misc.BasicCircuitBoard; -import io.github.thebusybiscuit.slimefun4.implementation.listeners.entity.MobDropListener; - -/** - * This interface, when attached to a {@link SlimefunItem}, provides an easy method for adding - * a % chance to drop for an {@link SlimefunItem} on {@link EntityDeathEvent}, this chance is 0-100 - * and used in conjunction with the {@link RecipeType#MOB_DROP}. - * - * @author dNiym - * - * @see BasicCircuitBoard - * @see MobDropListener - * @see PiglinBarterDrop - * - */ -public interface RandomMobDrop extends ItemAttribute { - - /** - * Implement this method to make the object have a variable chance of being - * added to the dropList when {@link EntityType} specified in - * the {@link RecipeType#MOB_DROP} is killed by the {@link Player}. - * - * @return The integer chance (0-100%) {@link SlimefunItem} has to drop. - */ - int getMobDropChance(); - -} +package io.github.thebusybiscuit.slimefun4.core.attributes; + +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDeathEvent; + +import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; +import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; +import io.github.thebusybiscuit.slimefun4.implementation.items.misc.BasicCircuitBoard; +import io.github.thebusybiscuit.slimefun4.implementation.listeners.entity.MobDropListener; + +/** + * This interface, when attached to a {@link SlimefunItem}, provides an easy method for adding + * a % chance to drop for an {@link SlimefunItem} on {@link EntityDeathEvent}, this chance is 0-100 + * and used in conjunction with the {@link RecipeType#MOB_DROP}. + * + * @author dNiym + * + * @see BasicCircuitBoard + * @see MobDropListener + * @see PiglinBarterDrop + * + */ +public interface RandomMobDrop extends ItemAttribute { + + /** + * Implement this method to make the object have a variable chance of being + * added to the dropList when {@link EntityType} specified in + * the {@link RecipeType#MOB_DROP} is killed by the {@link Player}. + * + * @return The integer chance (0-100%) {@link SlimefunItem} has to drop. + */ + int getMobDropChance(); + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/handlers/RainbowTickHandler.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/handlers/RainbowTickHandler.java index 38900d8524..6fa656f6d0 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/handlers/RainbowTickHandler.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/handlers/RainbowTickHandler.java @@ -1,134 +1,134 @@ -package io.github.thebusybiscuit.slimefun4.core.handlers; - -import java.util.Arrays; -import java.util.List; - -import javax.annotation.Nonnull; - -import org.apache.commons.lang.Validate; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.type.GlassPane; - -import io.github.bakedlibs.dough.collections.LoopIterator; -import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; -import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; -import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; -import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.RainbowBlock; -import io.github.thebusybiscuit.slimefun4.utils.ColoredMaterial; - -import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config; -import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker; - -/** - * This is a {@link BlockTicker} that is exclusively used for Rainbow blocks. - * On every tick it cycles through the {@link LoopIterator} and chooses the next {@link Material} - * and sets itself to that. - * - * @author TheBusyBiscuit - * - * @see RainbowBlock - * - */ -public class RainbowTickHandler extends BlockTicker { - - private final LoopIterator iterator; - private final boolean glassPanes; - private Material material; - - public RainbowTickHandler(@Nonnull List materials) { - Validate.noNullElements(materials, "A RainbowTicker cannot have a Material that is null!"); - - if (materials.isEmpty()) { - throw new IllegalArgumentException("A RainbowTicker must have at least one Material associated with it!"); - } - - glassPanes = containsGlassPanes(materials); - iterator = new LoopIterator<>(materials); - material = iterator.next(); - } - - public RainbowTickHandler(@Nonnull Material... materials) { - this(Arrays.asList(materials)); - } - - public RainbowTickHandler(@Nonnull ColoredMaterial material) { - this(material.asList()); - } - - /** - * This method checks whether a given {@link Material} array contains any {@link Material} - * that would result in a {@link GlassPane} {@link BlockData}. - * This is done to save performance, so we don't have to validate {@link BlockData} at - * runtime. - * - * @param materials - * The {@link Material} Array to check - * - * @return Whether the array contained any {@link GlassPane} materials - */ - private boolean containsGlassPanes(@Nonnull List materials) { - if (Slimefun.getMinecraftVersion() == MinecraftVersion.UNIT_TEST) { - // BlockData is not available to us during Unit Tests :/ - return false; - } - - for (Material type : materials) { - /* - This BlockData is purely virtual and only created on startup, it should have - no impact on performance, in fact it should save performance as it preloads - the data but also saves heavy calls for other Materials - */ - if (type.createBlockData() instanceof GlassPane) { - return true; - } - } - - return false; - } - - @Override - public void tick(Block b, SlimefunItem item, Config data) { - if (b.getType().isAir()) { - /* - The block was broken, setting the Material now would result in a - duplication glitch - */ - return; - } - - if (glassPanes) { - BlockData blockData = b.getBlockData(); - - if (blockData instanceof GlassPane previousData) { - BlockData block = material.createBlockData(bd -> { - if (bd instanceof GlassPane nextData) { - nextData.setWaterlogged(previousData.isWaterlogged()); - - for (BlockFace face : previousData.getAllowedFaces()) { - nextData.setFace(face, previousData.hasFace(face)); - } - } - }); - - b.setBlockData(block, false); - return; - } - } - - b.setType(material, false); - } - - @Override - public void uniqueTick() { - material = iterator.next(); - } - - @Override - public boolean isSynchronized() { - return true; - } - -} +package io.github.thebusybiscuit.slimefun4.core.handlers; + +import java.util.Arrays; +import java.util.List; + +import javax.annotation.Nonnull; + +import org.apache.commons.lang.Validate; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.type.GlassPane; + +import io.github.bakedlibs.dough.collections.LoopIterator; +import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; +import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; +import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.RainbowBlock; +import io.github.thebusybiscuit.slimefun4.utils.ColoredMaterial; + +import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config; +import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker; + +/** + * This is a {@link BlockTicker} that is exclusively used for Rainbow blocks. + * On every tick it cycles through the {@link LoopIterator} and chooses the next {@link Material} + * and sets itself to that. + * + * @author TheBusyBiscuit + * + * @see RainbowBlock + * + */ +public class RainbowTickHandler extends BlockTicker { + + private final LoopIterator iterator; + private final boolean glassPanes; + private Material material; + + public RainbowTickHandler(@Nonnull List materials) { + Validate.noNullElements(materials, "A RainbowTicker cannot have a Material that is null!"); + + if (materials.isEmpty()) { + throw new IllegalArgumentException("A RainbowTicker must have at least one Material associated with it!"); + } + + glassPanes = containsGlassPanes(materials); + iterator = new LoopIterator<>(materials); + material = iterator.next(); + } + + public RainbowTickHandler(@Nonnull Material... materials) { + this(Arrays.asList(materials)); + } + + public RainbowTickHandler(@Nonnull ColoredMaterial material) { + this(material.asList()); + } + + /** + * This method checks whether a given {@link Material} array contains any {@link Material} + * that would result in a {@link GlassPane} {@link BlockData}. + * This is done to save performance, so we don't have to validate {@link BlockData} at + * runtime. + * + * @param materials + * The {@link Material} Array to check + * + * @return Whether the array contained any {@link GlassPane} materials + */ + private boolean containsGlassPanes(@Nonnull List materials) { + if (Slimefun.getMinecraftVersion() == MinecraftVersion.UNIT_TEST) { + // BlockData is not available to us during Unit Tests :/ + return false; + } + + for (Material type : materials) { + /* + This BlockData is purely virtual and only created on startup, it should have + no impact on performance, in fact it should save performance as it preloads + the data but also saves heavy calls for other Materials + */ + if (type.createBlockData() instanceof GlassPane) { + return true; + } + } + + return false; + } + + @Override + public void tick(Block b, SlimefunItem item, Config data) { + if (b.getType().isAir()) { + /* + The block was broken, setting the Material now would result in a + duplication glitch + */ + return; + } + + if (glassPanes) { + BlockData blockData = b.getBlockData(); + + if (blockData instanceof GlassPane previousData) { + BlockData block = material.createBlockData(bd -> { + if (bd instanceof GlassPane nextData) { + nextData.setWaterlogged(previousData.isWaterlogged()); + + for (BlockFace face : previousData.getAllowedFaces()) { + nextData.setFace(face, previousData.hasFace(face)); + } + } + }); + + b.setBlockData(block, false); + return; + } + } + + b.setType(material, false); + } + + @Override + public void uniqueTick() { + material = iterator.next(); + } + + @Override + public boolean isSynchronized() { + return true; + } + +} From 5b2e95933ad9b7fa5e679722c7ce37db9ff2f3cb Mon Sep 17 00:00:00 2001 From: iTwins Date: Wed, 30 Aug 2023 23:52:17 +0200 Subject: [PATCH 031/131] added unit test for checkPlurality and IAE for negative values --- .../thebusybiscuit/slimefun4/utils/ChatUtils.java | 5 +++++ .../thebusybiscuit/slimefun4/utils/TestChatUtils.java | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChatUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChatUtils.java index c5a175d5a5..829e5891c3 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChatUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ChatUtils.java @@ -89,8 +89,13 @@ public static void awaitInput(@Nonnull Player p, @Nonnull Consumer callb * The amount of things * @return * {@code string} if {@code count} is 1 else {@code string + "s"} + * @throws IllegalArgumentException + * if count is less than 0 */ public static @Nonnull String checkPlurality(@Nonnull String string, int count) { + if (count < 0) { + throw new IllegalArgumentException("Argument count cannot be negative."); + } if (count == 1) { return string; } diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/utils/TestChatUtils.java b/src/test/java/io/github/thebusybiscuit/slimefun4/utils/TestChatUtils.java index 80fa61aa83..794b02e4b5 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/utils/TestChatUtils.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/utils/TestChatUtils.java @@ -33,4 +33,14 @@ void testColorCodeRemoval() { Assertions.assertEquals(expected, ChatUtils.removeColorCodes(ChatColor.GREEN + "Hello " + ChatColor.RED + "world")); } + @Test + @DisplayName("Test ChatUtils.checkPlurality(...)") + void testPluralization() { + String input = "Banana"; + Assertions.assertThrows(IllegalArgumentException.class, () -> ChatUtils.checkPlurality(input, -1)); + Assertions.assertEquals("Bananas", ChatUtils.checkPlurality(input, 0)); + Assertions.assertEquals("Banana", ChatUtils.checkPlurality(input, 1)); + Assertions.assertEquals("Bananas", ChatUtils.checkPlurality(input, 2)); + } + } From 666e9839dcd5a9eed725693f78ad4a9637aafd9f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 3 Sep 2023 12:39:30 +0200 Subject: [PATCH 032/131] [CI skip] Update dependency net.imprex:orebfuscator-api to v5.4.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index eee000c2b6..d17527aa4a 100644 --- a/pom.xml +++ b/pom.xml @@ -502,7 +502,7 @@ net.imprex orebfuscator-api - 5.3.3 + 5.4.0 provided From d265b7a0208349e5cb369f9653db13d0ab94226f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 3 Sep 2023 12:40:59 +0200 Subject: [PATCH 033/131] [CI skip] Update dependency org.mockito:mockito-core to v5.5.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d17527aa4a..8c41fbb567 100644 --- a/pom.xml +++ b/pom.xml @@ -389,7 +389,7 @@ org.mockito mockito-core - 5.4.0 + 5.5.0 test From ef3c960d7fb80e9bc70716a999a69dad177c0de8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 3 Sep 2023 12:41:56 +0200 Subject: [PATCH 034/131] [CI skip] Update actions/checkout action to v3.6.0 --- .github/workflows/discord-webhook.yml | 2 +- .github/workflows/sonarcloud.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/discord-webhook.yml b/.github/workflows/discord-webhook.yml index f4c018a140..14c37fc1ef 100644 --- a/.github/workflows/discord-webhook.yml +++ b/.github/workflows/discord-webhook.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v3.6.0 - name: Set up Java JDK 17 uses: actions/setup-java@v3.12.0 diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 8454eaac19..8128ed2ef2 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v3.6.0 with: fetch-depth: 0 From bcea5077f8236ab0bea6f74ce94287d0b1f900c1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 3 Sep 2023 12:42:59 +0200 Subject: [PATCH 035/131] [CI skip] Update dependency com.gmail.nossr50.mcMMO:mcMMO to v2.1.223 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8c41fbb567..2a2d47bf35 100644 --- a/pom.xml +++ b/pom.xml @@ -446,7 +446,7 @@ com.gmail.nossr50.mcMMO mcMMO - 2.1.222 + 2.1.223 provided From c06e316b6abe22991c84af60df2b2bd91d108b44 Mon Sep 17 00:00:00 2001 From: iTwins Date: Sun, 3 Sep 2023 14:27:28 +0200 Subject: [PATCH 036/131] cursor.getType() == null check --- .../slimefun4/implementation/items/geo/GEOMiner.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java index 06f41a17a9..951f56ac45 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java @@ -270,7 +270,7 @@ public boolean onClick(Player p, int slot, ItemStack cursor, ClickAction action) @Override public boolean onClick(InventoryClickEvent e, Player p, int slot, ItemStack cursor, ClickAction action) { - return cursor == null || cursor.getType() == Material.AIR; + return cursor == null || cursor.getType() == null || cursor.getType() == Material.AIR; } }); } From 6d70544bb715a1ca9875fec486de9edeabcd077a Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Sun, 3 Sep 2023 17:45:08 +0200 Subject: [PATCH 037/131] we now actually drop --- .../implementation/items/tools/ExplosiveTool.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java index db990c64c9..9f71e881d9 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java @@ -6,6 +6,7 @@ import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; +import dev.lone.itemsadder.api.CustomBlock; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; @@ -35,9 +36,9 @@ /** * This {@link SlimefunItem} is a super class for items like the {@link ExplosivePickaxe} or {@link ExplosiveShovel}. - * + * * @author TheBusyBiscuit - * + * * @see ExplosivePickaxe * @see ExplosiveShovel * @@ -83,6 +84,10 @@ private void breakBlocks(BlockBreakEvent e, Player p, ItemStack item, Block b, L if (!blockExplodeEvent.isCancelled()) { for (Block block : blockExplodeEvent.blockList()) { if (canBreak(p, block)) { + if (CustomBlock.byAlreadyPlaced(block) != null) { + drops.addAll(CustomBlock.byAlreadyPlaced(block).getLoot()); + CustomBlock.remove(block.getLocation()); + } blocksToDestroy.add(block); } } @@ -90,6 +95,10 @@ private void breakBlocks(BlockBreakEvent e, Player p, ItemStack item, Block b, L } else { for (Block block : blocks) { if (canBreak(p, block)) { + if (CustomBlock.byAlreadyPlaced(block) != null) { + drops.addAll(CustomBlock.byAlreadyPlaced(block).getLoot()); + CustomBlock.remove(block.getLocation()); + } blocksToDestroy.add(block); } } @@ -137,8 +146,6 @@ protected boolean canBreak(@Nonnull Player p, @Nonnull Block b) { return false; } else if (!b.getWorld().getWorldBorder().isInside(b.getLocation())) { return false; - } else if (Slimefun.getIntegrations().isCustomBlock(b)) { - return false; } else { return Slimefun.getProtectionManager().hasPermission(p, b.getLocation(), Interaction.BREAK_BLOCK); } From e032437b7154d2c1ed7f2d064dd2f16a9a8d379f Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Mon, 4 Sep 2023 10:28:52 +0200 Subject: [PATCH 038/131] make use of the intergration manager --- .../slimefun4/implementation/items/tools/ExplosiveTool.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java index 9f71e881d9..6fe1174e4f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java @@ -84,7 +84,7 @@ private void breakBlocks(BlockBreakEvent e, Player p, ItemStack item, Block b, L if (!blockExplodeEvent.isCancelled()) { for (Block block : blockExplodeEvent.blockList()) { if (canBreak(p, block)) { - if (CustomBlock.byAlreadyPlaced(block) != null) { + if (Slimefun.getIntegrations().isCustomBlock(block)) { drops.addAll(CustomBlock.byAlreadyPlaced(block).getLoot()); CustomBlock.remove(block.getLocation()); } @@ -95,7 +95,7 @@ private void breakBlocks(BlockBreakEvent e, Player p, ItemStack item, Block b, L } else { for (Block block : blocks) { if (canBreak(p, block)) { - if (CustomBlock.byAlreadyPlaced(block) != null) { + if (Slimefun.getIntegrations().isCustomBlock(block)) { drops.addAll(CustomBlock.byAlreadyPlaced(block).getLoot()); CustomBlock.remove(block.getLocation()); } From dc2cdadc3ca7e7e4ba2cc2919e3be496af20812d Mon Sep 17 00:00:00 2001 From: iTwins Date: Thu, 7 Sep 2023 02:29:15 +0200 Subject: [PATCH 039/131] pass BlockPosition to onCancel --- .../slimefun4/core/machines/MachineOperation.java | 3 ++- .../slimefun4/core/machines/MachineProcessor.java | 2 +- .../implementation/items/geo/GEOMiner.java | 2 +- .../operations/GEOMiningOperation.java | 13 +++++-------- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineOperation.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineOperation.java index ff211b4594..3da6569b6c 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineOperation.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineOperation.java @@ -1,5 +1,6 @@ package io.github.thebusybiscuit.slimefun4.core.machines; +import io.github.bakedlibs.dough.blocks.BlockPosition; import io.github.thebusybiscuit.slimefun4.core.attributes.MachineProcessHolder; /** @@ -61,6 +62,6 @@ default boolean isFinished() { * This method is called when a {@link MachineOperation} is interrupted before finishing. * Implement to specify behaviour that should happen in this case. */ - default void onCancel() {} + default void onCancel(BlockPosition position) {} } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java index f8064c5c78..c1e69b39c8 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java @@ -231,7 +231,7 @@ public boolean endOperation(@Nonnull BlockPosition pos) { Event event = new AsyncMachineOperationFinishEvent(pos, this, operation); Bukkit.getPluginManager().callEvent(event); } else { - operation.onCancel(); + operation.onCancel(pos); } return true; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java index 951f56ac45..d0f8c21b62 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java @@ -335,7 +335,7 @@ private void start(@Nonnull Block b, @Nonnull BlockMenu inv) { return; } - processor.startOperation(b, new GEOMiningOperation(resource, b, PROCESSING_TIME)); + processor.startOperation(b, new GEOMiningOperation(resource, PROCESSING_TIME)); Slimefun.getGPSNetwork().getResourceManager().setSupplies(resource, b.getWorld(), b.getX() >> 4, b.getZ() >> 4, supplies - 1); updateHologram(b, "&7Mining: &r" + resource.getName()); return; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java index 912e05e5b2..372f9f502c 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/GEOMiningOperation.java @@ -4,8 +4,7 @@ import javax.annotation.Nonnull; -import org.bukkit.block.Block; - +import io.github.bakedlibs.dough.blocks.BlockPosition; import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource; import io.github.thebusybiscuit.slimefun4.api.geo.ResourceManager; import io.github.thebusybiscuit.slimefun4.core.machines.MachineOperation; @@ -23,12 +22,10 @@ public class GEOMiningOperation extends MiningOperation { private final GEOResource resource; - private final Block block; - public GEOMiningOperation(@Nonnull GEOResource resource, @Nonnull Block block, int totalTicks) { + public GEOMiningOperation(@Nonnull GEOResource resource, int totalTicks) { super(resource.getItem().clone(), totalTicks); this.resource = resource; - this.block = block; } /** @@ -36,10 +33,10 @@ public GEOMiningOperation(@Nonnull GEOResource resource, @Nonnull Block block, i * when the {@link GEOMiningOperation} gets cancelled */ @Override - public void onCancel() { + public void onCancel(@Nonnull BlockPosition position) { ResourceManager resourceManager = Slimefun.getGPSNetwork().getResourceManager(); - OptionalInt supplies = resourceManager.getSupplies(resource, block.getWorld(), block.getX() >> 4, block.getZ() >> 4); - supplies.ifPresent(s -> resourceManager.setSupplies(resource, block.getWorld(), block.getX() >> 4, block.getZ() >> 4, s + 1)); + OptionalInt supplies = resourceManager.getSupplies(resource, position.getWorld(), position.getChunkX(), position.getChunkZ()); + supplies.ifPresent(s -> resourceManager.setSupplies(resource, position.getWorld(), position.getChunkX(), position.getChunkZ(), s + 1)); } } From 051c51915e26de4f01961bfc180c5e37c40cda7d Mon Sep 17 00:00:00 2001 From: iTwins Date: Thu, 7 Sep 2023 05:33:42 +0200 Subject: [PATCH 040/131] fix sensitive blocks attached to sf blocks not dropping (1.19+) --- .../listeners/BlockListener.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index 30593427ee..75a9cdba8c 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -14,6 +14,7 @@ import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; +import org.bukkit.block.data.BlockData; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -25,6 +26,7 @@ import org.bukkit.inventory.meta.ItemMeta; import io.github.bakedlibs.dough.protection.Interaction; +import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.api.events.ExplosiveToolBreakBlocksEvent; import io.github.thebusybiscuit.slimefun4.api.events.SlimefunBlockBreakEvent; import io.github.thebusybiscuit.slimefun4.api.events.SlimefunBlockPlaceEvent; @@ -53,6 +55,8 @@ */ public class BlockListener implements Listener { + private static final BlockFace[] CARDINAL_BLOCKFACES = new BlockFace[]{BlockFace.WEST, BlockFace.EAST, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.DOWN, BlockFace.UP}; + public BlockListener(@Nonnull Slimefun plugin) { plugin.getServer().getPluginManager().registerEvents(this, plugin); } @@ -152,6 +156,9 @@ public void onBlockBreak(BlockBreakEvent e) { } callBlockHandler(e, item, drops, sfItem); + + checkForSensitiveBlocks(e.getBlock(), 0); + dropItems(e, drops); } } @@ -222,6 +229,52 @@ private void dropItems(BlockBreakEvent e, List drops) { } } + /** + * This method checks recursively for any sensitive blocks + * that are no longer supported due to this block breaking + * + * @param block + * The {@link Block} in question + * @param c + * The amount of times this has been recursively called + */ + @ParametersAreNonnullByDefault + private void checkForSensitiveBlocks(Block block, Integer c) { + if (c >= Bukkit.getServer().getMaxChainedNeighborUpdates()) { + return; + } + for (BlockFace face : CARDINAL_BLOCKFACES) { + block.setType(Material.AIR, false); + if (!isSupported(block.getRelative(face).getBlockData(), block.getRelative(face))) { + Block relative = block.getRelative(face); + for (ItemStack drop : relative.getDrops()) { + block.getWorld().dropItemNaturally(relative.getLocation(), drop); + } + checkForSensitiveBlocks(relative, ++c); + } + } + } + + /** + * This method checks if the {@link BlockData} would be + * supported at the given {@link Block}. + * + * @param blockData + * The {@link BlockData} to check + * @param block + * The {@link Block} the {@link BlockData} would be at + * @return + * Whether the {@link BlockData} would be supported at the given {@link Block} + */ + private boolean isSupported(BlockData blockData, Block block) { + if (Slimefun.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_19)) { + return blockData.isSupported(block); + } else { + // TODO: Make 1.16-1.18 version. BlockData::isSupported is 1.19+. + return true; + } + } + /** * This method checks for a sensitive {@link Block}. * Sensitive {@link Block Blocks} are pressure plates or saplings, which should be broken From 9c5114f9c274899923807b946a34f402895cfc45 Mon Sep 17 00:00:00 2001 From: iTwins Date: Thu, 7 Sep 2023 05:41:25 +0200 Subject: [PATCH 041/131] annotation --- .../slimefun4/implementation/listeners/BlockListener.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index 75a9cdba8c..b919ac0980 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -266,6 +266,7 @@ private void checkForSensitiveBlocks(Block block, Integer c) { * @return * Whether the {@link BlockData} would be supported at the given {@link Block} */ + @ParametersAreNonnullByDefault private boolean isSupported(BlockData blockData, Block block) { if (Slimefun.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_19)) { return blockData.isSupported(block); From 67fd5183f813a0e92ed38ae0cbf9ee9e7989d9cd Mon Sep 17 00:00:00 2001 From: ybw0014 Date: Thu, 7 Sep 2023 00:39:03 -0400 Subject: [PATCH 042/131] fix: add version check --- .../implementation/items/weapons/SwordOfBeheading.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java index 17b91d534a..9c9f500608 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java @@ -5,6 +5,8 @@ import javax.annotation.ParametersAreNonnullByDefault; +import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import org.bukkit.Material; import org.bukkit.entity.Creeper; import org.bukkit.entity.Monster; @@ -80,7 +82,8 @@ public EntityKillHandler getItemHandler() { } } case PIGLIN -> { - if (random.nextInt(100) < chancePiglin.getValue()) { + if (Slimefun.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_20) && + random.nextInt(100) < chancePiglin.getValue()) { e.getDrops().add(new ItemStack(Material.PIGLIN_HEAD)); } } From 660f57b3b992fd767f9ce2f8a3c8f8e4829ff1ca Mon Sep 17 00:00:00 2001 From: ybw0014 Date: Thu, 7 Sep 2023 00:43:27 -0400 Subject: [PATCH 043/131] chore: fix import order --- .../implementation/items/weapons/SwordOfBeheading.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java index 9c9f500608..ce40980ded 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java @@ -5,8 +5,6 @@ import javax.annotation.ParametersAreNonnullByDefault; -import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; -import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import org.bukkit.Material; import org.bukkit.entity.Creeper; import org.bukkit.entity.Monster; @@ -19,12 +17,14 @@ import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.SkullMeta; +import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; import io.github.thebusybiscuit.slimefun4.core.handlers.EntityKillHandler; +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem; /** From d4b6c0aac8d510fcc1bab2f19f877ce95c371822 Mon Sep 17 00:00:00 2001 From: iTwins Date: Sat, 9 Sep 2023 16:46:14 +0200 Subject: [PATCH 044/131] renamed c to count --- .../slimefun4/implementation/listeners/BlockListener.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index b919ac0980..46152d988e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -235,12 +235,12 @@ private void dropItems(BlockBreakEvent e, List drops) { * * @param block * The {@link Block} in question - * @param c + * @param count * The amount of times this has been recursively called */ @ParametersAreNonnullByDefault - private void checkForSensitiveBlocks(Block block, Integer c) { - if (c >= Bukkit.getServer().getMaxChainedNeighborUpdates()) { + private void checkForSensitiveBlocks(Block block, Integer count) { + if (count >= Bukkit.getServer().getMaxChainedNeighborUpdates()) { return; } for (BlockFace face : CARDINAL_BLOCKFACES) { @@ -250,7 +250,7 @@ private void checkForSensitiveBlocks(Block block, Integer c) { for (ItemStack drop : relative.getDrops()) { block.getWorld().dropItemNaturally(relative.getLocation(), drop); } - checkForSensitiveBlocks(relative, ++c); + checkForSensitiveBlocks(relative, ++count); } } } From 76f3652615b8a5c0a230f0b4f7e0890b8e549ecc Mon Sep 17 00:00:00 2001 From: iTwins Date: Sat, 9 Sep 2023 17:35:19 +0200 Subject: [PATCH 045/131] capitalized Chosen --- src/main/resources/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index f906fd3754..c77b5463b8 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -87,4 +87,4 @@ research-ranks: - Excellent Master - Great Master - Proficient Master -- The chosen One +- The Chosen One From 62cb0b25b6095d79bf096dbd1e0c556950872b08 Mon Sep 17 00:00:00 2001 From: iTwins Date: Mon, 18 Sep 2023 14:53:33 +0200 Subject: [PATCH 046/131] fixed generating geo resources every scan --- .../thebusybiscuit/slimefun4/api/geo/ResourceManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/geo/ResourceManager.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/geo/ResourceManager.java index 3e93255b72..ce4fea9b02 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/geo/ResourceManager.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/geo/ResourceManager.java @@ -237,7 +237,7 @@ public void scan(@Nonnull Player p, @Nonnull Block block, int page) { for (int i = page * 28; i < resources.size() && i < (page + 1) * 28; i++) { GEOResource resource = resources.get(i); OptionalInt optional = getSupplies(resource, block.getWorld(), x, z); - int supplies = optional.orElse(generate(resource, block.getWorld(), x, block.getY(), z)); + int supplies = optional.orElseGet(() -> generate(resource, block.getWorld(), x, block.getY(), z)); String suffix = Slimefun.getLocalization().getResourceString(p, ChatUtils.checkPlurality("tooltips.unit", supplies)); ItemStack item = new CustomItemStack(resource.getItem(), "&f" + resource.getName(p), "&8\u21E8 &e" + supplies + ' ' + suffix); From 4ee2253a0244371a4210642d639cdc929e01c475 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 24 Sep 2023 22:16:31 +0000 Subject: [PATCH 047/131] Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2a2d47bf35..e5a0cbec47 100644 --- a/pom.xml +++ b/pom.xml @@ -191,7 +191,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.5.1 From 57a9fc68367d7265a016bb4fa207a5c3a28f1048 Mon Sep 17 00:00:00 2001 From: Jeroen <48769316+iTwins@users.noreply.github.com> Date: Tue, 26 Sep 2023 12:26:33 +0200 Subject: [PATCH 048/131] fix breaking sf block with not unlocked item duping contents (#3976) --- .../implementation/listeners/BlockListener.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index 30593427ee..f5cd298116 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -141,15 +141,15 @@ public void onBlockBreak(BlockBreakEvent e) { } } - if (!e.isCancelled()) { - checkForSensitiveBlockAbove(e.getPlayer(), e.getBlock(), item); + List drops = new ArrayList<>(); + if (!item.getType().isAir()) { int fortune = getBonusDropsWithFortune(item, e.getBlock()); - List drops = new ArrayList<>(); + callToolHandler(e, item, fortune, drops); + } - if (!item.getType().isAir()) { - callToolHandler(e, item, fortune, drops); - } + if (!e.isCancelled()) { + checkForSensitiveBlockAbove(e.getPlayer(), e.getBlock(), item); callBlockHandler(e, item, drops, sfItem); dropItems(e, drops); From 05e5e336585e43f349a27317e7ac8730f390d7a7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Sep 2023 12:48:21 +0200 Subject: [PATCH 049/131] [CI skip] Update actions/setup-java action to v3.13.0 --- .github/workflows/discord-webhook.yml | 2 +- .github/workflows/maven-compiler.yml | 2 +- .github/workflows/pull-request.yml | 2 +- .github/workflows/sonarcloud.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/discord-webhook.yml b/.github/workflows/discord-webhook.yml index 14c37fc1ef..6511aa9e7d 100644 --- a/.github/workflows/discord-webhook.yml +++ b/.github/workflows/discord-webhook.yml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@v3.6.0 - name: Set up Java JDK 17 - uses: actions/setup-java@v3.12.0 + uses: actions/setup-java@v3.13.0 with: distribution: 'adopt' java-version: '17' diff --git a/.github/workflows/maven-compiler.yml b/.github/workflows/maven-compiler.yml index ab13b31e5c..4fadf4a8fe 100644 --- a/.github/workflows/maven-compiler.yml +++ b/.github/workflows/maven-compiler.yml @@ -28,7 +28,7 @@ jobs: uses: actions/checkout@v3 - name: Set up JDK 17 - uses: actions/setup-java@v3.12.0 + uses: actions/setup-java@v3.13.0 with: distribution: 'adopt' java-version: '17' diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index cb76b7412d..4715615ad5 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@v3 - name: Set up JDK 17 - uses: actions/setup-java@v3.12.0 + uses: actions/setup-java@v3.13.0 with: distribution: 'adopt' java-version: '17' diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 8128ed2ef2..478951919e 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -24,7 +24,7 @@ jobs: fetch-depth: 0 - name: Set up JDK 17 - uses: actions/setup-java@v3.12.0 + uses: actions/setup-java@v3.13.0 with: distribution: 'adopt' java-version: '17' From a350830124fc7e0795fb281d3171d1f7e8faff54 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Sep 2023 12:50:51 +0200 Subject: [PATCH 050/131] [CI skip] Update dependency me.clip:placeholderapi to v2.11.4 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2a2d47bf35..2eb293433f 100644 --- a/pom.xml +++ b/pom.xml @@ -460,7 +460,7 @@ me.clip placeholderapi - 2.11.3 + 2.11.4 provided From cf6910c9c14781f34b77e9bbb3e2bacfd3d64c34 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Sep 2023 12:51:46 +0200 Subject: [PATCH 051/131] [CI skip] Update actions/checkout action to v4 --- .github/workflows/discord-webhook.yml | 2 +- .github/workflows/json-validator.yml | 2 +- .github/workflows/maven-compiler.yml | 2 +- .github/workflows/pull-request.yml | 2 +- .github/workflows/release-candidates.yml | 2 +- .github/workflows/sonarcloud.yml | 2 +- .github/workflows/yaml-linter.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/discord-webhook.yml b/.github/workflows/discord-webhook.yml index 6511aa9e7d..fd2c92bf35 100644 --- a/.github/workflows/discord-webhook.yml +++ b/.github/workflows/discord-webhook.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.1.0 - name: Set up Java JDK 17 uses: actions/setup-java@v3.13.0 diff --git a/.github/workflows/json-validator.yml b/.github/workflows/json-validator.yml index 9d8364ceda..512a484828 100644 --- a/.github/workflows/json-validator.yml +++ b/.github/workflows/json-validator.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Validate wiki.json uses: docker://orrosenblatt/validate-json-action:latest@sha256:02370758b8b199e0477da11ecfdd498c75c561685056b5c31b925a4ab95df7f4 env: diff --git a/.github/workflows/maven-compiler.yml b/.github/workflows/maven-compiler.yml index 4fadf4a8fe..4145068aa7 100644 --- a/.github/workflows/maven-compiler.yml +++ b/.github/workflows/maven-compiler.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v3.13.0 diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 4715615ad5..adbffdfa74 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v3.13.0 diff --git a/.github/workflows/release-candidates.yml b/.github/workflows/release-candidates.yml index 1c279e172e..1f4bda442e 100644 --- a/.github/workflows/release-candidates.yml +++ b/.github/workflows/release-candidates.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: 'stable' diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 478951919e..8a179c78af 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.1.0 with: fetch-depth: 0 diff --git a/.github/workflows/yaml-linter.yml b/.github/workflows/yaml-linter.yml index 3d87edf772..a1e22c99c5 100644 --- a/.github/workflows/yaml-linter.yml +++ b/.github/workflows/yaml-linter.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: YAML Linter uses: ibiqlik/action-yamllint@v3.1.1 with: From 4a2d611e303a572fd247338dc52680766f3912e0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Sep 2023 12:52:01 +0200 Subject: [PATCH 052/131] [CI skip] Update dependency com.github.LoneDev6:itemsadder-api to v3.5.0c-r5 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2eb293433f..32554a3d76 100644 --- a/pom.xml +++ b/pom.xml @@ -488,7 +488,7 @@ com.github.LoneDev6 itemsadder-api - 3.5.0b + 3.5.0c-r5 provided From 5d49162fc67600cf4d19db754d1ec54dacd33988 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Sep 2023 12:52:11 +0200 Subject: [PATCH 053/131] [CI skip] Update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.6.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 32554a3d76..c98348e2f1 100644 --- a/pom.xml +++ b/pom.xml @@ -239,7 +239,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.5.0 + 3.6.0 ${project.basedir} From 467f880102dc43f7b071cd53e3f5033e4cf9377d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Sep 2023 12:52:20 +0200 Subject: [PATCH 054/131] [CI skip] Update dependency org.sonarsource.scanner.maven:sonar-maven-plugin to v3.10.0.2594 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c98348e2f1..595b82a272 100644 --- a/pom.xml +++ b/pom.xml @@ -158,7 +158,7 @@ org.sonarsource.scanner.maven sonar-maven-plugin - 3.9.1.2184 + 3.10.0.2594 From 81c1fcc71a1e08b0a3f7941b08d5bfb3ac21e5ea Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 02:59:52 +0200 Subject: [PATCH 055/131] [CI skip] Update dependency com.sk89q.worldedit:worldedit-core to v7.2.16 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3694d852c2..544f3ce872 100644 --- a/pom.xml +++ b/pom.xml @@ -418,7 +418,7 @@ com.sk89q.worldedit worldedit-core - 7.2.15 + 7.2.16 provided From 1a8c8f65879948cc13fddcc62d370ee487489f60 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 03:00:09 +0200 Subject: [PATCH 056/131] [CI skip] Update dependency com.sk89q.worldedit:worldedit-bukkit to v7.2.16 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 544f3ce872..c613081fc8 100644 --- a/pom.xml +++ b/pom.xml @@ -432,7 +432,7 @@ com.sk89q.worldedit worldedit-bukkit - 7.2.15 + 7.2.16 provided From 1a1c7c2b51633111ea9d792a8f83e90a0d904ea2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Oct 2023 16:49:13 +0200 Subject: [PATCH 057/131] [CI skip] Update dependency com.gmail.nossr50.mcMMO:mcMMO to v2.1.224 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c613081fc8..8aced29566 100644 --- a/pom.xml +++ b/pom.xml @@ -446,7 +446,7 @@ com.gmail.nossr50.mcMMO mcMMO - 2.1.223 + 2.1.224 provided From 4746cbc6f935a9d5b26e7613e7b3b00c5d83d9f3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 7 Oct 2023 22:27:14 +0200 Subject: [PATCH 058/131] [CI skip] Update dependency org.mockito:mockito-core to v5.6.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8aced29566..de54e8ee1b 100644 --- a/pom.xml +++ b/pom.xml @@ -389,7 +389,7 @@ org.mockito mockito-core - 5.5.0 + 5.6.0 test From 7472552e1e45e8074247ff05f845ac1650f5ef67 Mon Sep 17 00:00:00 2001 From: iTwins Date: Sun, 8 Oct 2023 03:39:25 +0200 Subject: [PATCH 059/131] added compatibility for the 1.20 smithing table --- .../crafting/SmithingTableListener.java | 38 +++-- .../listeners/TestSmithingTableListener.java | 154 +++++++++++++++--- 2 files changed, 159 insertions(+), 33 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/SmithingTableListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/SmithingTableListener.java index 745a63736a..dd1567f778 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/SmithingTableListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/SmithingTableListener.java @@ -2,14 +2,13 @@ import javax.annotation.Nonnull; -import org.bukkit.entity.Player; import org.bukkit.event.Event.Result; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.ItemStack; +import org.bukkit.event.inventory.PrepareSmithingEvent; +import org.bukkit.event.inventory.SmithItemEvent; +import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; @@ -18,6 +17,7 @@ * smithing table. * * @author Sefiraat + * @author iTwins */ public class SmithingTableListener implements SlimefunCraftingListener { @@ -26,15 +26,29 @@ public SmithingTableListener(@Nonnull Slimefun plugin) { } @EventHandler(ignoreCancelled = true) - public void onSmith(InventoryClickEvent e) { - if (e.getInventory().getType() == InventoryType.SMITHING && e.getRawSlot() == 2 && e.getWhoClicked() instanceof Player) { - ItemStack materialItem = e.getInventory().getContents()[1]; - - // Checks if the item in the Material/Netherite slot is allowed to be used. - if (isUnallowed(materialItem)) { - e.setResult(Result.DENY); - Slimefun.getLocalization().sendMessage(e.getWhoClicked(), "smithing_table.not-working", true); + public void onSmith(SmithItemEvent e) { + SlimefunItem sfItem = SlimefunItem.getByItem(e.getInventory().getContents()[materialSlot()]); + if (sfItem != null && !sfItem.isUseableInWorkbench()) { + e.setResult(Result.DENY); + Slimefun.getLocalization().sendMessage(e.getWhoClicked(), "smithing_table.not-working", true); + } + } + + @EventHandler(ignoreCancelled = true) + public void onPrepareSmith(PrepareSmithingEvent e) { + if (e.getInventory().getResult() != null) { + SlimefunItem sfItem = SlimefunItem.getByItem(e.getInventory().getContents()[materialSlot()]); + if (sfItem != null && !sfItem.isUseableInWorkbench()) { + e.setResult(null); } } } + + private int materialSlot() { + if (Slimefun.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_20)) { + return 2; + } + return 1; + } + } diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TestSmithingTableListener.java b/src/test/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TestSmithingTableListener.java index 472a90c9a1..3c57ed5060 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TestSmithingTableListener.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TestSmithingTableListener.java @@ -1,21 +1,26 @@ package io.github.thebusybiscuit.slimefun4.implementation.listeners; +import be.seeseemelk.mockbukkit.MockBukkit; +import be.seeseemelk.mockbukkit.ServerMock; + +import org.apache.commons.lang3.mutable.MutableObject; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.Event.Result; import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryAction; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.InventoryType.SlotType; -import org.bukkit.inventory.Inventory; +import org.bukkit.event.inventory.PrepareSmithingEvent; +import org.bukkit.event.inventory.SmithItemEvent; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.SmithingInventory; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import io.github.bakedlibs.dough.items.CustomItemStack; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; @@ -24,15 +29,13 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.SmithingTableListener; import io.github.thebusybiscuit.slimefun4.test.TestUtilities; -import be.seeseemelk.mockbukkit.MockBukkit; -import be.seeseemelk.mockbukkit.ServerMock; - class TestSmithingTableListener { private static SmithingTableListener listener; private static ServerMock server; private static SlimefunItem slimefunIngot; + private static SlimefunItem usableSlimefunIngot; private static SlimefunItem slimefunTool; private static VanillaItem vanillaIngot; private static VanillaItem vanillaTool; @@ -45,11 +48,15 @@ public static void load() { slimefunTool = TestUtilities.mockSlimefunItem(plugin, "MOCK_DIAMOND_SWORD", new CustomItemStack(Material.DIAMOND_SWORD, "&6Mock")); slimefunIngot = TestUtilities.mockSlimefunItem(plugin, "MOCK_NETHERITE_INGOT", new CustomItemStack(Material.NETHERITE_INGOT, "&6Mock")); + usableSlimefunIngot = TestUtilities.mockSlimefunItem(plugin, "MOCK_NETHERITE_INGOT_USABLE", new CustomItemStack(Material.NETHERITE_INGOT, "&6Mock")); + usableSlimefunIngot.setUseableInWorkbench(true); + vanillaTool = TestUtilities.mockVanillaItem(plugin, Material.DIAMOND_SWORD, true); vanillaIngot = TestUtilities.mockVanillaItem(plugin, Material.NETHERITE_INGOT, true); slimefunTool.register(plugin); slimefunIngot.register(plugin); + usableSlimefunIngot.register(plugin); vanillaTool.register(plugin); vanillaIngot.register(plugin); } @@ -59,77 +66,182 @@ public static void unload() { MockBukkit.unmock(); } - private InventoryClickEvent mockSmithingEvent(ItemStack tool, ItemStack material) { + private SmithItemEvent mockSmithingEvent(ItemStack tool, ItemStack material) { Player player = server.addPlayer(); - Inventory inv = TestUtilities.mockInventory(InventoryType.SMITHING, tool, material, null); + + SmithingInventory inv = Mockito.mock(SmithingInventory.class); + // MinecraftVersion#isAtLeast always returns true during unit test, so we use the 1.20 layout here. + Mockito.when(inv.getContents()).thenReturn(new ItemStack[] { new ItemStack(Material.NETHERITE_UPGRADE_SMITHING_TEMPLATE), tool, material, null }); + InventoryView view = player.openInventory(inv); - InventoryClickEvent event = new InventoryClickEvent(view, SlotType.CONTAINER, 2, ClickType.LEFT, InventoryAction.PICKUP_ONE); + SmithItemEvent event = new SmithItemEvent(view, SlotType.RESULT, 3, ClickType.LEFT, InventoryAction.PICKUP_ONE); listener.onSmith(event); return event; } + private PrepareSmithingEvent mockPrepareSmithingEvent(ItemStack tool, ItemStack material) { + Player player = server.addPlayer(); + + SmithingInventory inv = Mockito.mock(SmithingInventory.class); + MutableObject result = new MutableObject<>(new ItemStack(Material.NETHERITE_PICKAXE)); + + Mockito.doAnswer(invocation -> { + ItemStack argument = invocation.getArgument(0); + result.setValue(argument); + return null; + }).when(inv).setResult(Mockito.any()); + + Mockito.when(inv.getResult()).thenAnswer(invocation -> result.getValue()); + // MinecraftVersion#isAtLeast always returns true during unit test, so we use the 1.20 layout here. + Mockito.when(inv.getContents()).thenReturn(new ItemStack[] { new ItemStack(Material.NETHERITE_UPGRADE_SMITHING_TEMPLATE), tool, material, null }); + + InventoryView view = player.openInventory(inv); + PrepareSmithingEvent event = new PrepareSmithingEvent(view, result.getValue()); + + listener.onPrepareSmith(event); + return event; + } + @Test @DisplayName("Test that vanilla is unchanged (ItemStack tool x ItemStack material)") void testSmithingTableWithItemStacks() { - InventoryClickEvent event = mockSmithingEvent(new ItemStack(Material.DIAMOND_SWORD), new ItemStack(Material.NETHERITE_INGOT)); + SmithItemEvent event = mockSmithingEvent(new ItemStack(Material.DIAMOND_SWORD), new ItemStack(Material.NETHERITE_INGOT)); Assertions.assertEquals(Result.DEFAULT, event.getResult()); } @Test @DisplayName("Test that SlimefunItem material doesn't work (ItemStack tool x SlimefunItem material)") void testSmithingTableWithItemStackAndSlimefunItem() { - InventoryClickEvent event = mockSmithingEvent(new ItemStack(Material.DIAMOND_SWORD), slimefunIngot.getItem()); + SmithItemEvent event = mockSmithingEvent(new ItemStack(Material.DIAMOND_SWORD), slimefunIngot.getItem()); Assertions.assertEquals(Result.DENY, event.getResult()); } @Test @DisplayName("Test that VanillaItem material works (ItemStack tool x VanillaItem material)") void testSmithingTableWithItemStackAndVanillaItem() { - InventoryClickEvent event = mockSmithingEvent(new ItemStack(Material.DIAMOND_SWORD), vanillaIngot.getItem()); + SmithItemEvent event = mockSmithingEvent(new ItemStack(Material.DIAMOND_SWORD), vanillaIngot.getItem()); Assertions.assertEquals(Result.DEFAULT, event.getResult()); } @Test @DisplayName("Test that SlimefunItems can upgrade with vanilla (SlimefunItem tool x ItemStack material)") void testSmithingTableWithSlimefunItemAndItemStack() { - InventoryClickEvent event = mockSmithingEvent(slimefunTool.getItem(), new ItemStack(Material.NETHERITE_INGOT)); + SmithItemEvent event = mockSmithingEvent(slimefunTool.getItem(), new ItemStack(Material.NETHERITE_INGOT)); Assertions.assertEquals(Result.DEFAULT, event.getResult()); } @Test @DisplayName("Test that SlimefunItems can't upgrade with SlimefunItem materials (SlimefunItem tool x SlimefunItem material)") void testSmithingTableWithSlimefunItems() { - InventoryClickEvent event = mockSmithingEvent(slimefunTool.getItem(), slimefunIngot.getItem()); + SmithItemEvent event = mockSmithingEvent(slimefunTool.getItem(), slimefunIngot.getItem()); Assertions.assertEquals(Result.DENY, event.getResult()); } @Test @DisplayName("Test that SlimefunItems can upgrade with VanillaItems (SlimefunItem tool x VanillaItem material)") void testSmithingTableWithSlimefunItemAndVanillaItem() { - InventoryClickEvent event = mockSmithingEvent(slimefunTool.getItem(), vanillaIngot.getItem()); + SmithItemEvent event = mockSmithingEvent(slimefunTool.getItem(), vanillaIngot.getItem()); Assertions.assertEquals(Result.DEFAULT, event.getResult()); } @Test - @DisplayName("Test that SlimefunItems can upgrade with vanilla (SlimefunItem tool x ItemStack material)") + @DisplayName("Test that VanillaItems can upgrade with vanilla (VanillaItem tool x ItemStack material)") void testSmithingTableWithVanillaItemAndItemStack() { - InventoryClickEvent event = mockSmithingEvent(vanillaTool.getItem(), new ItemStack(Material.NETHERITE_INGOT)); + SmithItemEvent event = mockSmithingEvent(vanillaTool.getItem(), new ItemStack(Material.NETHERITE_INGOT)); Assertions.assertEquals(Result.DEFAULT, event.getResult()); } @Test - @DisplayName("Test that SlimefunItems can't upgrade with SlimefunItem materials (SlimefunItem tool x SlimefunItem material)") + @DisplayName("Test that VanillaItems can't upgrade with SlimefunItem materials (VanillaItem tool x SlimefunItem material)") void testSmithingTableWithVanillaItemAndSlimefunItem() { - InventoryClickEvent event = mockSmithingEvent(vanillaTool.getItem(), slimefunIngot.getItem()); + SmithItemEvent event = mockSmithingEvent(vanillaTool.getItem(), slimefunIngot.getItem()); Assertions.assertEquals(Result.DENY, event.getResult()); } @Test - @DisplayName("Test that SlimefunItems can upgrade with VanillaItems (SlimefunItem tool x VanillaItem material)") + @DisplayName("Test that VanillaItems can upgrade with VanillaItems (VanillaItem tool x VanillaItem material)") void testSmithingTableWithVanillaItemAndVanillaItem() { - InventoryClickEvent event = mockSmithingEvent(vanillaTool.getItem(), vanillaIngot.getItem()); + SmithItemEvent event = mockSmithingEvent(vanillaTool.getItem(), vanillaIngot.getItem()); Assertions.assertEquals(Result.DEFAULT, event.getResult()); } + @Test + @DisplayName("Test that ItemStacks can be upgraded with SlimefunItem can-be-used-in-workbenches: true") + void testCanBeUsedInWorkbenchTrue() { + Assertions.assertTrue(usableSlimefunIngot.isUseableInWorkbench()); + SmithItemEvent event = mockSmithingEvent(new ItemStack(Material.DIAMOND_SWORD), usableSlimefunIngot.getItem()); + Assertions.assertEquals(Result.DEFAULT, event.getResult()); + } + + @Test + @DisplayName("Test that vanilla is unchanged (ItemStack tool x ItemStack material)") + void testPrepareSmithingTableWithItemStacks() { + PrepareSmithingEvent event = mockPrepareSmithingEvent(new ItemStack(Material.DIAMOND_SWORD), new ItemStack(Material.NETHERITE_INGOT)); + Assertions.assertNotNull(event.getResult()); + } + + @Test + @DisplayName("Test that SlimefunItem material doesn't work (ItemStack tool x SlimefunItem material)") + void testPrepareSmithingTableWithItemStackAndSlimefunItem() { + PrepareSmithingEvent event = mockPrepareSmithingEvent(new ItemStack(Material.DIAMOND_SWORD), slimefunIngot.getItem()); + Assertions.assertNull(event.getResult()); + } + + @Test + @DisplayName("Test that VanillaItem material works (ItemStack tool x VanillaItem material)") + void testPrepareSmithingTableWithItemStackAndVanillaItem() { + PrepareSmithingEvent event = mockPrepareSmithingEvent(new ItemStack(Material.DIAMOND_SWORD), vanillaIngot.getItem()); + Assertions.assertNotNull(event.getResult()); + } + + @Test + @DisplayName("Test that SlimefunItems can upgrade with vanilla (SlimefunItem tool x ItemStack material)") + void testPrepareSmithingTableWithSlimefunItemAndItemStack() { + PrepareSmithingEvent event = mockPrepareSmithingEvent(slimefunTool.getItem(), new ItemStack(Material.NETHERITE_INGOT)); + Assertions.assertNotNull(event.getResult()); + } + + @Test + @DisplayName("Test that SlimefunItems can't upgrade with SlimefunItem materials (SlimefunItem tool x SlimefunItem material)") + void testPrepareSmithingTableWithSlimefunItems() { + PrepareSmithingEvent event = mockPrepareSmithingEvent(slimefunTool.getItem(), slimefunIngot.getItem()); + Assertions.assertNull(event.getResult()); + } + + @Test + @DisplayName("Test that SlimefunItems can upgrade with VanillaItems (SlimefunItem tool x VanillaItem material)") + void testPrepareSmithingTableWithSlimefunItemAndVanillaItem() { + PrepareSmithingEvent event = mockPrepareSmithingEvent(slimefunTool.getItem(), vanillaIngot.getItem()); + Assertions.assertNotNull(event.getResult()); + } + + @Test + @DisplayName("Test that VanillaItems can upgrade with vanilla (VanillaItem tool x ItemStack material)") + void testPrepareSmithingTableWithVanillaItemAndItemStack() { + PrepareSmithingEvent event = mockPrepareSmithingEvent(vanillaTool.getItem(), new ItemStack(Material.NETHERITE_INGOT)); + Assertions.assertNotNull(event.getResult()); + } + + @Test + @DisplayName("Test that VanillaItems can't upgrade with SlimefunItem materials (VanillaItem tool x SlimefunItem material)") + void testPrepareSmithingTableWithVanillaItemAndSlimefunItem() { + PrepareSmithingEvent event = mockPrepareSmithingEvent(vanillaTool.getItem(), slimefunIngot.getItem()); + Assertions.assertNull(event.getResult()); + } + + @Test + @DisplayName("Test that VanillaItems can upgrade with VanillaItems (VanillaItem tool x VanillaItem material)") + void testPrepareSmithingTableWithVanillaItemAndVanillaItem() { + PrepareSmithingEvent event = mockPrepareSmithingEvent(vanillaTool.getItem(), vanillaIngot.getItem()); + Assertions.assertNotNull(event.getResult()); + } + + @Test + @DisplayName("Test that ItemStacks can be upgraded with SlimefunItem can-be-used-in-workbenches: true") + void testPrepareCanBeUsedInWorkbenchTrue() { + PrepareSmithingEvent event = mockPrepareSmithingEvent(new ItemStack(Material.DIAMOND_SWORD), usableSlimefunIngot.getItem()); + Assertions.assertNotNull(event.getResult()); + } + } From c977454e9430a56d295a5c3146a3f3529f712ce1 Mon Sep 17 00:00:00 2001 From: Jeroen <48769316+iTwins@users.noreply.github.com> Date: Mon, 9 Oct 2023 20:54:31 +0200 Subject: [PATCH 060/131] updated dough version (#3991) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index de54e8ee1b..fb6167b886 100644 --- a/pom.xml +++ b/pom.xml @@ -355,7 +355,7 @@ com.github.baked-libs.dough dough-api - d3b0997226 + e0ba50b254 compile From 9cc955d75eab4f584418998d8567f92736590ce4 Mon Sep 17 00:00:00 2001 From: Silent Date: Sun, 15 Oct 2023 01:39:20 -0700 Subject: [PATCH 061/131] Optional player for SlimefunItemSpawnEvent --- .../api/events/SlimefunItemSpawnEvent.java | 24 +++++++++++++++++++ .../items/altar/AncientPedestal.java | 2 +- .../items/seasonal/ChristmasPresent.java | 2 +- .../implementation/items/tools/GoldPan.java | 2 +- .../items/tools/PickaxeOfContainment.java | 2 +- .../slimefun4/utils/SlimefunUtils.java | 17 +++++++++++++ 6 files changed, 45 insertions(+), 4 deletions(-) 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 index 27f544e7e8..14dc2b4abf 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunItemSpawnEvent.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunItemSpawnEvent.java @@ -1,10 +1,14 @@ package io.github.thebusybiscuit.slimefun4.api.events; +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.Location; +import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; @@ -29,6 +33,7 @@ public class SlimefunItemSpawnEvent extends Event implements Cancellable { private ItemStack itemStack; private boolean cancelled; private final ItemSpawnReason itemSpawnReason; + private final Player player; @ParametersAreNonnullByDefault public SlimefunItemSpawnEvent(Location location, ItemStack itemStack, ItemSpawnReason itemSpawnReason) { @@ -36,6 +41,25 @@ public SlimefunItemSpawnEvent(Location location, ItemStack itemStack, ItemSpawnR this.itemStack = itemStack; this.itemSpawnReason = itemSpawnReason; this.cancelled = false; + this.player = null; + } + + @ParametersAreNonnullByDefault + public SlimefunItemSpawnEvent(@Nullable Player player, Location location, ItemStack itemStack, ItemSpawnReason itemSpawnReason) { + this.location = location; + this.itemStack = itemStack; + this.itemSpawnReason = itemSpawnReason; + this.cancelled = false; + this.player = player; + } + + /** + * Optionally returns the {@link Player} responsible for this spawn reason. + * + * @return The player responsible if applicable. + */ + public Optional getPlayer() { + return Optional.ofNullable(player); } /** 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 99a7b15585..f0a4fa95c0 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 @@ -167,7 +167,7 @@ public void placeItem(@Nonnull Player p, @Nonnull Block b) { ItemUtils.consumeItem(hand, false); } - Item entity = SlimefunUtils.spawnItem(b.getLocation().add(0.5, 1.2, 0.5), displayItem, ItemSpawnReason.ANCIENT_PEDESTAL_PLACE_ITEM); + Item entity = SlimefunUtils.spawnItem(p, b.getLocation().add(0.5, 1.2, 0.5), displayItem, ItemSpawnReason.ANCIENT_PEDESTAL_PLACE_ITEM, false); if (entity != null) { ArmorStand armorStand = getArmorStand(b, true); 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 f4cc010628..3d16205a8f 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 @@ -55,7 +55,7 @@ public ChristmasPresent(ItemGroup itemGroup, SlimefunItemStack item, RecipeType Block b = block.getRelative(e.getClickedFace()); ItemStack gift = gifts[ThreadLocalRandom.current().nextInt(gifts.length)].clone(); - SlimefunUtils.spawnItem(b.getLocation(), gift, ItemSpawnReason.CHRISTMAS_PRESENT_OPENED, true); + SlimefunUtils.spawnItem(e.getPlayer(), b.getLocation(), gift, ItemSpawnReason.CHRISTMAS_PRESENT_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 01478526cb..d7c0fb52b2 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 @@ -154,7 +154,7 @@ public void updateRandomizer() { // Make sure that the randomly selected item is not air if (output.getType() != Material.AIR) { - SlimefunUtils.spawnItem(b.getLocation(), output.clone(), ItemSpawnReason.GOLD_PAN_USE, true); + SlimefunUtils.spawnItem(e.getPlayer(), 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 c8064299a0..6be4cc5d71 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 @@ -50,7 +50,7 @@ public PickaxeOfContainment(ItemGroup itemGroup, SlimefunItemStack item, RecipeT if (b.getType() == Material.SPAWNER) { ItemStack spawner = breakSpawner(b); - SlimefunUtils.spawnItem(b.getLocation(), spawner, ItemSpawnReason.BROKEN_SPAWNER_DROP, true); + SlimefunUtils.spawnItem(e.getPlayer(), b.getLocation(), spawner, ItemSpawnReason.BROKEN_SPAWNER_DROP, true); e.setExpToDrop(0); e.setDropItems(false); 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 f57aaf4ac7..ada4a7db6f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java @@ -610,6 +610,23 @@ public static boolean canPlayerUseItem(@Nonnull Player p, @Nullable ItemStack it } } + public static @Nullable Item spawnItem(Player player, Location loc, ItemStack item, ItemSpawnReason reason, boolean addRandomOffset) { + SlimefunItemSpawnEvent event = new SlimefunItemSpawnEvent(player, loc, item, reason); + Slimefun.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 From 4636d66e77747143eaf34c9773d4d19468f6436c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 10:59:14 +0200 Subject: [PATCH 062/131] [CI skip] Update dependency com.github.LoneDev6:itemsadder-api to v3.6.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fb6167b886..60d89b0641 100644 --- a/pom.xml +++ b/pom.xml @@ -488,7 +488,7 @@ com.github.LoneDev6 itemsadder-api - 3.5.0c-r5 + 3.6.1 provided From 2b0645b9027ad97b7889fa88da46cb38a188c942 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 10:59:26 +0200 Subject: [PATCH 063/131] [CI skip] Update dependency com.sk89q.worldedit:worldedit-core to v7.2.17 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 60d89b0641..bd96bd192a 100644 --- a/pom.xml +++ b/pom.xml @@ -418,7 +418,7 @@ com.sk89q.worldedit worldedit-core - 7.2.16 + 7.2.17 provided From fad16e4543fab7d72b85c1b05c9faa06ac02fa8a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 10:59:33 +0200 Subject: [PATCH 064/131] [CI skip] Update dependency com.sk89q.worldedit:worldedit-bukkit to v7.2.17 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bd96bd192a..6d23ccde81 100644 --- a/pom.xml +++ b/pom.xml @@ -432,7 +432,7 @@ com.sk89q.worldedit worldedit-bukkit - 7.2.16 + 7.2.17 provided From bd4ca3e72fe156b20dfb9913943bc39f89d42cbe Mon Sep 17 00:00:00 2001 From: Silent <46107752+TheSilentPro@users.noreply.github.com> Date: Sun, 15 Oct 2023 03:47:31 -0700 Subject: [PATCH 065/131] Update src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunItemSpawnEvent.java Mark optional as nonnull Co-authored-by: TheBusyBiscuit --- .../slimefun4/api/events/SlimefunItemSpawnEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 14dc2b4abf..f7aa63f3e0 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunItemSpawnEvent.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunItemSpawnEvent.java @@ -58,7 +58,7 @@ public SlimefunItemSpawnEvent(@Nullable Player player, Location location, ItemSt * * @return The player responsible if applicable. */ - public Optional getPlayer() { + public @Nonnull Optional getPlayer() { return Optional.ofNullable(player); } From 7a8780bbae5b17e398d4e0c8b1da7306f50dcab7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 14:02:09 +0200 Subject: [PATCH 066/131] [CI skip] Update dependency com.gmail.nossr50.mcMMO:mcMMO to v2.1.225 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6d23ccde81..c065f4ff68 100644 --- a/pom.xml +++ b/pom.xml @@ -446,7 +446,7 @@ com.gmail.nossr50.mcMMO mcMMO - 2.1.224 + 2.1.225 provided From 5527729109108e7c262a38ee9c883d4bf9240854 Mon Sep 17 00:00:00 2001 From: Silent Date: Mon, 16 Oct 2023 14:24:10 -0700 Subject: [PATCH 067/131] Reduce repeated code --- .../api/events/SlimefunItemSpawnEvent.java | 12 ++---- .../items/altar/AncientPedestal.java | 2 +- .../items/seasonal/ChristmasPresent.java | 2 +- .../implementation/items/tools/GoldPan.java | 2 +- .../items/tools/PickaxeOfContainment.java | 2 +- .../slimefun4/utils/SlimefunUtils.java | 40 +++++++++++-------- 6 files changed, 31 insertions(+), 29 deletions(-) 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 index 14dc2b4abf..07d284050d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunItemSpawnEvent.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/SlimefunItemSpawnEvent.java @@ -36,21 +36,17 @@ public class SlimefunItemSpawnEvent extends Event implements Cancellable { private final Player player; @ParametersAreNonnullByDefault - public SlimefunItemSpawnEvent(Location location, ItemStack itemStack, ItemSpawnReason itemSpawnReason) { + public SlimefunItemSpawnEvent(@Nullable Player player, Location location, ItemStack itemStack, ItemSpawnReason itemSpawnReason) { this.location = location; this.itemStack = itemStack; this.itemSpawnReason = itemSpawnReason; this.cancelled = false; - this.player = null; + this.player = player; } @ParametersAreNonnullByDefault - public SlimefunItemSpawnEvent(@Nullable Player player, Location location, ItemStack itemStack, ItemSpawnReason itemSpawnReason) { - this.location = location; - this.itemStack = itemStack; - this.itemSpawnReason = itemSpawnReason; - this.cancelled = false; - this.player = player; + public SlimefunItemSpawnEvent(Location location, ItemStack itemStack, ItemSpawnReason itemSpawnReason) { + this(null, location, itemStack, itemSpawnReason); } /** 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 f0a4fa95c0..bbf19d36d8 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 @@ -167,7 +167,7 @@ public void placeItem(@Nonnull Player p, @Nonnull Block b) { ItemUtils.consumeItem(hand, false); } - Item entity = SlimefunUtils.spawnItem(p, b.getLocation().add(0.5, 1.2, 0.5), displayItem, ItemSpawnReason.ANCIENT_PEDESTAL_PLACE_ITEM, false); + Item entity = SlimefunUtils.spawnItem(b.getLocation().add(0.5, 1.2, 0.5), displayItem, ItemSpawnReason.ANCIENT_PEDESTAL_PLACE_ITEM, false, p); if (entity != null) { ArmorStand armorStand = getArmorStand(b, true); 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 3d16205a8f..37ec6cc244 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 @@ -55,7 +55,7 @@ public ChristmasPresent(ItemGroup itemGroup, SlimefunItemStack item, RecipeType Block b = block.getRelative(e.getClickedFace()); ItemStack gift = gifts[ThreadLocalRandom.current().nextInt(gifts.length)].clone(); - SlimefunUtils.spawnItem(e.getPlayer(), b.getLocation(), gift, ItemSpawnReason.CHRISTMAS_PRESENT_OPENED, true); + SlimefunUtils.spawnItem(b.getLocation(), gift, ItemSpawnReason.CHRISTMAS_PRESENT_OPENED, true, e.getPlayer()); }); }; } 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 d7c0fb52b2..08f69ec27a 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 @@ -154,7 +154,7 @@ public void updateRandomizer() { // Make sure that the randomly selected item is not air if (output.getType() != Material.AIR) { - SlimefunUtils.spawnItem(e.getPlayer(), b.getLocation(), output.clone(), ItemSpawnReason.GOLD_PAN_USE, true); + SlimefunUtils.spawnItem(b.getLocation(), output.clone(), ItemSpawnReason.GOLD_PAN_USE, true, e.getPlayer()); } } } 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 6be4cc5d71..86499f2bee 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 @@ -50,7 +50,7 @@ public PickaxeOfContainment(ItemGroup itemGroup, SlimefunItemStack item, RecipeT if (b.getType() == Material.SPAWNER) { ItemStack spawner = breakSpawner(b); - SlimefunUtils.spawnItem(e.getPlayer(), b.getLocation(), spawner, ItemSpawnReason.BROKEN_SPAWNER_DROP, true); + SlimefunUtils.spawnItem(b.getLocation(), spawner, ItemSpawnReason.BROKEN_SPAWNER_DROP, true, e.getPlayer()); e.setExpToDrop(0); e.setDropItems(false); 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 ada4a7db6f..be19a2b5ab 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java @@ -589,12 +589,14 @@ public static boolean canPlayerUseItem(@Nonnull Player p, @Nullable ItemStack it * The {@link ItemSpawnReason} why the item is being dropped * @param addRandomOffset * Whether a random offset should be added (see {@link World#dropItemNaturally(Location, ItemStack)}) + * @param player + * The player that caused this {@link org.bukkit.event.entity.ItemSpawnEvent} * * @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); + public static @Nullable Item spawnItem(Location loc, ItemStack item, ItemSpawnReason reason, boolean addRandomOffset, @Nullable Player player) { + SlimefunItemSpawnEvent event = new SlimefunItemSpawnEvent(player, loc, item, reason); Slimefun.instance().getServer().getPluginManager().callEvent(event); if (!event.isCancelled()) { @@ -610,21 +612,25 @@ public static boolean canPlayerUseItem(@Nonnull Player p, @Nullable ItemStack it } } - public static @Nullable Item spawnItem(Player player, Location loc, ItemStack item, ItemSpawnReason reason, boolean addRandomOffset) { - SlimefunItemSpawnEvent event = new SlimefunItemSpawnEvent(player, loc, item, reason); - Slimefun.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 + * @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) { + return spawnItem(loc, item, reason, addRandomOffset, null); } /** From cb736d314e28b59f89f3f9ddf92ece2ca0e9e246 Mon Sep 17 00:00:00 2001 From: Silent Date: Mon, 16 Oct 2023 23:27:25 -0700 Subject: [PATCH 068/131] fix qualifier --- .../io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 be19a2b5ab..5fc3bda47f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java @@ -590,7 +590,7 @@ public static boolean canPlayerUseItem(@Nonnull Player p, @Nullable ItemStack it * @param addRandomOffset * Whether a random offset should be added (see {@link World#dropItemNaturally(Location, ItemStack)}) * @param player - * The player that caused this {@link org.bukkit.event.entity.ItemSpawnEvent} + * The player that caused this {@link SlimefunItemSpawnEvent} * * @return The dropped {@link Item} (or null if the {@link SlimefunItemSpawnEvent} was cancelled) */ From 82b89673d8bb8c4ae2fe792fb23f3d45c11d38d2 Mon Sep 17 00:00:00 2001 From: Kub94ekCZ <145360194+Kub94ekCZ@users.noreply.github.com> Date: Wed, 25 Oct 2023 16:43:48 +0200 Subject: [PATCH 069/131] Update ButcherAndroidListener.java Fixed bug with emerald drop from vindicators when killed by Butcher Android --- .../implementation/listeners/ButcherAndroidListener.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ButcherAndroidListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ButcherAndroidListener.java index 1432edd1dd..793698641a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ButcherAndroidListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ButcherAndroidListener.java @@ -88,5 +88,9 @@ private void addExtraDrops(List drops, EntityType entityType) { if (entityType == EntityType.BLAZE) { drops.add(new ItemStack(Material.BLAZE_ROD, 1 + random.nextInt(1))); } + + if (entityType == EntityType.VINDICATOR) { + drops.add(new Itemstack(Material.EMERALD, 1 + random.nextInt(2))); + } } } From 4215e1b1f9bfb461ba9d95d37bd02e68cc37fea6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Nov 2023 13:20:44 +0100 Subject: [PATCH 070/131] [CI skip] Update dependency org.jacoco:jacoco-maven-plugin to v0.8.11 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c065f4ff68..336dfd261f 100644 --- a/pom.xml +++ b/pom.xml @@ -165,7 +165,7 @@ org.jacoco jacoco-maven-plugin - 0.8.10 + 0.8.11 From db53568f669965e0dce880b6ff3933714c342c76 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Nov 2023 13:20:50 +0100 Subject: [PATCH 071/131] [CI skip] Update actions/checkout action to v4.1.1 --- .github/workflows/discord-webhook.yml | 2 +- .github/workflows/sonarcloud.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/discord-webhook.yml b/.github/workflows/discord-webhook.yml index fd2c92bf35..a34070de5d 100644 --- a/.github/workflows/discord-webhook.yml +++ b/.github/workflows/discord-webhook.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Set up Java JDK 17 uses: actions/setup-java@v3.13.0 diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 8a179c78af..06abb9b2bf 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 with: fetch-depth: 0 From d8aaf87988d6b689b82892badce405ed07f8da5e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Nov 2023 13:20:57 +0100 Subject: [PATCH 072/131] [CI skip] Update thollander/actions-comment-pull-request action to v2.4.3 --- .github/workflows/pr-labels.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-labels.yml b/.github/workflows/pr-labels.yml index 3b8f8f3ebc..0636851f90 100644 --- a/.github/workflows/pr-labels.yml +++ b/.github/workflows/pr-labels.yml @@ -31,7 +31,7 @@ jobs: api: '🔧 API' compatibility: '🤝 Compatibility' - - uses: thollander/actions-comment-pull-request@v2.4.2 + - uses: thollander/actions-comment-pull-request@v2.4.3 name: Leave a comment about the applied label if: ${{ steps.labeller.outputs.applied != 0 }} with: @@ -40,7 +40,7 @@ jobs: Your Pull Request was automatically labelled as: "${{ steps.labeller.outputs.applied }}" Thank you for contributing to this project! ❤️ - - uses: thollander/actions-comment-pull-request@v2.4.2 + - uses: thollander/actions-comment-pull-request@v2.4.3 name: Leave a comment about our branch naming convention if: ${{ steps.labeller.outputs.applied == 0 }} with: From 092c5d667090fe4d698b05cb8d085fb5212a91c9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Nov 2023 13:21:20 +0100 Subject: [PATCH 073/131] [CI skip] Update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.2.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 336dfd261f..dcdd3fcef0 100644 --- a/pom.xml +++ b/pom.xml @@ -146,7 +146,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.1.2 + 3.2.1 org.junit.jupiter:junit-jupiter From 563ebec85626ed786755baa4322be8400a230864 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Nov 2023 13:21:23 +0100 Subject: [PATCH 074/131] [CI skip] Update dependency me.clip:placeholderapi to v2.11.5 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dcdd3fcef0..bde8ab6ecf 100644 --- a/pom.xml +++ b/pom.xml @@ -460,7 +460,7 @@ me.clip placeholderapi - 2.11.4 + 2.11.5 provided From 9135b3810ebf5622d494e75eb9442f0ecba67ca1 Mon Sep 17 00:00:00 2001 From: test137e29b Date: Fri, 10 Nov 2023 21:48:44 +0000 Subject: [PATCH 075/131] Add Yaw to GPS Waypoint Location --- .../slimefun4/implementation/items/gps/GPSMarkerTool.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSMarkerTool.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSMarkerTool.java index d677eea5b5..dd3d2f7f48 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSMarkerTool.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSMarkerTool.java @@ -36,7 +36,11 @@ public ItemUseHandler getItemHandler() { if (e.getClickedBlock().isPresent()) { Block b = e.getClickedBlock().get().getRelative(e.getClickedFace()); - Slimefun.getGPSNetwork().createWaypoint(e.getPlayer(), b.getLocation()); + Location l = b.getLocation(); + Location locationWithYaw = new Location( + l.getWorld(), l.getX(), l.getY(), l.getZ(), e.getPlayer().getLocation().getYaw(), 0.0f + ); + Slimefun.getGPSNetwork().createWaypoint(e.getPlayer(), locationWithYaw); } }; } From c8cb6ff7502114b8e09a6fbcdaf6906c26d966ef Mon Sep 17 00:00:00 2001 From: test137e29b Date: Sat, 11 Nov 2023 00:43:31 +0000 Subject: [PATCH 076/131] setYaw --- .../slimefun4/implementation/items/gps/GPSMarkerTool.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSMarkerTool.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSMarkerTool.java index dd3d2f7f48..65c430237a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSMarkerTool.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSMarkerTool.java @@ -37,10 +37,8 @@ public ItemUseHandler getItemHandler() { if (e.getClickedBlock().isPresent()) { Block b = e.getClickedBlock().get().getRelative(e.getClickedFace()); Location l = b.getLocation(); - Location locationWithYaw = new Location( - l.getWorld(), l.getX(), l.getY(), l.getZ(), e.getPlayer().getLocation().getYaw(), 0.0f - ); - Slimefun.getGPSNetwork().createWaypoint(e.getPlayer(), locationWithYaw); + l.setYaw(e.getPlayer().getLocation().getYaw()); + Slimefun.getGPSNetwork().createWaypoint(e.getPlayer(), l); } }; } From f48665da6d3668ecfa4c3972611a1cef03992737 Mon Sep 17 00:00:00 2001 From: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Date: Sat, 18 Nov 2023 19:18:04 -0600 Subject: [PATCH 077/131] Fix the case of SlimefunItem#itemhandlers --- .../slimefun4/api/items/SlimefunItem.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java index d3bc8368fd..20a12ef6b7 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java @@ -109,7 +109,7 @@ public class SlimefunItem implements Placeable { private Optional wikiURL = Optional.empty(); - private final OptionalMap, ItemHandler> itemhandlers = new OptionalMap<>(HashMap::new); + private final OptionalMap, ItemHandler> itemHandlers = new OptionalMap<>(HashMap::new); private final Set> itemSettings = new HashSet<>(); private boolean ticking = false; @@ -477,12 +477,12 @@ public void register(@Nonnull SlimefunAddon addon) { onEnable(); } else { // Clear item handlers if we are disabled so that calling them isn't possible later on - for (ItemHandler handler : this.itemhandlers.values()) { + for (ItemHandler handler : this.itemHandlers.values()) { if (handler instanceof BlockTicker) { Slimefun.getRegistry().getTickerBlocks().remove(getId()); } } - this.itemhandlers.clear(); + this.itemHandlers.clear(); } // Lock the SlimefunItemStack from any accidental manipulations @@ -540,7 +540,7 @@ private final void onEnable() { } private void loadItemHandlers() { - for (ItemHandler handler : itemhandlers.values()) { + for (ItemHandler handler : itemHandlers.values()) { Optional exception = handler.validate(this); // Check if the validation caused an exception. @@ -802,7 +802,7 @@ public final void addItemHandler(ItemHandler... handlers) { } for (ItemHandler handler : handlers) { - itemhandlers.put(handler.getIdentifier(), handler); + itemHandlers.put(handler.getIdentifier(), handler); // Tickers are a special case (at the moment at least) if (handler instanceof BlockTicker ticker) { @@ -914,7 +914,7 @@ public final void addOfficialWikipage(@Nonnull String page) { * @return The Set of item handlers */ public @Nonnull Collection getHandlers() { - return itemhandlers.values(); + return itemHandlers.values(); } /** @@ -932,7 +932,7 @@ public final void addOfficialWikipage(@Nonnull String page) { */ @ParametersAreNonnullByDefault public boolean callItemHandler(Class c, Consumer callable) { - Optional handler = itemhandlers.get(c); + Optional handler = itemHandlers.get(c); if (handler.isPresent()) { try { From 8783e7bccaa36a32fbc205b522b6388739361784 Mon Sep 17 00:00:00 2001 From: J3fftw <44972470+J3fftw1@users.noreply.github.com> Date: Mon, 20 Nov 2023 21:20:00 +0100 Subject: [PATCH 078/131] Update .github/workflows/e2e-testing.yml --- .github/workflows/e2e-testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index b4adf613f7..8044e9f63a 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -33,7 +33,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - - name: Set up JDK 17 + - name: Set up JDK uses: actions/setup-java@v3.11.0 with: distribution: temurin From ea9b2289aa8aa9296b8b1cf72ede4067abb6216f Mon Sep 17 00:00:00 2001 From: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Date: Tue, 21 Nov 2023 07:47:07 -0600 Subject: [PATCH 079/131] Fix typo --- .../implementation/listeners/ButcherAndroidListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ButcherAndroidListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ButcherAndroidListener.java index 793698641a..9e63107680 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ButcherAndroidListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ButcherAndroidListener.java @@ -90,7 +90,7 @@ private void addExtraDrops(List drops, EntityType entityType) { } if (entityType == EntityType.VINDICATOR) { - drops.add(new Itemstack(Material.EMERALD, 1 + random.nextInt(2))); + drops.add(new ItemStack(Material.EMERALD, 1 + random.nextInt(2))); } } } From 65dce9a43acdcb30aabaa013b9e9a198a7eb9bb6 Mon Sep 17 00:00:00 2001 From: J3fftw <44972470+J3fftw1@users.noreply.github.com> Date: Tue, 21 Nov 2023 20:40:32 +0100 Subject: [PATCH 080/131] Update .github/workflows/e2e-testing.yml --- .github/workflows/e2e-testing.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index 8044e9f63a..1033765601 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -10,7 +10,6 @@ on: jobs: e2e-testing: - name: End to End Testing runs-on: ubuntu-latest timeout-minutes: 5 From 4a0f76d27538d27dfd7ca7ae59e4bd664c661884 Mon Sep 17 00:00:00 2001 From: J3fftw <44972470+J3fftw1@users.noreply.github.com> Date: Tue, 21 Nov 2023 20:47:19 +0100 Subject: [PATCH 081/131] Update .github/workflows/e2e-testing.yml --- .github/workflows/e2e-testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index 1033765601..a18b1cf8d4 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -1,4 +1,4 @@ -name: End to End Testing +name: End to End Testings on: workflow_call: From 6b5e7a56dec2e9af6bf9406c2d50adc047694ab4 Mon Sep 17 00:00:00 2001 From: J3fftw <44972470+J3fftw1@users.noreply.github.com> Date: Tue, 21 Nov 2023 20:54:11 +0100 Subject: [PATCH 082/131] Update .github/workflows/e2e-testing.yml --- .github/workflows/e2e-testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index a18b1cf8d4..1033765601 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -1,4 +1,4 @@ -name: End to End Testings +name: End to End Testing on: workflow_call: From 63414033a6f05c2d8e2051326f4491a77dd475a7 Mon Sep 17 00:00:00 2001 From: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:07:00 -0600 Subject: [PATCH 083/131] Add MultiBlockCraftEvent (Updated version of #3439) (#3928) --- .../api/events/MultiBlockCraftEvent.java | 120 ++++++++++++++++++ .../items/multiblocks/AbstractSmeltery.java | 8 +- .../items/multiblocks/ArmorForge.java | 9 +- .../multiblocks/AutomatedPanningMachine.java | 16 ++- .../items/multiblocks/Compressor.java | 10 +- .../multiblocks/EnhancedCraftingTable.java | 9 +- .../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 +- 13 files changed, 234 insertions(+), 29 deletions(-) create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/api/events/MultiBlockCraftEvent.java 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..7a3fc3c535 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/MultiBlockCraftEvent.java @@ -0,0 +1,120 @@ +package io.github.thebusybiscuit.slimefun4.api.events; + +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; + +import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlockMachine; + +/** + * 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/multiblocks/AbstractSmeltery.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/AbstractSmeltery.java index e11e76b3c8..7f2f27f0cb 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 @@ -4,6 +4,7 @@ import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -14,6 +15,7 @@ import org.bukkit.inventory.ItemStack; 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; @@ -48,12 +50,14 @@ public void onInteract(Player p, Block b) { for (int i = 0; i < inputs.size(); i++) { 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 d8e7dae44b..4ee70ac722 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 @@ -4,6 +4,7 @@ import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -13,9 +14,9 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import io.github.thebusybiscuit.slimefun4.core.services.sounds.SoundEffect; 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; @@ -43,9 +44,11 @@ public void onInteract(Player p, Block b) { for (ItemStack[] input : inputs) { 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 c5e407404d..ca2d0c7124 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 @@ -7,6 +7,7 @@ import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.GameMode; import org.bukkit.Material; @@ -18,6 +19,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; @@ -74,6 +76,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); } @@ -82,13 +92,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 c799ae879c..f0b48882e6 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 @@ -6,6 +6,7 @@ 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; @@ -16,6 +17,7 @@ import org.bukkit.inventory.ItemStack; 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; @@ -66,13 +68,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 67b1ebbf58..4486197b62 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 @@ -4,6 +4,7 @@ import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -13,8 +14,8 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import io.github.thebusybiscuit.slimefun4.core.services.sounds.SoundEffect; 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; @@ -44,9 +45,11 @@ public void onInteract(Player p, Block b) { for (ItemStack[] input : inputs) { 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 140aa83f8d..f149093042 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 @@ -6,6 +6,7 @@ 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; @@ -16,6 +17,7 @@ import org.bukkit.inventory.ItemStack; import io.github.bakedlibs.dough.items.CustomItemStack; +import io.github.thebusybiscuit.slimefun4.api.events.MultiBlockCraftEvent; import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; @@ -126,12 +128,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 40978b05ca..a81c731434 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 @@ -6,6 +6,7 @@ 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; @@ -17,6 +18,7 @@ import org.bukkit.inventory.ItemStack; 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; @@ -62,12 +64,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 98cebcf884..25ce8cdcc8 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 @@ -4,6 +4,7 @@ import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; import org.bukkit.block.Block; @@ -15,6 +16,7 @@ import org.bukkit.inventory.ItemStack; 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; @@ -50,9 +52,11 @@ public void onInteract(Player p, Block b) { for (ItemStack[] input : inputs) { 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 2a0dad3d61..ea5141f099 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 @@ -7,6 +7,7 @@ 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; @@ -18,6 +19,7 @@ import org.bukkit.inventory.ItemStack; import io.github.bakedlibs.dough.items.CustomItemStack; +import io.github.thebusybiscuit.slimefun4.api.events.MultiBlockCraftEvent; import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; @@ -190,13 +192,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 80dc6c6cc3..25a3282369 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 @@ -2,12 +2,12 @@ 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; @@ -18,6 +18,7 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +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; @@ -84,8 +85,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 @@ -93,15 +94,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) { /* @@ -119,7 +119,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); @@ -130,14 +135,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 4080aa31a0..c8b75de5a3 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 @@ -6,6 +6,7 @@ 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; @@ -17,6 +18,7 @@ import org.bukkit.inventory.ItemStack; 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; @@ -51,13 +53,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 0e920cbe04..40bb1b2fdd 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 @@ -8,6 +8,7 @@ import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.GameMode; import org.bukkit.Material; @@ -19,6 +20,7 @@ import org.bukkit.inventory.ItemStack; 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.core.multiblocks.MultiBlockMachine; @@ -107,11 +109,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()); } From 4fbe2a0dcc47100182fcc1241f334bbb158a7102 Mon Sep 17 00:00:00 2001 From: J3fftw <44972470+J3fftw1@users.noreply.github.com> Date: Tue, 21 Nov 2023 21:09:49 +0100 Subject: [PATCH 084/131] fix taking damage on head collision while wearing elytra cap (#3760) --- .../listeners/ElytraImpactListener.java | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) 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 344fe14471..02fc80c56c 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 @@ -1,9 +1,14 @@ package io.github.thebusybiscuit.slimefun4.implementation.listeners; +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; @@ -18,20 +23,35 @@ 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 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 p)) { @@ -39,7 +59,9 @@ public void onPlayerCrash(EntityDamageEvent e) { return; } - if (e.getCause() == DamageCause.FALL || e.getCause() == DamageCause.FLY_INTO_WALL && p.isGliding()) { + if ((e.getCause() == DamageCause.FALL || e.getCause() == DamageCause.FLY_INTO_WALL) + && (p.isGliding() || gliding.contains(p.getUniqueId())) + ) { Optional optional = PlayerProfile.find(p); if (optional.isEmpty()) { @@ -48,7 +70,7 @@ public void onPlayerCrash(EntityDamageEvent e) { } PlayerProfile profile = optional.get(); - Optional helmet = profile.getArmor()[0].getItem(); + Optional helmet = profile.getArmor()[3].getItem(); if (helmet.isPresent()) { SlimefunItem item = helmet.get(); From 6e01add949590442b579fd421dad4777a83b6831 Mon Sep 17 00:00:00 2001 From: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:10:12 -0600 Subject: [PATCH 085/131] Remove Lore Check from Slimefun Guide (#3969) --- .../implementation/listeners/SlimefunGuideListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 783dcf59f8..53897013a2 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 @@ -81,7 +81,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); From 52f5a14cfc7230f551899d260080fcb9ec00a17b Mon Sep 17 00:00:00 2001 From: Jeroen <48769316+iTwins@users.noreply.github.com> Date: Tue, 21 Nov 2023 21:12:10 +0100 Subject: [PATCH 086/131] don't consume bookbinder inputs if the output is worse than the input (#3925) Co-authored-by: Jeroen --- .../machines/enchanting/BookBinder.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) 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 c85e86070b..4ac521faa2 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 @@ -57,6 +57,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,11 @@ 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(25 * (enchantments.size() / this.getSpeed()), new ItemStack[] { target, item }, new ItemStack[] { book }); @@ -97,6 +106,19 @@ 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); From 6559cfe07d021c26182a22fbc2c386e45207c9a8 Mon Sep 17 00:00:00 2001 From: J3fftw <44972470+J3fftw1@users.noreply.github.com> Date: Wed, 22 Nov 2023 20:00:34 +0100 Subject: [PATCH 087/131] Update .github/workflows/e2e-testing.yml --- .github/workflows/e2e-testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index 1033765601..4f7d0e1d13 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -4,7 +4,7 @@ on: workflow_call: inputs: artifact-name: - description: 'Slimefun artifact name' + description: 'Slimefun artifact names' required: true type: string From 9b959d96c17f9fa7834116633f045d466079220d Mon Sep 17 00:00:00 2001 From: J3fftw <44972470+J3fftw1@users.noreply.github.com> Date: Wed, 22 Nov 2023 20:05:56 +0100 Subject: [PATCH 088/131] Update .github/workflows/e2e-testing.yml --- .github/workflows/e2e-testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index 4f7d0e1d13..1033765601 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -4,7 +4,7 @@ on: workflow_call: inputs: artifact-name: - description: 'Slimefun artifact names' + description: 'Slimefun artifact name' required: true type: string From b37c48599db04260b1383e0fc0567040131578de Mon Sep 17 00:00:00 2001 From: J3fftw <44972470+J3fftw1@users.noreply.github.com> Date: Wed, 22 Nov 2023 20:46:48 +0100 Subject: [PATCH 089/131] fix heads showing as steve (#4027) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bde8ab6ecf..229c6bddbb 100644 --- a/pom.xml +++ b/pom.xml @@ -355,7 +355,7 @@ com.github.baked-libs.dough dough-api - e0ba50b254 + 99381b2 compile From d87e26b47a662ab1c5d3466f17bc44210a91eca3 Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Wed, 22 Nov 2023 20:38:30 +0100 Subject: [PATCH 090/131] replace builds page with blob builds --- .../slimefun4/core/services/UpdaterService.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java index bea541fc28..68259b6b64 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java @@ -5,6 +5,7 @@ import javax.annotation.Nonnull; +import io.github.bakedlibs.dough.updater.BlobBuildUpdater; import org.bukkit.plugin.Plugin; import io.github.bakedlibs.dough.config.Config; @@ -53,7 +54,7 @@ public class UpdaterService { */ public UpdaterService(@Nonnull Slimefun plugin, @Nonnull String version, @Nonnull File file) { this.plugin = plugin; - GitHubBuildsUpdater autoUpdater = null; + BlobBuildUpdater autoUpdater = null; if (version.contains("UNOFFICIAL")) { // This Server is using a modified build that is not a public release. @@ -61,7 +62,7 @@ public UpdaterService(@Nonnull Slimefun plugin, @Nonnull String version, @Nonnul } else if (version.startsWith("DEV - ")) { // If we are using a development build, we want to switch to our custom try { - autoUpdater = new GitHubBuildsUpdater(plugin, file, "TheBusyBiscuit/Slimefun4/master"); + autoUpdater = new BlobBuildUpdater(plugin, file, "Slimefun4", "Dev"); } catch (Exception x) { plugin.getLogger().log(Level.SEVERE, "Failed to create AutoUpdater", x); } @@ -70,7 +71,7 @@ public UpdaterService(@Nonnull Slimefun plugin, @Nonnull String version, @Nonnul } else if (version.startsWith("RC - ")) { // If we are using a "stable" build, we want to switch to our custom try { - autoUpdater = new GitHubBuildsUpdater(plugin, file, "TheBusyBiscuit/Slimefun4/stable", "RC - "); + autoUpdater = new BlobBuildUpdater(plugin, file, "Slimefun4", "RC"); } catch (Exception x) { plugin.getLogger().log(Level.SEVERE, "Failed to create AutoUpdater", x); } From 60a90d80f230a958b9722844ed00bd4dd07865dd Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Wed, 22 Nov 2023 21:05:53 +0100 Subject: [PATCH 091/131] removed unused import --- .../thebusybiscuit/slimefun4/core/services/UpdaterService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java index 68259b6b64..00f0ce3bcf 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java @@ -9,7 +9,6 @@ import org.bukkit.plugin.Plugin; import io.github.bakedlibs.dough.config.Config; -import io.github.bakedlibs.dough.updater.GitHubBuildsUpdater; import io.github.bakedlibs.dough.updater.PluginUpdater; import io.github.bakedlibs.dough.versions.PrefixedVersion; import io.github.thebusybiscuit.slimefun4.api.SlimefunBranch; From 7288cf3bf3bd6127ad540f9c3e21ede119e13f31 Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Wed, 22 Nov 2023 21:17:06 +0100 Subject: [PATCH 092/131] pulled latest changes and changed the url --- .../thebusybiscuit/slimefun4/core/services/UpdaterService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java index 00f0ce3bcf..ebd5f971e6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java @@ -16,7 +16,7 @@ /** * This Class represents our {@link PluginUpdater} Service. - * If enabled, it will automatically connect to https://thebusybiscuit.github.io/builds/ + * If enabled, it will automatically connect to https://blob.build/ * to check for updates and to download them automatically. * * @author TheBusyBiscuit From 6af85d9ab957ad07c9e0701b1f95182a2088962e Mon Sep 17 00:00:00 2001 From: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Date: Thu, 23 Nov 2023 06:30:35 -0600 Subject: [PATCH 093/131] Fix freezer material --- .../thebusybiscuit/slimefun4/implementation/SlimefunItems.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java index d65a67bd34..8695759316 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java @@ -830,7 +830,7 @@ private SlimefunItems() {} public static final SlimefunItemStack FREEZER = new SlimefunItemStack("FREEZER", Material.LIGHT_BLUE_STAINED_GLASS, "&bFreezer", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerBuffer(256), LoreBuilder.powerPerSecond(18)); public static final SlimefunItemStack FREEZER_2 = new SlimefunItemStack("FREEZER_2", Material.LIGHT_BLUE_STAINED_GLASS, "&bFreezer &7(&eII&7)", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.speed(2), LoreBuilder.powerBuffer(256), LoreBuilder.powerPerSecond(30)); - public static final SlimefunItemStack FREEZER_3 = new SlimefunItemStack("FREEZER_3", Material.LIGHT_GRAY_STAINED_GLASS, "&bFreezer &7(&eIII&7)", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.speed(3), LoreBuilder.powerBuffer(256), LoreBuilder.powerPerSecond(42)); + public static final SlimefunItemStack FREEZER_3 = new SlimefunItemStack("FREEZER_3", Material.LIGHT_BLUE_STAINED_GLASS, "&bFreezer &7(&eIII&7)", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.speed(3), LoreBuilder.powerBuffer(256), LoreBuilder.powerPerSecond(42)); public static final SlimefunItemStack ELECTRIC_GOLD_PAN = new SlimefunItemStack("ELECTRIC_GOLD_PAN", Material.BROWN_TERRACOTTA, "&6Electric Gold Pan", "", LoreBuilder.machine(MachineTier.BASIC, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(2)); public static final SlimefunItemStack ELECTRIC_GOLD_PAN_2 = new SlimefunItemStack("ELECTRIC_GOLD_PAN_2", Material.BROWN_TERRACOTTA, "&6Electric Gold Pan &7(&eII&7)", "", LoreBuilder.machine(MachineTier.BASIC, MachineType.MACHINE), LoreBuilder.speed(3), LoreBuilder.powerPerSecond(4)); From 087e9857954352eecc8b449e527cb1c70b2420ad Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Fri, 24 Nov 2023 18:49:34 +0100 Subject: [PATCH 094/131] fix auto update --- .../thebusybiscuit/slimefun4/core/services/UpdaterService.java | 2 +- .../slimefun4/core/services/TestUpdaterService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java index ebd5f971e6..b556789a91 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/UpdaterService.java @@ -58,7 +58,7 @@ public UpdaterService(@Nonnull Slimefun plugin, @Nonnull String version, @Nonnul if (version.contains("UNOFFICIAL")) { // This Server is using a modified build that is not a public release. branch = SlimefunBranch.UNOFFICIAL; - } else if (version.startsWith("DEV - ")) { + } else if (version.startsWith("Dev - ")) { // If we are using a development build, we want to switch to our custom try { autoUpdater = new BlobBuildUpdater(plugin, file, "Slimefun4", "Dev"); diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/core/services/TestUpdaterService.java b/src/test/java/io/github/thebusybiscuit/slimefun4/core/services/TestUpdaterService.java index 9f76c65d42..4de8e01e62 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/core/services/TestUpdaterService.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/core/services/TestUpdaterService.java @@ -33,7 +33,7 @@ public static void unload() { @Test @DisplayName("Test if the development branch is recognized correctly") void testDevelopmentBuilds() { - UpdaterService service = new UpdaterService(plugin, "DEV - 131 (git 123456)", file); + UpdaterService service = new UpdaterService(plugin, "Dev - 131 (git 123456)", file); Assertions.assertEquals(SlimefunBranch.DEVELOPMENT, service.getBranch()); Assertions.assertTrue(service.getBranch().isOfficial()); // Cannot currently be tested... yay From 0589b21af395a87495be532c0f48893cf541c01a Mon Sep 17 00:00:00 2001 From: Sefiraat Date: Fri, 24 Nov 2023 21:40:19 +0000 Subject: [PATCH 095/131] Deny placement when deletion is queued (#3911) Co-authored-by: Daniel Walsh Co-authored-by: J3fftw <44972470+J3fftw1@users.noreply.github.com> --- .../listeners/BlockListener.java | 24 +++++-- src/main/resources/languages/en/messages.yml | 1 + .../events/TestSlimefunBlockBreakEvent.java | 26 +++++++- .../events/TestSlimefunBlockPlaceEvent.java | 66 ++++++++++++++++--- .../slimefun4/test/TestUtilities.java | 13 ++++ 5 files changed, 113 insertions(+), 17 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index f5cd298116..58d066aae7 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -90,20 +90,34 @@ public void onBlockPlace(BlockPlaceEvent e) { Slimefun.getProtectionManager().logAction(e.getPlayer(), e.getBlock(), Interaction.PLACE_BLOCK); } if (sfItem != null && !(sfItem instanceof NotPlaceable)) { - if (!sfItem.canUse(e.getPlayer(), true)) { + Player player = e.getPlayer(); + + if (!sfItem.canUse(player, true)) { e.setCancelled(true); } else { - SlimefunBlockPlaceEvent placeEvent = new SlimefunBlockPlaceEvent(e.getPlayer(), item, e.getBlock(), sfItem); + Block block = e.getBlockPlaced(); + + /* + * Resolves an issue when placing a block in a location currently in the deletion queue + * TODO This can be safely removed if/when the deletion no longer has a delay associated with it. + */ + if (Slimefun.getTickerTask().isDeletedSoon(block.getLocation())) { + Slimefun.getLocalization().sendMessage(player, "messages.await-deletion"); + e.setCancelled(true); + return; + } + + SlimefunBlockPlaceEvent placeEvent = new SlimefunBlockPlaceEvent(player, item, block, sfItem); Bukkit.getPluginManager().callEvent(placeEvent); if (placeEvent.isCancelled()) { e.setCancelled(true); } else { - if (Slimefun.getBlockDataService().isTileEntity(e.getBlock().getType())) { - Slimefun.getBlockDataService().setBlockData(e.getBlock(), sfItem.getId()); + if (Slimefun.getBlockDataService().isTileEntity(block.getType())) { + Slimefun.getBlockDataService().setBlockData(block, sfItem.getId()); } - BlockStorage.addBlockInfo(e.getBlock(), "id", sfItem.getId(), true); + BlockStorage.addBlockInfo(block, "id", sfItem.getId(), true); sfItem.callItemHandler(BlockPlaceHandler.class, handler -> handler.onPlayerPlace(e)); } } diff --git a/src/main/resources/languages/en/messages.yml b/src/main/resources/languages/en/messages.yml index f9c32a8115..81d5115c30 100644 --- a/src/main/resources/languages/en/messages.yml +++ b/src/main/resources/languages/en/messages.yml @@ -172,6 +172,7 @@ messages: bee-suit-slow-fall: '&eYour Bee Wings will help you to get back to the ground safe and slow' deprecated-item: '&4This item has been deprecated and will be removed from Slimefun soon.' researching-is-disabled: '&cResearching has been disabled on this server. Everything is unlocked by default!' + await-deletion: '&cYou cannot place a Slimefun block so soon after breaking one. Try again shortly.' multi-tool: mode-change: '&b%device% mode changed to: &9%mode%' diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/api/events/TestSlimefunBlockBreakEvent.java b/src/test/java/io/github/thebusybiscuit/slimefun4/api/events/TestSlimefunBlockBreakEvent.java index 2f94729d38..9eb9225213 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/api/events/TestSlimefunBlockBreakEvent.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/api/events/TestSlimefunBlockBreakEvent.java @@ -58,7 +58,7 @@ void testEventIsFired() { Player player = new PlayerMock(server, "SomePlayer"); World world = server.addSimpleWorld("my_world"); - Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, 1, 1, 1)); + Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, TestUtilities.randomInt(), 100, TestUtilities.randomInt())); Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world)); BlockStorage.addBlockInfo(block, "id", "FOOD_COMPOSTER"); @@ -75,7 +75,7 @@ void testGetters() { player.getInventory().setItemInMainHand(itemStack); World world = server.addSimpleWorld("my_world"); - Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, 1, 1, 1)); + Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, TestUtilities.randomInt(), 100, TestUtilities.randomInt())); Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world)); BlockStorage.addBlockInfo(block, "id", "FOOD_COMPOSTER"); @@ -106,7 +106,7 @@ public void onBlockBreak(SlimefunBlockBreakEvent event) { player.getInventory().setItemInMainHand(itemStack); World world = server.addSimpleWorld("my_world"); - Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, 1, 1, 1)); + Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, TestUtilities.randomInt(), 100, TestUtilities.randomInt())); Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world)); BlockStorage.addBlockInfo(block, "id", "FOOD_COMPOSTER"); @@ -119,4 +119,24 @@ public void onBlockBreak(SlimefunBlockBreakEvent event) { return true; }); } + + @Test + @DisplayName("Test that breaking a Slimefun block gets queued for deletion") + void testBlockBreaksGetQueuedForDeletion() { + Player player = new PlayerMock(server, "SomePlayer"); + ItemStack itemStack = new ItemStack(Material.IRON_PICKAXE); + player.getInventory().setItemInMainHand(itemStack); + + World world = server.addSimpleWorld("my_world"); + Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, TestUtilities.randomInt(), 100, TestUtilities.randomInt())); + + Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world)); + BlockStorage.addBlockInfo(block, "id", "FOOD_COMPOSTER"); + + BlockBreakEvent blockBreakEvent = new BlockBreakEvent(block, player); + server.getPluginManager().callEvent(blockBreakEvent); + server.getPluginManager().assertEventFired(SlimefunBlockBreakEvent.class, e -> true); + + Assertions.assertTrue(Slimefun.getTickerTask().isDeletedSoon(block.getLocation())); + } } diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/api/events/TestSlimefunBlockPlaceEvent.java b/src/test/java/io/github/thebusybiscuit/slimefun4/api/events/TestSlimefunBlockPlaceEvent.java index b599f13eb6..f6d8d2868d 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/api/events/TestSlimefunBlockPlaceEvent.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/api/events/TestSlimefunBlockPlaceEvent.java @@ -16,6 +16,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; @@ -61,9 +62,10 @@ void testEventIsFired() { player.getInventory().setItemInMainHand(itemStack); World world = server.addSimpleWorld("my_world"); - Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, 1, 1, 1)); - Block blockAgainst = new BlockMock(Material.GRASS, new Location(world, 1, 0, 1)); - BlockStorage.clearBlockInfo(block); + int x = TestUtilities.randomInt(); + int z = TestUtilities.randomInt(); + Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, x, 0, z)); + Block blockAgainst = new BlockMock(Material.GRASS, new Location(world, x, 1, z)); Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world)); @@ -83,9 +85,10 @@ void testGetters() { player.getInventory().setItemInMainHand(itemStack); World world = server.addSimpleWorld("my_world"); - Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, 1, 1, 1)); - Block blockAgainst = new BlockMock(Material.GRASS, new Location(world, 1, 0, 1)); - BlockStorage.clearBlockInfo(block); + int x = TestUtilities.randomInt(); + int z = TestUtilities.randomInt(); + Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, x, 0, z)); + Block blockAgainst = new BlockMock(Material.GRASS, new Location(world, x, 1, z)); Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world)); @@ -119,9 +122,10 @@ public void onBlockPlace(SlimefunBlockPlaceEvent event) { player.getInventory().setItemInMainHand(itemStack); World world = server.addSimpleWorld("my_world"); - Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, 1, 1, 1)); - Block blockAgainst = new BlockMock(Material.GRASS, new Location(world, 1, 0, 1)); - BlockStorage.clearBlockInfo(block); + int x = TestUtilities.randomInt(); + int z = TestUtilities.randomInt(); + Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, x, 0, z)); + Block blockAgainst = new BlockMock(Material.GRASS, new Location(world, x, 1, z)); Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world)); @@ -136,4 +140,48 @@ public void onBlockPlace(SlimefunBlockPlaceEvent event) { return true; }); } + + @Test + @DisplayName("Test that you cannot place before a SlimefunBlock is fully cleared") + void testBlockPlacementBeforeFullDeletion() { + Player player = new PlayerMock(server, "SomePlayer"); + ItemStack itemStack = slimefunItem.getItem(); + player.getInventory().setItemInMainHand(itemStack); + + // Place first block + World world = server.addSimpleWorld("my_world"); + int x = TestUtilities.randomInt(); + int z = TestUtilities.randomInt(); + Block firstBlock = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, x, 0, z)); + Block firstBlockAgainst = new BlockMock(Material.GRASS, new Location(world, x, 1, z)); + + Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world)); + + BlockPlaceEvent firstBlockPlaceEvent = new BlockPlaceEvent( + firstBlock, firstBlock.getState(), firstBlockAgainst, itemStack, player, true, EquipmentSlot.HAND + ); + + server.getPluginManager().callEvent(firstBlockPlaceEvent); + server.getPluginManager().assertEventFired(SlimefunBlockPlaceEvent.class, e -> { + Assertions.assertFalse(e.isCancelled()); + return true; + }); + + // Break block + server.getPluginManager().callEvent(new BlockBreakEvent(firstBlock, player)); + server.getPluginManager().assertEventFired(SlimefunBlockBreakEvent.class, e -> true); + + // Assert that the block is not fully deleted + Assertions.assertTrue(Slimefun.getTickerTask().isDeletedSoon(firstBlock.getLocation())); + + // Place second block in the same location + Block secondBlock = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, x, 0, z)); + Block secondBlockAgainst = new BlockMock(Material.GRASS, new Location(world, x, 1, z)); + + BlockPlaceEvent secondBlockPlaceEvent = new BlockPlaceEvent( + secondBlock, secondBlock.getState(), secondBlockAgainst, itemStack, player, true, EquipmentSlot.HAND + ); + server.getPluginManager().callEvent(secondBlockPlaceEvent); + Assertions.assertTrue(secondBlockPlaceEvent.isCancelled()); + } } diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/test/TestUtilities.java b/src/test/java/io/github/thebusybiscuit/slimefun4/test/TestUtilities.java index 0f520306aa..56f517da20 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/test/TestUtilities.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/test/TestUtilities.java @@ -2,6 +2,7 @@ import static org.mockito.Mockito.when; +import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; @@ -30,6 +31,8 @@ public final class TestUtilities { + private static final Random random = new Random(); + private TestUtilities() {} @ParametersAreNonnullByDefault @@ -76,4 +79,14 @@ private TestUtilities() {} latch.await(2, TimeUnit.SECONDS); return ref.get(); } + + @ParametersAreNonnullByDefault + public static @Nonnull int randomInt() { + return random.nextInt(Integer.MAX_VALUE); + } + + @ParametersAreNonnullByDefault + public static @Nonnull int randomInt(int upperBound) { + return random.nextInt(upperBound); + } } From b3e4e5aebbeb5f8da180bdeef74cd860ac7bd6cb Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Tue, 5 Dec 2023 22:50:22 +0100 Subject: [PATCH 096/131] e2e test on latest version --- .github/workflows/e2e-testing.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index 1033765601..126a4e6e94 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -25,7 +25,7 @@ jobs: javaVersion: '18' - mcVersion: '1.19.4' javaVersion: '19' - - mcVersion: '1.20.1' + - mcVersion: 'latest' javaVersion: '20' steps: @@ -48,10 +48,16 @@ jobs: - name: Download ${{ matrix.mcVersion }} Paper run: | VERSION="${{ matrix.mcVersion }}" + if [ "$VERSION" == "latest" ]; then + VERSION=$(curl https://api.papermc.io/v2/projects/paper/ -s | jq -r '.versions[-1]') + fi + 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}') + + echo "Downloading... https://api.papermc.io/v2/projects/paper/versions/$VERSION/builds/$BUILD/downloads/$JAR_FILE" curl -o paper.jar \ "https://api.papermc.io/v2/projects/paper/versions/$VERSION/builds/$BUILD/downloads/$JAR_FILE" From 6ce0911a1660df4c938260e3fb6c300c471af624 Mon Sep 17 00:00:00 2001 From: Jeroen <48769316+iTwins@users.noreply.github.com> Date: Tue, 5 Dec 2023 22:54:50 +0100 Subject: [PATCH 097/131] Add config option for radiation (#3988) --- .../thebusybiscuit/slimefun4/implementation/Slimefun.java | 6 +++++- src/main/resources/config.yml | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java index 2b8dd78f02..e8c7b460a1 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java @@ -367,9 +367,13 @@ private void onPluginStart() { // Armor Update Task if (config.getBoolean("options.enable-armor-effects")) { new SlimefunArmorTask().schedule(this, config.getInt("options.armor-update-interval") * 20L); - new RadiationTask().schedule(this, config.getInt("options.radiation-update-interval") * 20L); + if (config.getBoolean("options.enable-radiation")) { + new RadiationTask().schedule(this, config.getInt("options.radiation-update-interval") * 20L); + } new RainbowArmorTask().schedule(this, config.getInt("options.rainbow-armor-update-interval") * 20L); new SolarHelmetTask().schedule(this, config.getInt("options.armor-update-interval")); + } else if (config.getBoolean("options.enable-radiation")) { + logger.log(Level.WARNING, "Cannot enable radiation while armor effects are disabled."); } // Starting our tasks diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index c77b5463b8..ece2aa3410 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -8,6 +8,7 @@ options: chat-prefix: '&a&lSlimefun 4&7> ' armor-update-interval: 10 enable-armor-effects: true + enable-radiation: true radiation-update-interval: 1 radiation-grace-period: 15 rainbow-armor-update-interval: 3 From 5f9da5b146e12dde22b6023b859889f7f3340df0 Mon Sep 17 00:00:00 2001 From: Jeroen <48769316+iTwins@users.noreply.github.com> Date: Tue, 5 Dec 2023 22:56:23 +0100 Subject: [PATCH 098/131] Filter unlocked researches of player (#3996) --- .../slimefun4/api/player/PlayerProfile.java | 43 +++++++++++++------ .../slimefun4/api/researches/Research.java | 17 ++++++++ 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java index 2362a91d4a..7b975f5702 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java @@ -1,6 +1,7 @@ package io.github.thebusybiscuit.slimefun4.api.player; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -36,7 +37,6 @@ import io.github.thebusybiscuit.slimefun4.api.events.AsyncProfileLoadEvent; import io.github.thebusybiscuit.slimefun4.api.gps.Waypoint; import io.github.thebusybiscuit.slimefun4.api.items.HashedArmorpiece; -import io.github.thebusybiscuit.slimefun4.api.items.ItemState; import io.github.thebusybiscuit.slimefun4.api.researches.Research; import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectionType; import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectiveArmor; @@ -325,35 +325,52 @@ public final void markDirty() { return Optional.empty(); } - // returns the amount of researches with at least 1 enabled item - private int nonEmptyResearches() { - return (int) Slimefun.getRegistry().getResearches() - .stream() - .filter(research -> research.getAffectedItems().stream().anyMatch(item -> item.getState() == ItemState.ENABLED)) - .count(); + private int countNonEmptyResearches(@Nonnull Collection researches) { + int count = 0; + for (Research research : researches) { + if (research.hasEnabledItems()) { + count++; + } + } + return count; } + /** + * This method gets the research title, as defined in {@code config.yml}, + * of this {@link PlayerProfile} based on the fraction + * of unlocked {@link Research}es of this player. + * + * @return The research title of this {@link PlayerProfile} + */ public @Nonnull String getTitle() { List titles = Slimefun.getRegistry().getResearchRanks(); - float fraction = (float) researches.size() / nonEmptyResearches(); + int allResearches = countNonEmptyResearches(Slimefun.getRegistry().getResearches()); + float fraction = (float) countNonEmptyResearches(researches) / allResearches; int index = (int) (fraction * (titles.size() - 1)); return titles.get(index); } + /** + * This sends the statistics for the specified {@link CommandSender} + * to the {@link CommandSender}. This includes research title, research progress + * and total xp spent. + * + * @param sender The {@link CommandSender} for which to get the statistics and send them to. + */ public void sendStats(@Nonnull CommandSender sender) { - Set unlockedResearches = getResearches(); - int levels = unlockedResearches.stream().mapToInt(Research::getCost).sum(); - int allResearches = nonEmptyResearches(); + int unlockedResearches = countNonEmptyResearches(getResearches()); + int levels = getResearches().stream().mapToInt(Research::getCost).sum(); + int allResearches = countNonEmptyResearches(Slimefun.getRegistry().getResearches()); - float progress = Math.round(((unlockedResearches.size() * 100.0F) / allResearches) * 100.0F) / 100.0F; + float progress = Math.round(((unlockedResearches * 100.0F) / allResearches) * 100.0F) / 100.0F; sender.sendMessage(""); sender.sendMessage(ChatColors.color("&7Statistics for Player: &b" + name)); sender.sendMessage(""); sender.sendMessage(ChatColors.color("&7Title: " + ChatColor.AQUA + getTitle())); - sender.sendMessage(ChatColors.color("&7Research Progress: " + NumberUtils.getColorFromPercentage(progress) + progress + " &r% " + ChatColor.YELLOW + '(' + unlockedResearches.size() + " / " + allResearches + ')')); + sender.sendMessage(ChatColors.color("&7Research Progress: " + NumberUtils.getColorFromPercentage(progress) + progress + " &r% " + ChatColor.YELLOW + '(' + unlockedResearches + " / " + allResearches + ')')); sender.sendMessage(ChatColors.color("&7Total XP Levels spent: " + ChatColor.AQUA + levels)); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/researches/Research.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/researches/Research.java index 6a4ee6b528..c4c96e4e79 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/researches/Research.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/researches/Research.java @@ -22,6 +22,7 @@ import io.github.thebusybiscuit.slimefun4.api.events.PlayerPreResearchEvent; import io.github.thebusybiscuit.slimefun4.api.events.ResearchUnlockEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; +import io.github.thebusybiscuit.slimefun4.api.items.ItemState; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideImplementation; @@ -197,6 +198,22 @@ public List getAffectedItems() { return items; } + /** + * This method checks whether there is at least one enabled {@link SlimefunItem} + * included in this {@link Research}. + * + * @return whether there is at least one enabled {@link SlimefunItem} + * included in this {@link Research}. + */ + public boolean hasEnabledItems() { + for (SlimefunItem item : items) { + if (item.getState() == ItemState.ENABLED) { + return true; + } + } + return false; + } + /** * Handle what to do when a {@link Player} clicks on an un-researched item in * a {@link SlimefunGuideImplementation}. From 978b1a4d009e33b5ca670d1e1c95399bb137841d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 14:28:52 +0100 Subject: [PATCH 099/131] [CI skip] Update actions/setup-java action to v4 --- .github/workflows/discord-webhook.yml | 2 +- .github/workflows/e2e-testing.yml | 2 +- .github/workflows/maven-compiler.yml | 2 +- .github/workflows/pull-request.yml | 2 +- .github/workflows/sonarcloud.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/discord-webhook.yml b/.github/workflows/discord-webhook.yml index a34070de5d..3364a75bb1 100644 --- a/.github/workflows/discord-webhook.yml +++ b/.github/workflows/discord-webhook.yml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@v4.1.1 - name: Set up Java JDK 17 - uses: actions/setup-java@v3.13.0 + uses: actions/setup-java@v4.0.0 with: distribution: 'adopt' java-version: '17' diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index 126a4e6e94..d973289d91 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -33,7 +33,7 @@ jobs: uses: actions/checkout@v3 - name: Set up JDK - uses: actions/setup-java@v3.11.0 + uses: actions/setup-java@v4.0.0 with: distribution: temurin java-version: ${{ matrix.javaVersion }} diff --git a/.github/workflows/maven-compiler.yml b/.github/workflows/maven-compiler.yml index 4145068aa7..7529fdbd77 100644 --- a/.github/workflows/maven-compiler.yml +++ b/.github/workflows/maven-compiler.yml @@ -28,7 +28,7 @@ jobs: uses: actions/checkout@v4 - name: Set up JDK 17 - uses: actions/setup-java@v3.13.0 + uses: actions/setup-java@v4.0.0 with: distribution: 'adopt' java-version: '17' diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index b564ba9e26..89b9374dcf 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -22,7 +22,7 @@ jobs: uses: actions/checkout@v4 - name: Set up JDK 17 - uses: actions/setup-java@v3.13.0 + uses: actions/setup-java@v4.0.0 with: distribution: 'adopt' java-version: '17' diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 06abb9b2bf..6fe3823205 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -24,7 +24,7 @@ jobs: fetch-depth: 0 - name: Set up JDK 17 - uses: actions/setup-java@v3.13.0 + uses: actions/setup-java@v4.0.0 with: distribution: 'adopt' java-version: '17' From 9c02d9a5eb0f3d10e705e38ba98114d922bd21c1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 14:29:49 +0100 Subject: [PATCH 100/131] [CI skip] Update actions/checkout action to v4 --- .github/workflows/e2e-testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index d973289d91..0f7cc57413 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v4.0.0 From 5f3729a01b115e5bf87c65f5fed67ae63be8adc5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 14:30:15 +0100 Subject: [PATCH 101/131] [CI skip] Update actions/github-script action to v7 --- .github/workflows/preview-builds.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/preview-builds.yml b/.github/workflows/preview-builds.yml index 947ded7153..b9e7b5d26a 100644 --- a/.github/workflows/preview-builds.yml +++ b/.github/workflows/preview-builds.yml @@ -20,7 +20,7 @@ jobs: # Kinda jank way to grab the PR and commit hash and then download the artifact # TODO: Move this code to our own mini-action - name: Grab PR & run ID and download the artifact - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ From e81ed116e1e401e8843e6e68a64cd5ebfa1a4065 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 14:30:32 +0100 Subject: [PATCH 102/131] [CI skip] Update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.6.3 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 229c6bddbb..2f00ceea8c 100644 --- a/pom.xml +++ b/pom.xml @@ -239,7 +239,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.0 + 3.6.3 ${project.basedir} From 93829d800a92d4b4509baf89e06e5851a8be6f2a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 14:30:49 +0100 Subject: [PATCH 103/131] [CI skip] Update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.2.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2f00ceea8c..59ef2165cc 100644 --- a/pom.xml +++ b/pom.xml @@ -146,7 +146,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.1 + 3.2.2 org.junit.jupiter:junit-jupiter From 007309d29a330244050e30ef3fe7c32d25b95c00 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 14:33:07 +0100 Subject: [PATCH 104/131] [CI skip] Update dependency org.mockito:mockito-core to v5.8.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 59ef2165cc..714b7afedb 100644 --- a/pom.xml +++ b/pom.xml @@ -389,7 +389,7 @@ org.mockito mockito-core - 5.6.0 + 5.8.0 test From 88daec571d124613914fa9b97cb50a37f1fcac5b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 14:34:40 +0100 Subject: [PATCH 105/131] [CI skip] Update dependency org.slf4j:slf4j-simple to v2.0.9 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 714b7afedb..6984311b42 100644 --- a/pom.xml +++ b/pom.xml @@ -395,7 +395,7 @@ org.slf4j slf4j-simple - 2.0.7 + 2.0.9 test From d2f7486e082c855a19759e6af863d82ce06ad274 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 15:07:07 +0100 Subject: [PATCH 106/131] [CI skip] Update dependency org.junit.jupiter:junit-jupiter to v5.10.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6984311b42..fd065cb4a7 100644 --- a/pom.xml +++ b/pom.xml @@ -383,7 +383,7 @@ org.junit.jupiter junit-jupiter - 5.10.0 + 5.10.1 test From 530f375a1f1f24b2344a2f372ec20f221b30957f Mon Sep 17 00:00:00 2001 From: iTwins Date: Wed, 6 Dec 2023 20:27:05 +0100 Subject: [PATCH 107/131] revert unnecessary changes --- .../core/machines/MachineProcessor.java | 33 ++++++++-------- .../implementation/items/geo/GEOMiner.java | 38 ++++++++++--------- .../operations/MiningOperation.java | 9 ++--- 3 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java index c1e69b39c8..dd2349e196 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java @@ -6,8 +6,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import com.google.common.base.Preconditions; - +import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.block.Block; @@ -47,7 +46,7 @@ public class MachineProcessor { * The owner of this {@link MachineProcessor}. */ public MachineProcessor(@Nonnull MachineProcessHolder owner) { - Preconditions.checkArgument(owner != null, "The MachineProcessHolder cannot be null."); + Validate.notNull(owner, "The MachineProcessHolder cannot be null."); this.owner = owner; } @@ -94,8 +93,8 @@ public void setProgressBar(@Nullable ItemStack progressBar) { * {@link MachineOperation} has already been started at that {@link Location}. */ public boolean startOperation(@Nonnull Location loc, @Nonnull T operation) { - Preconditions.checkArgument(loc != null, "The location must not be null"); - Preconditions.checkArgument(operation != null, "The operation cannot be null"); + Validate.notNull(loc, "The location must not be null"); + Validate.notNull(operation, "The operation cannot be null"); return startOperation(new BlockPosition(loc), operation); } @@ -112,8 +111,8 @@ public boolean startOperation(@Nonnull Location loc, @Nonnull T operation) { * {@link MachineOperation} has already been started at that {@link Block}. */ public boolean startOperation(@Nonnull Block b, @Nonnull T operation) { - Preconditions.checkArgument(b != null, "The Block must not be null"); - Preconditions.checkArgument(operation != null, "The machine operation cannot be null"); + Validate.notNull(b, "The Block must not be null"); + Validate.notNull(operation, "The machine operation cannot be null"); return startOperation(new BlockPosition(b), operation); } @@ -130,8 +129,8 @@ public boolean startOperation(@Nonnull Block b, @Nonnull T operation) { * {@link MachineOperation} has already been started at that {@link BlockPosition}. */ public boolean startOperation(@Nonnull BlockPosition pos, @Nonnull T operation) { - Preconditions.checkArgument(pos != null, "The BlockPosition must not be null"); - Preconditions.checkArgument(operation != null, "The machine operation cannot be null"); + Validate.notNull(pos, "The BlockPosition must not be null"); + Validate.notNull(operation, "The machine operation cannot be null"); return machines.putIfAbsent(pos, operation) == null; } @@ -145,7 +144,7 @@ public boolean startOperation(@Nonnull BlockPosition pos, @Nonnull T operation) * @return The current {@link MachineOperation} or null. */ public @Nullable T getOperation(@Nonnull Location loc) { - Preconditions.checkArgument(loc != null, "The location cannot be null"); + Validate.notNull(loc, "The location cannot be null"); return getOperation(new BlockPosition(loc)); } @@ -159,7 +158,7 @@ public boolean startOperation(@Nonnull BlockPosition pos, @Nonnull T operation) * @return The current {@link MachineOperation} or null. */ public @Nullable T getOperation(@Nonnull Block b) { - Preconditions.checkArgument(b != null, "The Block cannot be null"); + Validate.notNull(b, "The Block cannot be null"); return getOperation(new BlockPosition(b)); } @@ -173,7 +172,7 @@ public boolean startOperation(@Nonnull BlockPosition pos, @Nonnull T operation) * @return The current {@link MachineOperation} or null. */ public @Nullable T getOperation(@Nonnull BlockPosition pos) { - Preconditions.checkArgument(pos != null, "The BlockPosition must not be null"); + Validate.notNull(pos, "The BlockPosition must not be null"); return machines.get(pos); } @@ -188,7 +187,7 @@ public boolean startOperation(@Nonnull BlockPosition pos, @Nonnull T operation) * {@link MachineOperation} to begin with. */ public boolean endOperation(@Nonnull Location loc) { - Preconditions.checkArgument(loc != null, "The location should not be null"); + Validate.notNull(b, "The Block should not be null"); return endOperation(new BlockPosition(loc)); } @@ -203,7 +202,7 @@ public boolean endOperation(@Nonnull Location loc) { * {@link MachineOperation} to begin with. */ public boolean endOperation(@Nonnull Block b) { - Preconditions.checkArgument(b != null, "The Block should not be null"); + Validate.notNull(b, "The Block should not be null"); return endOperation(new BlockPosition(b)); } @@ -218,7 +217,7 @@ public boolean endOperation(@Nonnull Block b) { * {@link MachineOperation} to begin with. */ public boolean endOperation(@Nonnull BlockPosition pos) { - Preconditions.checkArgument(pos != null, "The BlockPosition cannot be null"); + Validate.notNull(pos, "The BlockPosition cannot be null"); T operation = machines.remove(pos); @@ -241,8 +240,8 @@ public boolean endOperation(@Nonnull BlockPosition pos) { } public void updateProgressBar(@Nonnull BlockMenu inv, int slot, @Nonnull T operation) { - Preconditions.checkArgument(inv != null, "The inventory must not be null."); - Preconditions.checkArgument(operation != null, "The MachineOperation must not be null."); + Validate.notNull(inv, "The inventory must not be null."); + Validate.notNull(operation, "The MachineOperation must not be null."); if (getProgressBar() == null) { // No progress bar, no need to update anything. diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java index d0f8c21b62..e8bc21fa64 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java @@ -7,8 +7,7 @@ import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; -import com.google.common.base.Preconditions; - +import org.apache.commons.lang.Validate; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.block.Block; @@ -123,7 +122,7 @@ public int getSpeed() { * @return This method will return the current instance of {@link GEOMiner}, so that can be chained. */ public final @Nonnull GEOMiner setCapacity(int capacity) { - Preconditions.checkArgument(capacity > 0, "The capacity must be greater than zero!"); + Validate.isTrue(capacity > 0, "The capacity must be greater than zero!"); if (getState() == ItemState.UNREGISTERED) { this.energyCapacity = capacity; @@ -141,8 +140,8 @@ public int getSpeed() { * * @return This method will return the current instance of {@link GEOMiner}, so that can be chained. */ - public final @Nonnull GEOMiner setProcessingSpeed(int speed) { - Preconditions.checkArgument(speed > 0, "The speed must be greater than zero!"); + public final GEOMiner setProcessingSpeed(int speed) { + Validate.isTrue(speed > 0, "The speed must be greater than zero!"); this.processingSpeed = speed; return this; @@ -156,10 +155,10 @@ public int getSpeed() { * * @return This method will return the current instance of {@link GEOMiner}, so that can be chained. */ - public final @Nonnull GEOMiner setEnergyConsumption(int energyConsumption) { - Preconditions.checkArgument(energyConsumption > 0, "The energy consumption must be greater than zero!"); - Preconditions.checkArgument(energyCapacity > 0, "You must specify the capacity before you can set the consumption amount."); - Preconditions.checkArgument(energyConsumption <= energyCapacity, "The energy consumption cannot be higher than the capacity (" + energyCapacity + ')'); + public final GEOMiner setEnergyConsumption(int energyConsumption) { + Validate.isTrue(energyConsumption > 0, "The energy consumption must be greater than zero!"); + Validate.isTrue(energyCapacity > 0, "You must specify the capacity before you can set the consumption amount."); + Validate.isTrue(energyConsumption <= energyCapacity, "The energy consumption cannot be higher than the capacity (" + energyCapacity + ')'); this.energyConsumedPerTick = energyConsumption; return this; @@ -189,17 +188,19 @@ public void register(@Nonnull SlimefunAddon addon) { } } - private @Nonnull BlockPlaceHandler onBlockPlace() { + @Nonnull + private BlockPlaceHandler onBlockPlace() { return new BlockPlaceHandler(false) { @Override - public void onPlayerPlace(@Nonnull BlockPlaceEvent e) { + public void onPlayerPlace( BlockPlaceEvent e) { updateHologram(e.getBlock(), "&7Idling..."); } }; } - private @Nonnull BlockBreakHandler onBlockBreak() { + @Nonnull + private BlockBreakHandler onBlockBreak() { return new SimpleBlockBreakHandler() { @Override @@ -216,18 +217,21 @@ public void onBlockBreak(@Nonnull Block b) { }; } + @Nonnull @Override - public @Nonnull int[] getInputSlots() { + public int[] getInputSlots() { return new int[0]; } + @Nonnull @Override - public @Nonnull int[] getOutputSlots() { + public int[] getOutputSlots() { return OUTPUT_SLOTS; } + @Nonnull @Override - public @Nonnull List getDisplayRecipes() { + public List getDisplayRecipes() { List displayRecipes = new LinkedList<>(); for (GEOResource resource : Slimefun.getRegistry().getGEOResources().values()) { @@ -245,7 +249,7 @@ public void onBlockBreak(@Nonnull Block b) { } @Override - public @Nonnull EnergyNetComponentType getEnergyComponentType() { + public EnergyNetComponentType getEnergyComponentType() { return EnergyNetComponentType.CONSUMER; } @@ -324,7 +328,7 @@ private void start(@Nonnull Block b, @Nonnull BlockMenu inv) { if (resource.isObtainableFromGEOMiner()) { OptionalInt optional = Slimefun.getGPSNetwork().getResourceManager().getSupplies(resource, b.getWorld(), b.getX() >> 4, b.getZ() >> 4); - if (optional.isEmpty()) { + if (!optional.isPresent()) { updateHologram(b, "&4GEO-Scan required!"); return; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/MiningOperation.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/MiningOperation.java index 83480ce63f..e7f94c98bf 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/MiningOperation.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/operations/MiningOperation.java @@ -2,8 +2,7 @@ import javax.annotation.Nonnull; -import com.google.common.base.Preconditions; - +import org.apache.commons.lang.Validate; import org.bukkit.inventory.ItemStack; import io.github.thebusybiscuit.slimefun4.core.machines.MachineOperation; @@ -23,8 +22,8 @@ public class MiningOperation implements MachineOperation { private int currentTicks = 0; public MiningOperation(@Nonnull ItemStack result, int totalTicks) { - Preconditions.checkArgument(result != null, "The result cannot be null"); - Preconditions.checkArgument(totalTicks >= 0, "The amount of total ticks must be a positive integer or zero, received: " + totalTicks); + Validate.notNull(result, "The result cannot be null"); + Validate.isTrue(totalTicks >= 0, "The amount of total ticks must be a positive integer or zero, received: " + totalTicks); this.result = result; this.totalTicks = totalTicks; @@ -32,7 +31,7 @@ public MiningOperation(@Nonnull ItemStack result, int totalTicks) { @Override public void addProgress(int num) { - Preconditions.checkArgument(num > 0, "Progress must be positive."); + Validate.isTrue(num > 0, "Progress must be positive."); currentTicks += num; } From c7506d863b9fbd2da8ffbd81f4b1d02c47969425 Mon Sep 17 00:00:00 2001 From: iTwins Date: Wed, 6 Dec 2023 20:30:44 +0100 Subject: [PATCH 108/131] revert these unnecessary changes as well --- .../slimefun4/core/machines/MachineProcessor.java | 2 +- .../slimefun4/implementation/items/geo/GEOMiner.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java index dd2349e196..9ec92b578a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/machines/MachineProcessor.java @@ -187,7 +187,7 @@ public boolean startOperation(@Nonnull BlockPosition pos, @Nonnull T operation) * {@link MachineOperation} to begin with. */ public boolean endOperation(@Nonnull Location loc) { - Validate.notNull(b, "The Block should not be null"); + Validate.notNull(loc, "The location should not be null"); return endOperation(new BlockPosition(loc)); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java index e8bc21fa64..cc09eb0ac6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java @@ -121,7 +121,7 @@ public int getSpeed() { * * @return This method will return the current instance of {@link GEOMiner}, so that can be chained. */ - public final @Nonnull GEOMiner setCapacity(int capacity) { + public final GEOMiner setCapacity(int capacity) { Validate.isTrue(capacity > 0, "The capacity must be greater than zero!"); if (getState() == ItemState.UNREGISTERED) { @@ -193,7 +193,7 @@ private BlockPlaceHandler onBlockPlace() { return new BlockPlaceHandler(false) { @Override - public void onPlayerPlace( BlockPlaceEvent e) { + public void onPlayerPlace(BlockPlaceEvent e) { updateHologram(e.getBlock(), "&7Idling..."); } }; From f49d2dda4342c8126465c4983a4cdbc78a5a1dc8 Mon Sep 17 00:00:00 2001 From: J3fftw <44972470+J3fftw1@users.noreply.github.com> Date: Wed, 6 Dec 2023 22:07:50 +0100 Subject: [PATCH 109/131] fix rate limiting issues (#4042) --- pom.xml | 2 +- .../slimefun4/core/services/github/GitHubTask.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index fd065cb4a7..8a9143c52f 100644 --- a/pom.xml +++ b/pom.xml @@ -355,7 +355,7 @@ com.github.baked-libs.dough dough-api - 99381b2 + 4b28bd408e compile diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java index 37a45e4315..da42dfa996 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java @@ -133,7 +133,7 @@ private int requestTexture(@Nonnull Contributor contributor, @Nonnull Map uuid = contributor.getUniqueId(); if (!uuid.isPresent()) { - CompletableFuture future = UUIDLookup.forUsername(Slimefun.instance(), contributor.getMinecraftName()); + CompletableFuture future = UUIDLookup.getUuidFromUsername(Slimefun.instance(), contributor.getMinecraftName()); // Fixes #3241 - Do not wait for more than 30 seconds uuid = Optional.ofNullable(future.get(30, TimeUnit.SECONDS)); From e261bbebe9e9e2f6b1cad358698b2e5df2eced46 Mon Sep 17 00:00:00 2001 From: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Date: Thu, 7 Dec 2023 11:39:49 -0600 Subject: [PATCH 110/131] Strip search term --- .../slimefun4/implementation/guide/SurvivalSlimefunGuide.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/SurvivalSlimefunGuide.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/SurvivalSlimefunGuide.java index 2e86296008..b9d0b70b9a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/SurvivalSlimefunGuide.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/SurvivalSlimefunGuide.java @@ -350,7 +350,7 @@ public void openSearch(PlayerProfile profile, String input, boolean addToHistory } ChestMenu menu = new ChestMenu(Slimefun.getLocalization().getMessage(p, "guide.search.inventory").replace("%item%", ChatUtils.crop(ChatColor.WHITE, input))); - String searchTerm = input.toLowerCase(Locale.ROOT); + String searchTerm = ChatColor.strip(input.toLowerCase(Locale.ROOT)); if (addToHistory) { profile.getGuideHistory().add(searchTerm); From d0963697ca682f58411ffecbd0ab787834dcf85c Mon Sep 17 00:00:00 2001 From: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Date: Thu, 7 Dec 2023 11:48:45 -0600 Subject: [PATCH 111/131] use proper method name --- .../slimefun4/implementation/guide/SurvivalSlimefunGuide.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/SurvivalSlimefunGuide.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/SurvivalSlimefunGuide.java index b9d0b70b9a..621431efc1 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/SurvivalSlimefunGuide.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/SurvivalSlimefunGuide.java @@ -350,7 +350,7 @@ public void openSearch(PlayerProfile profile, String input, boolean addToHistory } ChestMenu menu = new ChestMenu(Slimefun.getLocalization().getMessage(p, "guide.search.inventory").replace("%item%", ChatUtils.crop(ChatColor.WHITE, input))); - String searchTerm = ChatColor.strip(input.toLowerCase(Locale.ROOT)); + String searchTerm = ChatColor.stripColor(input.toLowerCase(Locale.ROOT)); if (addToHistory) { profile.getGuideHistory().add(searchTerm); From e83c9f704e8ca78756aa0ef1bb32457ef0dbc54e Mon Sep 17 00:00:00 2001 From: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Date: Thu, 7 Dec 2023 12:48:57 -0600 Subject: [PATCH 112/131] Add test for both normal and colored seearches --- .../core/guide/TestGuideOpening.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/core/guide/TestGuideOpening.java b/src/test/java/io/github/thebusybiscuit/slimefun4/core/guide/TestGuideOpening.java index 8ed5d838b9..586800bec4 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/core/guide/TestGuideOpening.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/core/guide/TestGuideOpening.java @@ -5,11 +5,14 @@ import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; +import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide; +import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -90,8 +93,28 @@ void testOpenItemStack() throws InterruptedException { } @Test - @DisplayName("Test if the Slimefun Search can be opened from the History") + @DisplayName("Test if the Slimefun Search works with normal and colored querys") void testOpenSearch() throws InterruptedException { + String normalQuery = "iron"; + String coloredQuery = ChatColor.DARK_PURPLE + "iron"; + + SlimefunItem testItem = TestUtilities.mockSlimefunItem(plugin, "IRON_ITEM", new CustomItemStack(Material.IRON_INGOT, "iron item")); + testItem.register(plugin); + + Player player = server.addPlayer(); + PlayerProfile profile = TestUtilities.awaitProfile(player); + SlimefunGuideImplementation guide = new SurvivalSlimefunGuide(false, false); + + guide.openSearch(profile, normalQuery, false); + Assertions.assertTrue(player.getOpenInventory().getTopInventory().contains(testItem.getItem()), "Failed on normal query"); + + guide.openSearch(profile, coloredQuery, false); + Assertions.assertTrue(player.getOpenInventory().getTopInventory().contains(testItem.getItem()), "Failed on colored query"); + } + + @Test + @DisplayName("Test if the Slimefun Search can be opened from the History") + void testOpenSearchHistory() throws InterruptedException { String query = "electric"; SlimefunGuideImplementation guide = Mockito.mock(SlimefunGuideImplementation.class); From 82c8c91451306158a6211d7ce3375fe2cfc566ce Mon Sep 17 00:00:00 2001 From: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Date: Thu, 7 Dec 2023 16:28:39 -0600 Subject: [PATCH 113/131] Suggestions and consistency --- .../core/guide/TestGuideOpening.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/core/guide/TestGuideOpening.java b/src/test/java/io/github/thebusybiscuit/slimefun4/core/guide/TestGuideOpening.java index 586800bec4..a8685b9736 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/core/guide/TestGuideOpening.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/core/guide/TestGuideOpening.java @@ -93,10 +93,10 @@ void testOpenItemStack() throws InterruptedException { } @Test - @DisplayName("Test if the Slimefun Search works with normal and colored querys") - void testOpenSearch() throws InterruptedException { - String normalQuery = "iron"; - String coloredQuery = ChatColor.DARK_PURPLE + "iron"; + @DisplayName("Test if the Slimefun Search works with normal and colored terms") + void testOpenSearch_withColoredSearchTerm() throws InterruptedException { + String normalTerm = "iron"; + String coloredTerm = ChatColor.DARK_PURPLE + "iron"; SlimefunItem testItem = TestUtilities.mockSlimefunItem(plugin, "IRON_ITEM", new CustomItemStack(Material.IRON_INGOT, "iron item")); testItem.register(plugin); @@ -105,21 +105,23 @@ void testOpenSearch() throws InterruptedException { PlayerProfile profile = TestUtilities.awaitProfile(player); SlimefunGuideImplementation guide = new SurvivalSlimefunGuide(false, false); - guide.openSearch(profile, normalQuery, false); + guide.openSearch(profile, normalTerm, false); + // Assert we can open with a non-coloured search term Assertions.assertTrue(player.getOpenInventory().getTopInventory().contains(testItem.getItem()), "Failed on normal query"); - guide.openSearch(profile, coloredQuery, false); + guide.openSearch(profile, coloredTerm, false); + // Assert we can open with a coloured search term Assertions.assertTrue(player.getOpenInventory().getTopInventory().contains(testItem.getItem()), "Failed on colored query"); } @Test @DisplayName("Test if the Slimefun Search can be opened from the History") void testOpenSearchHistory() throws InterruptedException { - String query = "electric"; + String term = "electric"; SlimefunGuideImplementation guide = Mockito.mock(SlimefunGuideImplementation.class); - PlayerProfile profile = prepare(guide, history -> history.add(query)); - Mockito.verify(guide).openSearch(profile, query, false); + PlayerProfile profile = prepare(guide, history -> history.add(term)); + Mockito.verify(guide).openSearch(profile, term, false); } @Test From e1d230dcb6c799bc2060f0d70d9d1135f5d37d64 Mon Sep 17 00:00:00 2001 From: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Date: Fri, 8 Dec 2023 17:47:22 -0600 Subject: [PATCH 114/131] Patch hopefully --- .../slimefun4/implementation/listeners/BlockListener.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index 967a6ad6d6..beb241f7ad 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -257,8 +257,9 @@ private void checkForSensitiveBlocks(Block block, Integer count) { if (count >= Bukkit.getServer().getMaxChainedNeighborUpdates()) { return; } + BlockData blockData = block.getBlockData(); + block.setType(Material.AIR, false); for (BlockFace face : CARDINAL_BLOCKFACES) { - block.setType(Material.AIR, false); if (!isSupported(block.getRelative(face).getBlockData(), block.getRelative(face))) { Block relative = block.getRelative(face); for (ItemStack drop : relative.getDrops()) { @@ -267,6 +268,7 @@ private void checkForSensitiveBlocks(Block block, Integer count) { checkForSensitiveBlocks(relative, ++count); } } + block.setBlockData(blockData, false); } /** From d6516613700cdfe928087f7270367e27b895ac84 Mon Sep 17 00:00:00 2001 From: J3fftw <44972470+J3fftw1@users.noreply.github.com> Date: Sat, 9 Dec 2023 04:39:27 +0100 Subject: [PATCH 115/131] 1.19.3 support (#4039) --- .../resources/tags/block_placer_ignored_materials.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/resources/tags/block_placer_ignored_materials.json b/src/main/resources/tags/block_placer_ignored_materials.json index 3f9417b711..bc32030c7f 100644 --- a/src/main/resources/tags/block_placer_ignored_materials.json +++ b/src/main/resources/tags/block_placer_ignored_materials.json @@ -27,7 +27,6 @@ "minecraft:lily_pad", "minecraft:dead_bush", "minecraft:fern", - "minecraft:grass", "minecraft:sea_pickle", "minecraft:nether_wart", "minecraft:seagrass", @@ -35,6 +34,10 @@ "minecraft:kelp", "minecraft:bell", "minecraft:lantern", + { + "id" : "minecraft:grass", + "required" : false + }, { "id" : "minecraft:soul_lantern", "required" : false @@ -58,6 +61,10 @@ { "id" : "minecraft:weeping_vines", "required" : false + }, + { + "id" : "minecraft:short_grass", + "required" : false } ] } From d35798040cc5c3758e897c9d8a3e03c6dd1ab111 Mon Sep 17 00:00:00 2001 From: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Date: Sat, 9 Dec 2023 09:03:54 -0600 Subject: [PATCH 116/131] Revert Sensitive Block Changes --- .../listeners/BlockListener.java | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index beb241f7ad..f66140c3e7 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -14,7 +14,6 @@ import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -26,7 +25,6 @@ import org.bukkit.inventory.meta.ItemMeta; import io.github.bakedlibs.dough.protection.Interaction; -import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.api.events.ExplosiveToolBreakBlocksEvent; import io.github.thebusybiscuit.slimefun4.api.events.SlimefunBlockBreakEvent; import io.github.thebusybiscuit.slimefun4.api.events.SlimefunBlockPlaceEvent; @@ -171,8 +169,6 @@ public void onBlockBreak(BlockBreakEvent e) { callBlockHandler(e, item, drops, sfItem); - checkForSensitiveBlocks(e.getBlock(), 0); - dropItems(e, drops); } } @@ -243,55 +239,6 @@ private void dropItems(BlockBreakEvent e, List drops) { } } - /** - * This method checks recursively for any sensitive blocks - * that are no longer supported due to this block breaking - * - * @param block - * The {@link Block} in question - * @param count - * The amount of times this has been recursively called - */ - @ParametersAreNonnullByDefault - private void checkForSensitiveBlocks(Block block, Integer count) { - if (count >= Bukkit.getServer().getMaxChainedNeighborUpdates()) { - return; - } - BlockData blockData = block.getBlockData(); - block.setType(Material.AIR, false); - for (BlockFace face : CARDINAL_BLOCKFACES) { - if (!isSupported(block.getRelative(face).getBlockData(), block.getRelative(face))) { - Block relative = block.getRelative(face); - for (ItemStack drop : relative.getDrops()) { - block.getWorld().dropItemNaturally(relative.getLocation(), drop); - } - checkForSensitiveBlocks(relative, ++count); - } - } - block.setBlockData(blockData, false); - } - - /** - * This method checks if the {@link BlockData} would be - * supported at the given {@link Block}. - * - * @param blockData - * The {@link BlockData} to check - * @param block - * The {@link Block} the {@link BlockData} would be at - * @return - * Whether the {@link BlockData} would be supported at the given {@link Block} - */ - @ParametersAreNonnullByDefault - private boolean isSupported(BlockData blockData, Block block) { - if (Slimefun.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_19)) { - return blockData.isSupported(block); - } else { - // TODO: Make 1.16-1.18 version. BlockData::isSupported is 1.19+. - return true; - } - } - /** * This method checks for a sensitive {@link Block}. * Sensitive {@link Block Blocks} are pressure plates or saplings, which should be broken From 6a4b1fe794c8857433fae7f1cfa97a88734ee8f3 Mon Sep 17 00:00:00 2001 From: Alessio Colombo Date: Sat, 9 Dec 2023 18:16:34 +0100 Subject: [PATCH 117/131] Fixed vanilla sensitive blocks --- .../listeners/BlockListener.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index f66140c3e7..3526b4d11a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -10,10 +10,13 @@ import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.block.data.BlockData; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -170,6 +173,8 @@ public void onBlockBreak(BlockBreakEvent e) { callBlockHandler(e, item, drops, sfItem); dropItems(e, drops); + + checkForSensitiveBlocks(e.getBlock(), 0, e.isDropItems()); } } @@ -283,6 +288,59 @@ private void checkForSensitiveBlockAbove(Player player, Block block, ItemStack i } } + /** + * This method checks recursively for any sensitive blocks + * that are no longer supported due to this block breaking + * + * @param block + * The {@link Block} in question + * @param count + * The amount of times this has been recursively called + */ + @ParametersAreNonnullByDefault + private void checkForSensitiveBlocks(Block block, Integer count, boolean isDropItems) { + if (count >= Bukkit.getServer().getMaxChainedNeighborUpdates()) { + return; + } + + BlockState state = block.getState(); + block.setType(Material.AIR, false); + for (BlockFace face : CARDINAL_BLOCKFACES) { + if (!isSupported(block.getRelative(face).getBlockData(), block.getRelative(face))) { + Block relative = block.getRelative(face); + if (!isDropItems) { + for (ItemStack drop : relative.getDrops()) { + block.getWorld().dropItemNaturally(relative.getLocation(), drop); + } + } + checkForSensitiveBlocks(relative, ++count, isDropItems); + } + } + block.setBlockData(state.getBlockData(), false); + state.update(true, false); + } + + /** + * This method checks if the {@link BlockData} would be + * supported at the given {@link Block}. + * + * @param blockData + * The {@link BlockData} to check + * @param block + * The {@link Block} the {@link BlockData} would be at + * @return + * Whether the {@link BlockData} would be supported at the given {@link Block} + */ + @ParametersAreNonnullByDefault + private boolean isSupported(BlockData blockData, Block block) { + if (Slimefun.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_19)) { + return blockData.isSupported(block); + } else { + // TODO: Make 1.16-1.18 version. BlockData::isSupported is 1.19+. + return true; + } + } + private int getBonusDropsWithFortune(@Nullable ItemStack item, @Nonnull Block b) { int amount = 1; From b3ff154f241612abd973d7affd33105ec41874e7 Mon Sep 17 00:00:00 2001 From: Alessio Colombo Date: Sat, 9 Dec 2023 18:30:56 +0100 Subject: [PATCH 118/131] Import order, comments --- .../slimefun4/implementation/listeners/BlockListener.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index 3526b4d11a..60b44b3ab0 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -10,7 +10,6 @@ import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; @@ -32,6 +31,7 @@ import io.github.thebusybiscuit.slimefun4.api.events.SlimefunBlockBreakEvent; import io.github.thebusybiscuit.slimefun4.api.events.SlimefunBlockPlaceEvent; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; +import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler; @@ -168,12 +168,15 @@ public void onBlockBreak(BlockBreakEvent e) { } if (!e.isCancelled()) { + // Checks for Slimefun sensitive blocks above, using Slimefun Tags + // TODO: merge this with the vanilla sensitive block check (when 1.18- is dropped) checkForSensitiveBlockAbove(e.getPlayer(), e.getBlock(), item); callBlockHandler(e, item, drops, sfItem); dropItems(e, drops); + // Checks for vanilla sensitive blocks everywhere checkForSensitiveBlocks(e.getBlock(), 0, e.isDropItems()); } } From b38743d713a8d972d0c996c2545166940e49fa5d Mon Sep 17 00:00:00 2001 From: Alessio Colombo Date: Sat, 9 Dec 2023 18:36:00 +0100 Subject: [PATCH 119/131] More comments --- .../slimefun4/implementation/listeners/BlockListener.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index 60b44b3ab0..91fb9eb291 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -307,6 +307,7 @@ private void checkForSensitiveBlocks(Block block, Integer count, boolean isDropI } BlockState state = block.getState(); + // We set the block to air to make use of BlockData#isSupported. block.setType(Material.AIR, false); for (BlockFace face : CARDINAL_BLOCKFACES) { if (!isSupported(block.getRelative(face).getBlockData(), block.getRelative(face))) { @@ -319,6 +320,7 @@ private void checkForSensitiveBlocks(Block block, Integer count, boolean isDropI checkForSensitiveBlocks(relative, ++count, isDropItems); } } + // Set the BlockData back: this makes it so containers and spawners drop correctly. This is a hacky fix. block.setBlockData(state.getBlockData(), false); state.update(true, false); } From dd698083553adea13818e3cef13d2b9f33e20233 Mon Sep 17 00:00:00 2001 From: ybw0014 Date: Mon, 11 Dec 2023 16:55:26 -0500 Subject: [PATCH 120/131] chore: update download link (#4053) Co-authored-by: Daniel Walsh Co-authored-by: J3fftw <44972470+J3fftw1@users.noreply.github.com> --- README.md | 2 +- .../slimefun4/api/events/BlockPlacerPlaceEvent.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 72a597409f..46ce4c0096 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Here is a full summary of the differences between the two different versions of | **Bug Reports** | :heavy_check_mark: | :x: | | **testing before release** | :x: | :heavy_check_mark: | | **change logs** | :x: | :memo: **[change log](https://github.com/Slimefun/Slimefun4/blob/master/CHANGELOG.md)** | -| **Download link** | :floppy_disk: **[download latest](https://thebusybiscuit.github.io/builds/TheBusyBiscuit/Slimefun4/master/)** | :floppy_disk: **[download "stable"](https://thebusybiscuit.github.io/builds/TheBusyBiscuit/Slimefun4/stable/)** | +| **Download links** | :floppy_disk: **[download latest](https://blob.build/project/Slimefun4/Dev)** | :floppy_disk: **[download "stable"](https://blob.build/project/Slimefun4/RC)** | **:exclamation: We wholeheartedly recommend you to use _development builds_, they are the most recent version of Slimefun and also receive the most frequent updates! In fact, "stable" builds are so outdated that we won't accept bug reports from them at all.**
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/BlockPlacerPlaceEvent.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/BlockPlacerPlaceEvent.java index 4ea35c510d..59ee4bdf51 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/BlockPlacerPlaceEvent.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/BlockPlacerPlaceEvent.java @@ -116,4 +116,4 @@ public HandlerList getHandlers() { return getHandlerList(); } -} \ No newline at end of file +} From 88ac05ff31a58624e49a60660ab7b9a719314b82 Mon Sep 17 00:00:00 2001 From: JustAHuman-xD <65748158+JustAHuman-xD@users.noreply.github.com> Date: Tue, 12 Dec 2023 14:51:14 -0600 Subject: [PATCH 121/131] Add TalismanActivateEvent (Updated version of #3920) (#4045) Co-authored-by: TheBusyBiscuit Co-authored-by: Sefiraat Co-authored-by: J3fftw <44972470+J3fftw1@users.noreply.github.com> Co-authored-by: Daniel Walsh Co-authored-by: China Worldstar <40675557+Sniperkaos@users.noreply.github.com> Co-authored-by: cworldstar Co-authored-by: Alessio Colombo <37039432+Sfiguz7@users.noreply.github.com> --- .../api/events/TalismanActivateEvent.java | 96 ++++++++++ .../items/magical/talismans/Talisman.java | 29 ++- .../api/events/TestTalismanActivateEvent.java | 177 ++++++++++++++++++ 3 files changed, 294 insertions(+), 8 deletions(-) create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/api/events/TalismanActivateEvent.java create mode 100644 src/test/java/io/github/thebusybiscuit/slimefun4/api/events/TestTalismanActivateEvent.java diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/TalismanActivateEvent.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/TalismanActivateEvent.java new file mode 100644 index 0000000000..775691a0a6 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/TalismanActivateEvent.java @@ -0,0 +1,96 @@ +package io.github.thebusybiscuit.slimefun4.api.events; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.bukkit.inventory.ItemStack; + +import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.Talisman; + +/** + * This {@link PlayerEvent} is called when a {@link Player} activates a {@link Talisman} + * + * @author cworldstar + */ +public class TalismanActivateEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + private final Talisman talisman; + private final ItemStack talismanItemStack; + private boolean preventConsumption = false; + private boolean cancelled = false; + + /** + * @param player + * The {@link Player} who activated the talisman. + * + * @param talisman + * The {@link Talisman} that was activated. + * + * @param talismanItem + * The {@link ItemStack} corresponding to the Talisman. + */ + @ParametersAreNonnullByDefault + public TalismanActivateEvent(Player player, Talisman talisman, ItemStack talismanItem) { + super(player); + this.talisman = talisman; + this.talismanItemStack = talismanItem; + } + + /** + * @return The {@link Talisman} used. + */ + public @Nonnull Talisman getTalisman() { + return this.talisman; + } + + /** + * @return The {@link ItemStack} of the used {@link Talisman}. + */ + public @Nonnull ItemStack getTalismanItem() { + return this.talismanItemStack; + } + + /** + * Only applies if {@link Talisman#isConsumable()} is true. + * Defaults to false. + * + * @return Whether the {@link ItemStack} should not be consumed. + */ + public boolean preventsConsumption() { + return this.preventConsumption; + } + + /** + * Only applies if {@link Talisman#isConsumable()} is true. + * + * @param preventConsumption + * Whether the {@link ItemStack} should not be consumed. + */ + public void setPreventConsumption(boolean preventConsumption) { + this.preventConsumption = preventConsumption; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + @Override + public @Nonnull HandlerList getHandlers() { + return getHandlerList(); + } + + public static @Nonnull HandlerList getHandlerList() { + return handlers; + } +} \ No newline at end of file diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/Talisman.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/Talisman.java index 7ecc6f6fab..9f97f19892 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/Talisman.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/Talisman.java @@ -10,6 +10,7 @@ import javax.annotation.ParametersAreNonnullByDefault; import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; @@ -27,6 +28,7 @@ import io.github.bakedlibs.dough.items.CustomItemStack; import io.github.bakedlibs.dough.items.ItemUtils; +import io.github.thebusybiscuit.slimefun4.api.events.TalismanActivateEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; @@ -186,11 +188,15 @@ public static boolean trigger(Event e, SlimefunItem item, boolean sendMessage) { return false; } } else { - ItemStack enderTalisman = talisman.getEnderVariant(); + SlimefunItemStack enderTalismanItem = talisman.getEnderVariant(); + if (enderTalismanItem == null) { + return false; + } - if (SlimefunUtils.containsSimilarItem(p.getEnderChest(), enderTalisman, true)) { + EnderTalisman enderTalisman = enderTalismanItem.getItem(EnderTalisman.class); + if (enderTalisman != null && SlimefunUtils.containsSimilarItem(p.getEnderChest(), enderTalismanItem, true)) { if (talisman.canUse(p, true)) { - activateTalisman(e, p, p.getEnderChest(), talisman, enderTalisman, sendMessage); + activateTalisman(e, p, p.getEnderChest(), enderTalisman, enderTalismanItem, sendMessage); return true; } else { return false; @@ -203,12 +209,19 @@ public static boolean trigger(Event e, SlimefunItem item, boolean sendMessage) { @ParametersAreNonnullByDefault private static void activateTalisman(Event e, Player p, Inventory inv, Talisman talisman, ItemStack talismanItem, boolean sendMessage) { - consumeItem(inv, talisman, talismanItem); - applyTalismanEffects(p, talisman); - cancelEvent(e, talisman); + TalismanActivateEvent talismanEvent = new TalismanActivateEvent(p, talisman, talismanItem); + Bukkit.getPluginManager().callEvent(talismanEvent); + if (!talismanEvent.isCancelled()) { + if (!talismanEvent.preventsConsumption()) { + consumeItem(inv, talisman, talismanItem); + } - if (sendMessage) { - talisman.sendMessage(p); + applyTalismanEffects(p, talisman); + cancelEvent(e, talisman); + + if (sendMessage) { + talisman.sendMessage(p); + } } } diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/api/events/TestTalismanActivateEvent.java b/src/test/java/io/github/thebusybiscuit/slimefun4/api/events/TestTalismanActivateEvent.java new file mode 100644 index 0000000000..83b49fa231 --- /dev/null +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/api/events/TestTalismanActivateEvent.java @@ -0,0 +1,177 @@ +package io.github.thebusybiscuit.slimefun4.api.events; + +import be.seeseemelk.mockbukkit.MockBukkit; +import be.seeseemelk.mockbukkit.ServerMock; +import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; +import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; +import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.Talisman; +import io.github.thebusybiscuit.slimefun4.implementation.listeners.TalismanListener; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerItemBreakEvent; +import org.bukkit.inventory.ItemStack; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class TestTalismanActivateEvent { + + private static ServerMock server; + private static Slimefun plugin; + private static Player player; + private static SlimefunItem talisman; + private static SlimefunItem enderTalisman; + + @BeforeAll + public static void load() { + server = MockBukkit.mock(); + plugin = MockBukkit.load(Slimefun.class); + + new TalismanListener(plugin); + + talisman = new Talisman(SlimefunItems.TALISMAN_ANVIL, new ItemStack[] {}, true, false, "anvil"); + talisman.register(plugin); + + enderTalisman = SlimefunItem.getById("ENDER_" + talisman.getId()); + + player = server.addPlayer(); + } + + @AfterAll + public static void unload() { + MockBukkit.unmock(); + } + + void activateAnvilTalisman(boolean enderVariant, boolean inEnderChest) { + player.getInventory().clear(); + player.getEnderChest().clear(); + + ItemStack talismanItem = enderVariant ? enderTalisman.getItem() : talisman.getItem(); + ItemStack breakableItem = new ItemStack(Material.IRON_PICKAXE); + + if (inEnderChest) { + player.getEnderChest().addItem(talismanItem); + } else { + player.getInventory().addItem(talismanItem); + } + + player.getInventory().setItemInMainHand(breakableItem); + + PlayerItemBreakEvent event = new PlayerItemBreakEvent(player, breakableItem); + server.getPluginManager().callEvent(event); + } + + @Test + @DisplayName("Test that TalismanActivateEvent is fired when an anvil talisman activates") + void testEventIsFired() { + // Assert the talisman activates in the inventory + activateAnvilTalisman(false, false); + server.getPluginManager().assertEventFired(TalismanActivateEvent.class, ignored -> true); + server.getPluginManager().clearEvents(); + + // Assert the talisman activates in the ender chest + activateAnvilTalisman(true, true); + server.getPluginManager().assertEventFired(TalismanActivateEvent.class, ignored -> true); + server.getPluginManager().clearEvents(); + // Assert the normal talisman does not activate in the ender chest + activateAnvilTalisman(false, true); + try { + server.getPluginManager().assertEventFired(TalismanActivateEvent.class, ignored -> true); + } catch (AssertionError ignored) { + return; // This is expected; the event should not have fired + } + server.getPluginManager().clearEvents(); + + // Assert the ender talisman does not activate in the inventory + try { + activateAnvilTalisman(true, false); + server.getPluginManager().assertEventFired(TalismanActivateEvent.class, ignored -> true); + } catch (AssertionError ignored) { + return; // This is expected; the event should not have fired + } + server.getPluginManager().clearEvents(); + } + + @Test + @DisplayName("Test that the TalismanActivateEvent has the correct fields") + void testEventFields() { + // Assert the talisman activates in the inventory + activateAnvilTalisman(false, false); + server.getPluginManager().assertEventFired(TalismanActivateEvent.class, event -> { + Assertions.assertEquals(talisman, event.getTalisman()); + Assertions.assertEquals(talisman.getItem(), event.getTalismanItem()); + Assertions.assertEquals(player, event.getPlayer()); + return true; + }); + server.getPluginManager().clearEvents(); + + // Assert the talisman activates in the ender chest + activateAnvilTalisman(true, true); + server.getPluginManager().assertEventFired(TalismanActivateEvent.class, event -> { + Assertions.assertEquals(enderTalisman, event.getTalisman()); + Assertions.assertEquals(enderTalisman.getItem(), event.getTalismanItem()); + Assertions.assertEquals(player, event.getPlayer()); + return true; + }); + server.getPluginManager().clearEvents(); + } + + @Test + @DisplayName("Test that the TalismanActivateEvent can be cancelled") + void testEventCanBeCancelled() { + server.getPluginManager().registerEvents(new Listener() { + @EventHandler + public void onTalismanActivate(TalismanActivateEvent event) { + event.setCancelled(true); + } + }, plugin); + + // Assert the talisman activates in the inventory + activateAnvilTalisman(false, false); + server.getPluginManager().assertEventFired(TalismanActivateEvent.class, event -> { + Assertions.assertTrue(event.isCancelled()); + return true; + }); + server.getPluginManager().clearEvents(); + + // Assert the talisman activates in the ender chest + activateAnvilTalisman(true, true); + server.getPluginManager().assertEventFired(TalismanActivateEvent.class, event -> { + Assertions.assertTrue(event.isCancelled()); + return true; + }); + server.getPluginManager().clearEvents(); + } + + @Test + @DisplayName("Test that the TalismanActivateEvent can prevent consumption") + void testEventCanPreventConsumption() { + server.getPluginManager().registerEvents(new Listener() { + @EventHandler + public void onTalismanActivate(TalismanActivateEvent event) { + event.setPreventConsumption(true); + } + }, plugin); + + // Assert the talisman activates in the inventory + activateAnvilTalisman(false, false); + server.getPluginManager().assertEventFired(TalismanActivateEvent.class, event -> { + Assertions.assertTrue(event.preventsConsumption()); + return true; + }); + server.getPluginManager().clearEvents(); + + // Assert the talisman activates in the ender chest + activateAnvilTalisman(true, true); + server.getPluginManager().assertEventFired(TalismanActivateEvent.class, event -> { + Assertions.assertTrue(event.preventsConsumption()); + return true; + }); + server.getPluginManager().clearEvents(); + } +} From 9deb0fa6d535703aa3f2a83c3baba2d5ed5bf8d9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 22:49:21 +0100 Subject: [PATCH 122/131] [CI skip] chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.2.3 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8a9143c52f..8dc81f23f4 100644 --- a/pom.xml +++ b/pom.xml @@ -146,7 +146,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.2 + 3.2.3 org.junit.jupiter:junit-jupiter From 09d6f64a60c749e0d52ec67863dc368483796af0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 22:49:34 +0100 Subject: [PATCH 123/131] [CI skip] fix(deps): update dependency com.sk89q.worldedit:worldedit-core to v7.2.18 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8dc81f23f4..92f579ec10 100644 --- a/pom.xml +++ b/pom.xml @@ -418,7 +418,7 @@ com.sk89q.worldedit worldedit-core - 7.2.17 + 7.2.18 provided From bbfb9734b9f549d7e82291eff041f9b666a61b63 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 22:49:50 +0100 Subject: [PATCH 124/131] [CI skip] fix(deps): update dependency com.sk89q.worldedit:worldedit-bukkit to v7.2.18 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 92f579ec10..6a45ac2cf0 100644 --- a/pom.xml +++ b/pom.xml @@ -432,7 +432,7 @@ com.sk89q.worldedit worldedit-bukkit - 7.2.17 + 7.2.18 provided From 18565eba2e5ce5031a6b48fc5b9a3bb511ea9a94 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 21:21:01 +0100 Subject: [PATCH 125/131] [CI skip] Update dependency com.gmail.nossr50.mcMMO:mcMMO to v2.1.226 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6a45ac2cf0..3dbac1e08e 100644 --- a/pom.xml +++ b/pom.xml @@ -446,7 +446,7 @@ com.gmail.nossr50.mcMMO mcMMO - 2.1.225 + 2.1.226 provided From 9e8758b990809bc94243e5d9fed7bdc19aaac3d7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 21:24:53 +0100 Subject: [PATCH 126/131] [CI skip] Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.12.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3dbac1e08e..a548bfc1a6 100644 --- a/pom.xml +++ b/pom.xml @@ -115,7 +115,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.12.0 From a56aacd4d62878a718f1b83076344d79cfd576bb Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Tue, 19 Dec 2023 20:35:26 +0000 Subject: [PATCH 127/131] Update changelog for RC-36 (#4066) --- CHANGELOG.md | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecd01fbb11..fd52f7a3dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Table of contents -- [Release Candidate 36 (TBD)](#release-candidate-36-tbd) -- [Release Candidate 35 (7 Jul 2023)](#release-candidate-35-7-jul-2023) +- [Release Candidate 37 (TBD)](#release-candidate-37-tbd) +- [Release Candidate 36 (20 Dec 2023)](#release-candidate-36-20-dec-2023) +- [Release Candidate 35 (07 Jul 2023)](#release-candidate-35-07-jul-2023) - [Release Candidate 34 (20 Jun 2023)](#release-candidate-34-20-jun-2023) - [Release Candidate 33 (07 Jan 2023)](#release-candidate-33-07-jan-2023) - [Release Candidate 32 (26 Jun 2022)](#release-candidate-32-26-jun-2022) @@ -36,15 +37,55 @@ - [Release Candidate 2 (29 Sep 2019)](#release-candidate-2-29-sep-2019) - [Release Candidate 1 (26 Sep 2019)](#release-candidate-1-26-sep-2019) -## Release Candidate 36 (TBD) +## Release Candidate 37 (TBD) + +## Release Candidate 36 (20 Dec 2023) #### Additions +* Added e2e testing to PRs to better ensure compatibility +* Added compatibility to 1.20+ +* Added rainbow armor +* Added grace periods to radiation +* Added cherry log to android woodcutter +* Added blackstone recipes to Grindstone and Ore Crusher (#3912) +* Added Enchanted Golden Apple recipe (suggestion #2147 from punished_Garett) (#3591) +* Added new flags for timings (#3246) +* Added yaw to GPS Waypoints +* (API) Add MultiBlockCraftEvent (#3928) +* (API) Add TalismanActivateEvent (#4045) #### Changes +* Changed the radiation system +* Removed backwards compatibility +* (API) Improve performance for clearAllBlockInfoAtChunk +* Change Energized GPS Transmitter values to follow the pattern of previous tiers (#3915) +* Allowed the sword of beheading to drop piglin heads +* Improvements to BlockStorage handling (#3911) +* Moved builds to https://blob.build #### Fixes - -## Release Candidate 35 (7 Jul 2023) +* Fix #3444 +* Fix #3507 +* Fix possible enchantment duplication +* Fix Different Time of Pan Recipes +* Fix some of the reported blocks not working (#3848) +* Fix Soulbound Runes not working (#3932) +* Fix #3836 +* Fix unable to craft soulbound backpack with woven backpack with id (#3939) +* Fix getting radiated when not supposed to +* Fix geo miner voiding resources +* Fix sensitive blocks attached to sf blocks not dropping (1.19+) +* Fix breaking sf block with not unlocked item duping contents (#3976) +* Fix the case of SlimefunItem#itemhandlers +* Fix taking damage on head collision while wearing elytra cap (#3760) +* Fix heads showing as steve (#4027) +* Fix grappling hook not working due to bat dying (#3926) +* Fix freezer material +* Fix auto update +* Fix rate limiting issues (#4042) +* Fix orebfuscator plugin with blocks when gold panning (#3921) + +## Release Candidate 35 (07 Jul 2023) #### Additions * Added `sounds.yml` file to configure sound effects for Slimefun From 6b038509655817fa9d6ff80cd54dd5c5fade6438 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Wed, 27 Dec 2023 02:59:19 +0000 Subject: [PATCH 128/131] Fix contributor head being pullable (#4072) --- pom.xml | 8 +++++++- .../slimefun4/core/services/github/GitHubTask.java | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a548bfc1a6..8fa8a7be1d 100644 --- a/pom.xml +++ b/pom.xml @@ -355,7 +355,7 @@ com.github.baked-libs.dough dough-api - 4b28bd408e + da42c2f268 compile @@ -513,6 +513,12 @@ + + com.mojang + authlib + 1.5.25 + provided + commons-lang diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java index da42dfa996..8b065e3ff4 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java @@ -142,7 +142,7 @@ private int requestTexture(@Nonnull Contributor contributor, @Nonnull Map future = PlayerSkin.fromPlayerUUID(Slimefun.instance(), uuid.get()); - Optional skin = Optional.of(future.get().toString()); + Optional skin = Optional.of(future.get().getProfile().getBase64Texture()); skins.put(contributor.getMinecraftName(), skin.orElse("")); return skin.orElse(null); } else { From dad6020680bda143fb998020c33aa2270186b0f5 Mon Sep 17 00:00:00 2001 From: Silent <46107752+TheSilentPro@users.noreply.github.com> Date: Sun, 31 Dec 2023 09:58:28 +0100 Subject: [PATCH 129/131] Feature/block drop creative (#3934) Co-authored-by: J3fftw <44972470+J3fftw1@users.noreply.github.com> Co-authored-by: Silent --- .../slimefun4/implementation/listeners/BlockListener.java | 5 ++++- src/main/resources/config.yml | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index 91fb9eb291..1db923bebc 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -11,6 +11,7 @@ import javax.annotation.ParametersAreNonnullByDefault; import org.bukkit.Bukkit; +import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -240,7 +241,9 @@ private void dropItems(BlockBreakEvent e, List drops) { for (ItemStack drop : drops) { // Prevent null or air from being dropped if (drop != null && drop.getType() != Material.AIR) { - e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), drop); + if (e.getPlayer().getGameMode() != GameMode.CREATIVE || Slimefun.getCfg().getBoolean("options.drop-block-creative")) { + e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), drop); + } } } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index ece2aa3410..cb133170e4 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -22,6 +22,7 @@ options: burn-players-when-radioactive: true drop-excess-sf-give-items: false backup-data: true + drop-block-creative: true guide: show-vanilla-recipes: true From 4d710fa0b119a400478a22494c0f306648326bd0 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Tue, 2 Jan 2024 12:11:04 +0000 Subject: [PATCH 130/131] Storage rewrite - Phase 1 (#4065) * Phase 1 - wip * Add some tests * wip * Save waypoints * Implement backpacks * Add tests for waypoints * Changes to ADR * Small changes * Fix englandish and some small changes to UUID in PlayerProfile * Fix saving of player data in a few cases * Documentation around deprecated * Add some more tests * Some small doc updates * Make old Waypoint constructor deprecated and fix javadocs --- .adr-dir | 1 + .gitignore | 1 + docs/adr/0001-storage-layer.md | 129 ++++++ docs/adr/README.md | 11 + .../slimefun4/api/gps/GPSNetwork.java | 2 +- .../slimefun4/api/gps/Waypoint.java | 56 ++- .../slimefun4/api/items/SlimefunItem.java | 8 +- .../slimefun4/api/player/PlayerBackpack.java | 71 +++- .../slimefun4/api/player/PlayerProfile.java | 124 ++---- .../slimefun4/implementation/Slimefun.java | 16 + .../slimefun4/storage/Storage.java | 26 ++ .../storage/backend/legacy/LegacyStorage.java | 127 ++++++ .../slimefun4/storage/data/PlayerData.java | 96 +++++ .../slimefun4/api/gps/TestWaypoints.java | 31 +- .../api/profiles/TestPlayerBackpacks.java | 38 +- .../listeners/TestBackpackListener.java | 13 +- .../storage/backend/TestLegacyBackend.java | 383 ++++++++++++++++++ .../slimefun4/test/mocks/MockProfile.java | 9 +- 18 files changed, 975 insertions(+), 167 deletions(-) create mode 100644 .adr-dir create mode 100644 docs/adr/0001-storage-layer.md create mode 100644 docs/adr/README.md create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/storage/Storage.java create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/storage/backend/legacy/LegacyStorage.java create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/storage/data/PlayerData.java create mode 100644 src/test/java/io/github/thebusybiscuit/slimefun4/storage/backend/TestLegacyBackend.java diff --git a/.adr-dir b/.adr-dir new file mode 100644 index 0000000000..c73b64aed2 --- /dev/null +++ b/.adr-dir @@ -0,0 +1 @@ +docs/adr diff --git a/.gitignore b/.gitignore index fda2f4a052..f025c1e196 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /.settings/ /.idea/ /.vscode/ +/data-store/ dependency-reduced-pom.xml diff --git a/docs/adr/0001-storage-layer.md b/docs/adr/0001-storage-layer.md new file mode 100644 index 0000000000..0809ed04a2 --- /dev/null +++ b/docs/adr/0001-storage-layer.md @@ -0,0 +1,129 @@ +# 1. Storage layer + +Date: 2023-11-15 +Last update: 2023-12-27 + +**DO NOT rely on any APIs introduced until we finish the work completely!** + +## Status + +Work in progress + +## Context + +Slimefun has been around for a very long time and due to that, the way we +wrote persistence of data has also been around for a very long time. +While Slimefun has grown, the storage layer has never been adapted. +This means that even all these years later, it's using the same old saving/loading. +This isn't necessarily always bad, however, as Slimefun has grown both in terms of content +and the servers using it - we've seen some issues. + +Today, files are saved as YAML files (sometimes with just a JSON object per line), +which is good for a config format but not good for a data store. It can create very large files +that can get corrupted, the way we've been saving data often means loading it all at once as well +rather than lazy-loading and generally isn't very performant. + +For a long time we've been talking about rewriting our data storage in multiple forms +(you may have seen this referenced for "BlockStorage rewrite" or "SQL for PlayerProfiles", etc.). +Now is the time we start to do this, this will be a very large change and will not be done quickly or rushed. + +This ADR talks about the future of our data persistence. + +## Decision + +We want to create a new storage layer abstraction and implementations +which will be backwards-compatible but open up new ways of storing data +within Slimefun. The end end goal is we can quickly and easily support +new storage backends (such as binary storage, SQL, etc.) for things like +[PlayerProfile](https://github.com/Slimefun/Slimefun4/blob/bbfb9734b9f549d7e82291eff041f9b666a61b63/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java), [BlockStorage](https://github.com/Slimefun/Slimefun4/blob/bbfb9734b9f549d7e82291eff041f9b666a61b63/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java), etc. + +We also want to be generally more efficient in the way we save and load data. +Today, we load way more than is required. +We can improve memory usage by only loading what we need, when we need it. + +We will do this incrementally and at first, in an experimental context. +In that regard, we should aim to minimise the blast radius and lift as much +as possible. + +### Quick changes overview + +* New abstraction over storage to easily support multiple backends. +* Work towards moving away from the legacy YAML based storage. +* Lazy load and save data to more efficiently handle the data life cycle. + +### Implementation details + +There is a new interface called [`Storage`](TBD) which is what all storage +backends will implement. +This will have methods for loading and saving things like +[`PlayerProfile`](https://github.com/Slimefun/Slimefun4/blob/bbfb9734b9f549d7e82291eff041f9b666a61b63/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java) and [`BlockStorage`](https://github.com/Slimefun/Slimefun4/blob/bbfb9734b9f549d7e82291eff041f9b666a61b63/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java). + +Then, backends will implement these +(e.g. [`LegacyStorageBackend`](TBD) (today's YAML situation)) +in order to support these functions. +Not all storage backends are required support each data type. +e.g. SQL may not support [`BlockStorage`](https://github.com/Slimefun/Slimefun4/blob/bbfb9734b9f549d7e82291eff041f9b666a61b63/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java). + + +## Addons + +The goal is that Addons will be able to use and implement new storage backends +if they wish and also be extended so they can load/save things as they wish. + +The first few iterations will not focus on Addon support. We want to ensure +this new storage layer will work and supports what we need it to today. + +This ADR will be updated when we get to supporting Addons properly. + +## Considerations + +This will be a big change therefore we will be doing it as incrementally as +possible. +Changes will be tested while in the PR stage and merged into the Dev releases when possible. +We may do an experimental release if required. + +Phases do not (and very likely will not) be done within a single PR. They will also not have any timeframe attached to them. + +The current plan looks like this: + +* Phase 1 - Implement legacy data backend for [`PlayerProfile`](https://github.com/Slimefun/Slimefun4/blob/bbfb9734b9f549d7e82291eff041f9b666a61b63/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java). + * We want to load player data using the new storage layer with the current + data system. + * We'll want to monitor for any possible issues and generally refine + how this system should look +* Phase 2 - Implement new experimental binary backend for [`PlayerProfile`](https://github.com/Slimefun/Slimefun4/blob/bbfb9734b9f549d7e82291eff041f9b666a61b63/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java). + * Create a new backend for binary storage + * Implement in an experimental capacity and allow users to opt-in + * Provide a warning that this is **experimental** and there will be bugs. + * Implement new metric for storage backend being used +* Phase 3 - Mark the new backend as stable for [`PlayerProfile`](https://github.com/Slimefun/Slimefun4/blob/bbfb9734b9f549d7e82291eff041f9b666a61b63/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java). + * Mark it as stable and remove the warnings once we're sure things are + working correctly + * Create a migration path for users currently using "legacy". + * Enable by default for new servers +* Phase 4 - Move [`BlockStorage`](https://github.com/Slimefun/Slimefun4/blob/bbfb9734b9f549d7e82291eff041f9b666a61b63/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java) to new storage layer. + * The big one! We're gonna tackle adding this to BlockStorage. + This will probably be a large change and we'll want to be as + careful as possible here. + * Implement `legacy` and `binary` as experimental storage backends + for BlockStorage and allow users to opt-in + * Provide a warning that this is **experimental** and there will be bugs. +* Phase 5 - Mark the new storage layer as stable for [`BlockStorage`](https://github.com/Slimefun/Slimefun4/blob/bbfb9734b9f549d7e82291eff041f9b666a61b63/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java). + * Mark it as stable and remove the warnings once we're sure things are + working correctly + * Ensure migration path works here too. + * Enable by default for new servers +* Phase 6 - Finish up and move anything else we want over + * Move over any other data stores we have to the new layer + * We should probably still do experimental -> stable but it should have + less of a lead time. + +## State of work + +* Phase 1: In progress + * https://github.com/Slimefun/Slimefun4/pull/4065 +* Phase 2: Not started +* Phase 3: Not started +* Phase 4: Not started +* Phase 5: Not started +* Phase 6: Not started diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 0000000000..1762af11cd --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,11 @@ +# ADR + +An ADR (Architecture Decision Record) is a document describing large changes, why we made them, etc. + +## Making a new ADR + +If you're making a large change to Slimefun, we recommend creating an ADR +in order to document why this is being made and how it works for future contributors. + +Please follow the general format of the former ADRs or use a tool +such as [`adr-tools`](https://github.com/npryce/adr-tools) to generate a new document. \ No newline at end of file diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/GPSNetwork.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/GPSNetwork.java index d2d9a3c1ee..47574fb2ca 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/GPSNetwork.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/GPSNetwork.java @@ -331,7 +331,7 @@ public void addWaypoint(@Nonnull Player p, @Nonnull String name, @Nonnull Locati } } - profile.addWaypoint(new Waypoint(profile, id, event.getLocation(), event.getName())); + profile.addWaypoint(new Waypoint(p.getUniqueId(), id, event.getLocation(), event.getName())); SoundEffect.GPS_NETWORK_ADD_WAYPOINT.playFor(p); Slimefun.getLocalization().sendMessage(p, "gps.waypoint.added", true); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/Waypoint.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/Waypoint.java index 13c8b42561..468b70af6b 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/Waypoint.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/Waypoint.java @@ -1,11 +1,13 @@ package io.github.thebusybiscuit.slimefun4.api.gps; import java.util.Objects; +import java.util.UUID; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World.Environment; import org.bukkit.entity.Player; @@ -30,14 +32,14 @@ */ public class Waypoint { - private final PlayerProfile profile; + private final UUID ownerId; private final String id; private final String name; private final Location location; /** * This constructs a new {@link Waypoint} object. - * + * * @param profile * The owning {@link PlayerProfile} * @param id @@ -46,28 +48,62 @@ public class Waypoint { * The {@link Location} of the {@link Waypoint} * @param name * The name of this {@link Waypoint} + * + * @deprecated Use {@link #Waypoint(UUID, String, Location, String)} instead */ + @Deprecated @ParametersAreNonnullByDefault public Waypoint(PlayerProfile profile, String id, Location loc, String name) { - Validate.notNull(profile, "Profile must never be null!"); + this(profile.getUUID(), id, loc, name); + } + + /** + * This constructs a new {@link Waypoint} object. + * + * @param ownerId + * The owning {@link Player}'s {@link UUID} + * @param id + * The unique id for this {@link Waypoint} + * @param loc + * The {@link Location} of the {@link Waypoint} + * @param name + * The name of this {@link Waypoint} + */ + @ParametersAreNonnullByDefault + public Waypoint(UUID ownerId, String id, Location loc, String name) { + Validate.notNull(ownerId, "owner ID must never be null!"); Validate.notNull(id, "id must never be null!"); Validate.notNull(loc, "Location must never be null!"); Validate.notNull(name, "Name must never be null!"); - this.profile = profile; + this.ownerId = ownerId; this.id = id; this.location = loc; this.name = name; } /** - * This returns the owner of the {@link Waypoint}. + * This returns the owner's {@link UUID} of the {@link Waypoint}. * + * @return The corresponding owner's {@link UUID} + */ + @Nonnull + public UUID getOwnerId() { + return this.ownerId; + } + + /** + * This returns the owner of the {@link Waypoint}. + * * @return The corresponding {@link PlayerProfile} + * + * @deprecated Use {@link #getOwnerId()} instead */ @Nonnull + @Deprecated public PlayerProfile getOwner() { - return profile; + // This is jank and should never actually return null + return PlayerProfile.find(Bukkit.getOfflinePlayer(ownerId)).orElse(null); } /** @@ -126,7 +162,7 @@ public ItemStack getIcon() { */ @Override public int hashCode() { - return Objects.hash(profile.getUUID(), id, name, location); + return Objects.hash(this.ownerId, this.id, this.name, this.location); } /** @@ -139,7 +175,9 @@ public boolean equals(Object obj) { } Waypoint waypoint = (Waypoint) obj; - return profile.getUUID().equals(waypoint.getOwner().getUUID()) && id.equals(waypoint.getId()) && location.equals(waypoint.getLocation()) && name.equals(waypoint.getName()); + return this.ownerId.equals(waypoint.getOwnerId()) + && id.equals(waypoint.getId()) + && location.equals(waypoint.getLocation()) + && name.equals(waypoint.getName()); } - } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java index 20a12ef6b7..28dc680ff1 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/SlimefunItem.java @@ -1160,11 +1160,11 @@ public final int hashCode() { } /** - * Retrieve a {@link Optional}<{@link SlimefunItem}> by its id. + * Retrieve a {@link Optional} {@link SlimefunItem} by its id. * * @param id * The id of the {@link SlimefunItem} - * @return The {@link Optional}<{@link SlimefunItem}> associated with that id. Empty if non-existent + * @return The {@link Optional} {@link SlimefunItem} associated with that id. Empty if non-existent */ public static @Nonnull Optional getOptionalById(@Nonnull String id) { return Optional.ofNullable(getById(id)); @@ -1193,11 +1193,11 @@ public final int hashCode() { } /** - * Retrieve a {@link Optional}<{@link SlimefunItem}> from an {@link ItemStack}. + * Retrieve a {@link Optional} {@link SlimefunItem} from an {@link ItemStack}. * * @param item * The {@link ItemStack} to check - * @return The {@link Optional}<{@link SlimefunItem}> associated with this {@link ItemStack} if present, otherwise empty + * @return The {@link Optional} {@link SlimefunItem} associated with this {@link ItemStack} if present, otherwise empty */ public @Nonnull Optional getOptionalByItem(@Nullable ItemStack item) { return Optional.ofNullable(getByItem(item)); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerBackpack.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerBackpack.java index 4960a7c9b3..c0886778df 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerBackpack.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerBackpack.java @@ -2,10 +2,13 @@ import java.io.File; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; import org.bukkit.Bukkit; import org.bukkit.entity.HumanEntity; @@ -34,13 +37,22 @@ public class PlayerBackpack { private static final String CONFIG_PREFIX = "backpacks."; - private final PlayerProfile profile; + private final UUID ownerId; private final int id; - private final Config cfg; + @Deprecated + private PlayerProfile profile; + @Deprecated + private Config cfg; private Inventory inventory; private int size; + private PlayerBackpack(@Nonnull UUID ownerId, int id, int size) { + this.ownerId = ownerId; + this.id = id; + this.size = size; + } + /** * This constructor loads an existing Backpack * @@ -48,7 +60,10 @@ public class PlayerBackpack { * The {@link PlayerProfile} of this Backpack * @param id * The id of this Backpack + * + * @deprecated Use {@link PlayerBackpack#load(UUID, int, int, HashMap)} instead */ + @Deprecated public PlayerBackpack(@Nonnull PlayerProfile profile, int id) { this(profile, id, profile.getConfig().getInt(CONFIG_PREFIX + id + ".size")); @@ -66,12 +81,16 @@ public PlayerBackpack(@Nonnull PlayerProfile profile, int id) { * The id of this Backpack * @param size * The size of this Backpack + * + * @deprecated Use {@link PlayerBackpack#newBackpack(UUID, int, int)} instead */ + @Deprecated public PlayerBackpack(@Nonnull PlayerProfile profile, int id, int size) { if (size < 9 || size > 54 || size % 9 != 0) { throw new IllegalArgumentException("Invalid size! Size must be one of: [9, 18, 27, 36, 45, 54]"); } + this.ownerId = profile.getUUID(); this.profile = profile; this.id = id; this.cfg = profile.getConfig(); @@ -96,10 +115,17 @@ public int getId() { * This method returns the {@link PlayerProfile} this {@link PlayerBackpack} belongs to * * @return The owning {@link PlayerProfile} + * + * @deprecated Use {@link PlayerBackpack#getOwnerId()} instead */ + @Deprecated @Nonnull public PlayerProfile getOwner() { - return profile; + return profile != null ? profile : PlayerProfile.find(Bukkit.getOfflinePlayer(ownerId)).orElse(null); + } + + public UUID getOwnerId() { + return this.ownerId; } /** @@ -172,7 +198,6 @@ public void setSize(int size) { } this.size = size; - cfg.setValue(CONFIG_PREFIX + id + ".size", size); Inventory inv = Bukkit.createInventory(null, size, "Backpack [" + size + " Slots]"); @@ -187,7 +212,10 @@ public void setSize(int size) { /** * This method will save the contents of this backpack to a {@link File}. + * + * @deprecated Handled by {@link PlayerProfile#save()} now */ + @Deprecated public void save() { for (int i = 0; i < size; i++) { cfg.setValue(CONFIG_PREFIX + id + ".contents." + i, inventory.getItem(i)); @@ -199,7 +227,40 @@ public void save() { * using {@link PlayerBackpack#save()} */ public void markDirty() { - profile.markDirty(); + if (profile != null) { + profile.markDirty(); + } } + private void setContents(int size, HashMap contents) { + if (this.inventory == null) { + this.inventory = Bukkit.createInventory(null, size, "Backpack [" + size + " Slots]"); + } + + for (int i = 0; i < size; i++) { + this.inventory.setItem(i, contents.get(i)); + } + } + + @ParametersAreNonnullByDefault + public static PlayerBackpack load(UUID ownerId, int id, int size, HashMap contents) { + PlayerBackpack backpack = new PlayerBackpack(ownerId, id, size); + + backpack.setContents(size, contents); + + return backpack; + } + + @ParametersAreNonnullByDefault + public static PlayerBackpack newBackpack(UUID ownerId, int id, int size) { + if (size < 9 || size > 54 || size % 9 != 0) { + throw new IllegalArgumentException("Invalid size! Size must be one of: [9, 18, 27, 36, 45, 54]"); + } + + PlayerBackpack backpack = new PlayerBackpack(ownerId, id, size); + + backpack.setContents(size, new HashMap<>()); + + return backpack; + } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java index 7b975f5702..c51888a1d0 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java @@ -1,27 +1,22 @@ package io.github.thebusybiscuit.slimefun4.api.player; -import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.OptionalInt; import java.util.Set; import java.util.UUID; import java.util.function.Consumer; -import java.util.logging.Level; import java.util.stream.IntStream; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import io.github.thebusybiscuit.slimefun4.storage.data.PlayerData; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.Location; import org.bukkit.NamespacedKey; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; @@ -59,50 +54,26 @@ */ public class PlayerProfile { - private final UUID uuid; + private final UUID ownerId; private final String name; private final Config configFile; - private final Config waypointsFile; private boolean dirty = false; private boolean markedForDeletion = false; - private final Set researches = new HashSet<>(); - private final List waypoints = new ArrayList<>(); - private final Map backpacks = new HashMap<>(); private final GuideHistory guideHistory = new GuideHistory(this); private final HashedArmorpiece[] armor = { new HashedArmorpiece(), new HashedArmorpiece(), new HashedArmorpiece(), new HashedArmorpiece() }; - protected PlayerProfile(@Nonnull OfflinePlayer p) { - this.uuid = p.getUniqueId(); - this.name = p.getName(); + private final PlayerData data; - configFile = new Config("data-storage/Slimefun/Players/" + uuid.toString() + ".yml"); - waypointsFile = new Config("data-storage/Slimefun/waypoints/" + uuid.toString() + ".yml"); + protected PlayerProfile(@Nonnull OfflinePlayer p, PlayerData data) { + this.ownerId = p.getUniqueId(); + this.name = p.getName(); + this.data = data; - loadProfileData(); - } - - private void loadProfileData() { - for (Research research : Slimefun.getRegistry().getResearches()) { - if (configFile.contains("researches." + research.getID())) { - researches.add(research); - } - } - - for (String key : waypointsFile.getKeys()) { - try { - if (waypointsFile.contains(key + ".world") && Bukkit.getWorld(waypointsFile.getString(key + ".world")) != null) { - String waypointName = waypointsFile.getString(key + ".name"); - Location loc = waypointsFile.getLocation(key); - waypoints.add(new Waypoint(this, key, loc, waypointName)); - } - } catch (Exception x) { - Slimefun.logger().log(Level.WARNING, x, () -> "Could not load Waypoint \"" + key + "\" for Player \"" + name + '"'); - } - } + configFile = new Config("data-storage/Slimefun/Players/" + ownerId.toString() + ".yml"); } /** @@ -131,7 +102,7 @@ private void loadProfileData() { * @return The {@link UUID} of our {@link PlayerProfile} */ public @Nonnull UUID getUUID() { - return uuid; + return ownerId; } /** @@ -157,12 +128,7 @@ public boolean isDirty() { * This method will save the Player's Researches and Backpacks to the hard drive */ public void save() { - for (PlayerBackpack backpack : backpacks.values()) { - backpack.save(); - } - - waypointsFile.save(); - configFile.save(); + Slimefun.getPlayerStorage().savePlayerData(this.ownerId, this.data); dirty = false; } @@ -180,11 +146,9 @@ public void setResearched(@Nonnull Research research, boolean unlock) { dirty = true; if (unlock) { - configFile.setValue("researches." + research.getID(), true); - researches.add(research); + data.addResearch(research); } else { - configFile.setValue("researches." + research.getID(), null); - researches.remove(research); + data.removeResearch(research); } } @@ -202,7 +166,7 @@ public boolean hasUnlocked(@Nullable Research research) { return true; } - return !research.isEnabled() || researches.contains(research); + return !research.isEnabled() || data.getResearches().contains(research); } /** @@ -228,7 +192,7 @@ public boolean hasUnlockedEverything() { * @return A {@code Hashset} of all Researches this {@link Player} has unlocked */ public @Nonnull Set getResearches() { - return ImmutableSet.copyOf(researches); + return ImmutableSet.copyOf(this.data.getResearches()); } /** @@ -238,7 +202,7 @@ public boolean hasUnlockedEverything() { * @return A {@link List} containing every {@link Waypoint} */ public @Nonnull List getWaypoints() { - return ImmutableList.copyOf(waypoints); + return ImmutableList.copyOf(this.data.getWaypoints()); } /** @@ -249,21 +213,8 @@ public boolean hasUnlockedEverything() { * The {@link Waypoint} to add */ public void addWaypoint(@Nonnull Waypoint waypoint) { - Validate.notNull(waypoint, "Cannot add a 'null' waypoint!"); - - for (Waypoint wp : waypoints) { - if (wp.getId().equals(waypoint.getId())) { - throw new IllegalArgumentException("A Waypoint with that id already exists for this Player"); - } - } - - if (waypoints.size() < 21) { - waypoints.add(waypoint); - - waypointsFile.setValue(waypoint.getId(), waypoint.getLocation()); - waypointsFile.setValue(waypoint.getId() + ".name", waypoint.getName()); - markDirty(); - } + this.data.addWaypoint(waypoint); + markDirty(); } /** @@ -274,12 +225,8 @@ public void addWaypoint(@Nonnull Waypoint waypoint) { * The {@link Waypoint} to remove */ public void removeWaypoint(@Nonnull Waypoint waypoint) { - Validate.notNull(waypoint, "Cannot remove a 'null' waypoint!"); - - if (waypoints.remove(waypoint)) { - waypointsFile.setValue(waypoint.getId(), null); - markDirty(); - } + this.data.removeWaypoint(waypoint); + markDirty(); } /** @@ -301,8 +248,10 @@ public final void markDirty() { IntStream stream = IntStream.iterate(0, i -> i + 1).filter(i -> !configFile.contains("backpacks." + i + ".size")); int id = stream.findFirst().getAsInt(); - PlayerBackpack backpack = new PlayerBackpack(this, id, size); - backpacks.put(id, backpack); + PlayerBackpack backpack = PlayerBackpack.newBackpack(this.ownerId, id, size); + this.data.addBackpack(backpack); + + markDirty(); return backpack; } @@ -312,13 +261,10 @@ public final void markDirty() { throw new IllegalArgumentException("Backpacks cannot have negative ids!"); } - PlayerBackpack backpack = backpacks.get(id); + PlayerBackpack backpack = data.getBackpack(id); if (backpack != null) { - return Optional.of(backpack); - } else if (configFile.contains("backpacks." + id + ".size")) { - backpack = new PlayerBackpack(this, id); - backpacks.put(id, backpack); + markDirty(); return Optional.of(backpack); } @@ -346,7 +292,7 @@ private int countNonEmptyResearches(@Nonnull Collection researches) { List titles = Slimefun.getRegistry().getResearchRanks(); int allResearches = countNonEmptyResearches(Slimefun.getRegistry().getResearches()); - float fraction = (float) countNonEmptyResearches(researches) / allResearches; + float fraction = (float) countNonEmptyResearches(getResearches()) / allResearches; int index = (int) (fraction * (titles.size() - 1)); return titles.get(index); @@ -420,7 +366,9 @@ public static boolean get(@Nonnull OfflinePlayer p, @Nonnull Consumer { - AsyncProfileLoadEvent event = new AsyncProfileLoadEvent(new PlayerProfile(p)); + PlayerData data = Slimefun.getPlayerStorage().loadPlayerData(p.getUniqueId()); + + AsyncProfileLoadEvent event = new AsyncProfileLoadEvent(new PlayerProfile(p, data)); Bukkit.getPluginManager().callEvent(event); Slimefun.getRegistry().getPlayerProfiles().put(uuid, event.getProfile()); @@ -445,7 +393,9 @@ public static boolean request(@Nonnull OfflinePlayer p) { if (!Slimefun.getRegistry().getPlayerProfiles().containsKey(p.getUniqueId())) { // Should probably prevent multiple requests for the same profile in the future Bukkit.getScheduler().runTaskAsynchronously(Slimefun.instance(), () -> { - PlayerProfile pp = new PlayerProfile(p); + PlayerData data = Slimefun.getPlayerStorage().loadPlayerData(p.getUniqueId()); + + PlayerProfile pp = new PlayerProfile(p, data); Slimefun.getRegistry().getPlayerProfiles().put(p.getUniqueId(), pp); }); @@ -527,19 +477,23 @@ public boolean hasFullProtectionAgainst(@Nonnull ProtectionType type) { return armorCount == 4; } + public PlayerData getPlayerData() { + return this.data; + } + @Override public int hashCode() { - return uuid.hashCode(); + return ownerId.hashCode(); } @Override public boolean equals(Object obj) { - return obj instanceof PlayerProfile profile && uuid.equals(profile.uuid); + return obj instanceof PlayerProfile profile && ownerId.equals(profile.ownerId); } @Override public String toString() { - return "PlayerProfile {" + uuid + "}"; + return "PlayerProfile {" + ownerId + "}"; } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java index e8c7b460a1..8667eed682 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java @@ -15,6 +15,9 @@ import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import io.github.thebusybiscuit.slimefun4.storage.Storage; +import io.github.thebusybiscuit.slimefun4.storage.backend.legacy.LegacyStorage; + import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.Server; @@ -197,6 +200,9 @@ public final class Slimefun extends JavaPlugin implements SlimefunAddon { private final Config items = new Config(this, "Items.yml"); private final Config researches = new Config(this, "Researches.yml"); + // Data storage + private Storage playerStorage; + // Listeners that need to be accessed elsewhere private final GrapplingHookListener grapplingHookListener = new GrapplingHookListener(); private final BackpackListener backpackListener = new BackpackListener(); @@ -258,6 +264,9 @@ private void onUnitTestStart() { registry.load(this, config); loadTags(); soundService.reload(false); + // TODO: What do we do if tests want to use another storage backend (e.g. testing new feature on legacy + sql)? + // Do we have a way to override this? + playerStorage = new LegacyStorage(); } /** @@ -312,6 +321,10 @@ private void onPluginStart() { networkManager = new NetworkManager(networkSize, config.getBoolean("networks.enable-visualizer"), config.getBoolean("networks.delete-excess-items")); + // Data storage + playerStorage = new LegacyStorage(); + logger.log(Level.INFO, "Using legacy storage for player data"); + // Setting up bStats new Thread(metricsService::start, "Slimefun Metrics").start(); @@ -1068,4 +1081,7 @@ public static boolean isNewlyInstalled() { return instance.getServer().getScheduler().runTask(instance, runnable); } + public static @Nonnull Storage getPlayerStorage() { + return instance().playerStorage; + } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/storage/Storage.java b/src/main/java/io/github/thebusybiscuit/slimefun4/storage/Storage.java new file mode 100644 index 0000000000..037db2afc3 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/storage/Storage.java @@ -0,0 +1,26 @@ +package io.github.thebusybiscuit.slimefun4.storage; + +import io.github.thebusybiscuit.slimefun4.storage.data.PlayerData; + +import javax.annotation.concurrent.ThreadSafe; + +import com.google.common.annotations.Beta; + +import java.util.UUID; + +/** + * The {@link Storage} interface is the abstract layer on top of our storage backends. + * Every backend has to implement this interface and has to implement it in a thread-safe way. + * There will be no expectation of running functions in here within the main thread. + * + *

+ * This API is still experimental, it may change without notice. + */ +@Beta +@ThreadSafe +public interface Storage { + + PlayerData loadPlayerData(UUID uuid); + + void savePlayerData(UUID uuid, PlayerData data); +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/storage/backend/legacy/LegacyStorage.java b/src/main/java/io/github/thebusybiscuit/slimefun4/storage/backend/legacy/LegacyStorage.java new file mode 100644 index 0000000000..d7981a5466 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/storage/backend/legacy/LegacyStorage.java @@ -0,0 +1,127 @@ +package io.github.thebusybiscuit.slimefun4.storage.backend.legacy; + +import io.github.bakedlibs.dough.config.Config; +import io.github.thebusybiscuit.slimefun4.api.gps.Waypoint; +import io.github.thebusybiscuit.slimefun4.api.player.PlayerBackpack; +import io.github.thebusybiscuit.slimefun4.api.researches.Research; +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; +import io.github.thebusybiscuit.slimefun4.storage.Storage; +import io.github.thebusybiscuit.slimefun4.storage.data.PlayerData; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.inventory.ItemStack; + +import com.google.common.annotations.Beta; + +import javax.annotation.Nonnull; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import java.util.logging.Level; + +@Beta +public class LegacyStorage implements Storage { + + @Override + public PlayerData loadPlayerData(@Nonnull UUID uuid) { + Config playerFile = new Config("data-storage/Slimefun/Players/" + uuid + ".yml"); + // Not too sure why this is its own file + Config waypointsFile = new Config("data-storage/Slimefun/waypoints/" + uuid + ".yml"); + + // Load research + Set researches = new HashSet<>(); + for (Research research : Slimefun.getRegistry().getResearches()) { + if (playerFile.contains("researches." + research.getID())) { + researches.add(research); + } + } + + // Load backpacks + HashMap backpacks = new HashMap<>(); + for (String key : playerFile.getKeys("backpacks")) { + try { + int id = Integer.parseInt(key); + int size = playerFile.getInt("backpacks." + key + ".size"); + + HashMap items = new HashMap<>(); + for (int i = 0; i < size; i++) { + items.put(i, playerFile.getItem("backpacks." + key + ".contents." + i)); + } + + PlayerBackpack backpack = PlayerBackpack.load(uuid, id, size, items); + + backpacks.put(id, backpack); + } catch (Exception x) { + Slimefun.logger().log(Level.WARNING, x, () -> "Could not load Backpack \"" + key + "\" for Player \"" + uuid + '"'); + } + } + + // Load waypoints + Set waypoints = new HashSet<>(); + for (String key : waypointsFile.getKeys()) { + try { + if (waypointsFile.contains(key + ".world") && Bukkit.getWorld(waypointsFile.getString(key + ".world")) != null) { + String waypointName = waypointsFile.getString(key + ".name"); + Location loc = waypointsFile.getLocation(key); + waypoints.add(new Waypoint(uuid, key, loc, waypointName)); + } + } catch (Exception x) { + Slimefun.logger().log(Level.WARNING, x, () -> "Could not load Waypoint \"" + key + "\" for Player \"" + uuid + '"'); + } + } + + return new PlayerData(researches, backpacks, waypoints); + } + + // The current design of saving all at once isn't great, this will be refined. + @Override + public void savePlayerData(@Nonnull UUID uuid, @Nonnull PlayerData data) { + Config playerFile = new Config("data-storage/Slimefun/Players/" + uuid + ".yml"); + // Not too sure why this is its own file + Config waypointsFile = new Config("data-storage/Slimefun/waypoints/" + uuid + ".yml"); + + // Save research + playerFile.setValue("rearches", null); + for (Research research : Slimefun.getRegistry().getResearches()) { + // Save the research if it's researched + if (data.getResearches().contains(research)) { + playerFile.setValue("researches." + research.getID(), true); + + // Remove the research if it's no longer researched + } else if (playerFile.contains("researches." + research.getID())) { + playerFile.setValue("researches." + research.getID(), null); + } + } + + // Save backpacks + for (PlayerBackpack backpack : data.getBackpacks().values()) { + playerFile.setValue("backpacks." + backpack.getId() + ".size", backpack.getSize()); + + for (int i = 0; i < backpack.getSize(); i++) { + ItemStack item = backpack.getInventory().getItem(i); + if (item != null) { + playerFile.setValue("backpacks." + backpack.getId() + ".contents." + i, item); + + // Remove the item if it's no longer in the inventory + } else if (playerFile.contains("backpacks." + backpack.getId() + ".contents." + i)) { + playerFile.setValue("backpacks." + backpack.getId() + ".contents." + i, null); + } + } + } + + // Save waypoints + waypointsFile.clear(); + for (Waypoint waypoint : data.getWaypoints()) { + // Legacy data uses IDs + waypointsFile.setValue(waypoint.getId(), waypoint.getLocation()); + waypointsFile.setValue(waypoint.getId() + ".name", waypoint.getName()); + } + + // Save files + playerFile.save(); + waypointsFile.save(); + } +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/storage/data/PlayerData.java b/src/main/java/io/github/thebusybiscuit/slimefun4/storage/data/PlayerData.java new file mode 100644 index 0000000000..8615b6ee5f --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/storage/data/PlayerData.java @@ -0,0 +1,96 @@ +package io.github.thebusybiscuit.slimefun4.storage.data; + +import com.google.common.annotations.Beta; + +import io.github.thebusybiscuit.slimefun4.api.gps.Waypoint; +import io.github.thebusybiscuit.slimefun4.api.player.PlayerBackpack; +import io.github.thebusybiscuit.slimefun4.api.researches.Research; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.annotation.Nonnull; + +import org.apache.commons.lang.Validate; + +/** + * The data which backs {@link io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile} + * + * This API is still experimental, it may change without notice. + */ +// TODO: Should we keep this in PlayerProfile? +@Beta +public class PlayerData { + + private final Set researches = new HashSet<>(); + private final Map backpacks = new HashMap<>(); + private final Set waypoints = new HashSet<>(); + + public PlayerData(Set researches, Map backpacks, Set waypoints) { + this.researches.addAll(researches); + this.backpacks.putAll(backpacks); + this.waypoints.addAll(waypoints); + } + + public Set getResearches() { + return researches; + } + + public void addResearch(@Nonnull Research research) { + Validate.notNull(research, "Cannot add a 'null' research!"); + researches.add(research); + } + + public void removeResearch(@Nonnull Research research) { + Validate.notNull(research, "Cannot remove a 'null' research!"); + researches.remove(research); + } + + @Nonnull + public Map getBackpacks() { + return backpacks; + } + + @Nonnull + public PlayerBackpack getBackpack(int id) { + return backpacks.get(id); + } + + public void addBackpack(@Nonnull PlayerBackpack backpack) { + Validate.notNull(backpack, "Cannot add a 'null' backpack!"); + backpacks.put(backpack.getId(), backpack); + } + + public void removeBackpack(@Nonnull PlayerBackpack backpack) { + Validate.notNull(backpack, "Cannot remove a 'null' backpack!"); + backpacks.remove(backpack.getId()); + } + + public Set getWaypoints() { + return waypoints; + } + + public void addWaypoint(@Nonnull Waypoint waypoint) { + Validate.notNull(waypoint, "Cannot add a 'null' waypoint!"); + + for (Waypoint wp : waypoints) { + if (wp.getId().equals(waypoint.getId())) { + throw new IllegalArgumentException("A Waypoint with that id already exists for this Player"); + } + } + + // Limited to 21 due to limited UI space and no pagination + if (waypoints.size() >= 21) { + return; // not sure why this doesn't throw but the one above does... + } + + waypoints.add(waypoint); + } + + public void removeWaypoint(@Nonnull Waypoint waypoint) { + Validate.notNull(waypoint, "Cannot remove a 'null' waypoint!"); + waypoints.remove(waypoint); + } +} diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/api/gps/TestWaypoints.java b/src/test/java/io/github/thebusybiscuit/slimefun4/api/gps/TestWaypoints.java index d115135ba7..a0de64b14f 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/api/gps/TestWaypoints.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/api/gps/TestWaypoints.java @@ -1,5 +1,9 @@ package io.github.thebusybiscuit.slimefun4.api.gps; +import java.io.File; +import java.io.IOException; + +import org.apache.commons.io.FileUtils; import org.bukkit.entity.Player; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; @@ -19,16 +23,20 @@ class TestWaypoints { private static ServerMock server; private static Slimefun plugin; + private static File dataFolder; @BeforeAll public static void load() { server = MockBukkit.mock(); plugin = MockBukkit.load(Slimefun.class); + dataFolder = new File("data-storage/Slimefun/waypoints"); + dataFolder.mkdirs(); } @AfterAll - public static void unload() { + public static void unload() throws IOException { MockBukkit.unmock(); + FileUtils.deleteDirectory(dataFolder); } @Test @@ -38,9 +46,8 @@ void testAddWaypointToProfile() throws InterruptedException { PlayerProfile profile = TestUtilities.awaitProfile(player); Assertions.assertTrue(profile.getWaypoints().isEmpty()); - Waypoint waypoint = new Waypoint(profile, "hello", player.getLocation(), "HELLO"); + Waypoint waypoint = new Waypoint(player.getUniqueId(), "hello", player.getLocation(), "HELLO"); profile.addWaypoint(waypoint); - Assertions.assertTrue(profile.isDirty()); Assertions.assertThrows(IllegalArgumentException.class, () -> profile.addWaypoint(null)); @@ -55,7 +62,7 @@ void testRemoveWaypointFromProfile() throws InterruptedException { Player player = server.addPlayer(); PlayerProfile profile = TestUtilities.awaitProfile(player); - Waypoint waypoint = new Waypoint(profile, "hello", player.getLocation(), "HELLO"); + Waypoint waypoint = new Waypoint(player.getUniqueId(), "hello", player.getLocation(), "HELLO"); profile.addWaypoint(waypoint); Assertions.assertEquals(1, profile.getWaypoints().size()); @@ -76,7 +83,7 @@ void testWaypointAlreadyExisting() throws InterruptedException { Player player = server.addPlayer(); PlayerProfile profile = TestUtilities.awaitProfile(player); - Waypoint waypoint = new Waypoint(profile, "test", player.getLocation(), "Testing"); + Waypoint waypoint = new Waypoint(player.getUniqueId(), "test", player.getLocation(), "Testing"); profile.addWaypoint(waypoint); Assertions.assertEquals(1, profile.getWaypoints().size()); @@ -91,7 +98,7 @@ void testTooManyWaypoints() throws InterruptedException { PlayerProfile profile = TestUtilities.awaitProfile(player); for (int i = 0; i < 99; i++) { - Waypoint waypoint = new Waypoint(profile, String.valueOf(i), player.getLocation(), "Test"); + Waypoint waypoint = new Waypoint(player.getUniqueId(), String.valueOf(i), player.getLocation(), "Test"); profile.addWaypoint(waypoint); } @@ -114,11 +121,10 @@ void testWaypointEvent() throws InterruptedException { @DisplayName("Test equal Waypoints being equal") void testWaypointComparison() throws InterruptedException { Player player = server.addPlayer(); - PlayerProfile profile = TestUtilities.awaitProfile(player); - Waypoint waypoint = new Waypoint(profile, "waypoint", player.getLocation(), "Test"); - Waypoint same = new Waypoint(profile, "waypoint", player.getLocation(), "Test"); - Waypoint different = new Waypoint(profile, "waypoint_nope", player.getLocation(), "Test2"); + Waypoint waypoint = new Waypoint(player.getUniqueId(), "waypoint", player.getLocation(), "Test"); + Waypoint same = new Waypoint(player.getUniqueId(), "waypoint", player.getLocation(), "Test"); + Waypoint different = new Waypoint(player.getUniqueId(), "waypoint_nope", player.getLocation(), "Test2"); Assertions.assertEquals(waypoint, same); Assertions.assertEquals(waypoint.hashCode(), same.hashCode()); @@ -131,10 +137,9 @@ void testWaypointComparison() throws InterruptedException { @DisplayName("Test Deathpoints being recognized as Deathpoints") void testIsDeathpoint() throws InterruptedException { Player player = server.addPlayer(); - PlayerProfile profile = TestUtilities.awaitProfile(player); - Waypoint waypoint = new Waypoint(profile, "waypoint", player.getLocation(), "Some Waypoint"); - Waypoint deathpoint = new Waypoint(profile, "deathpoint", player.getLocation(), "player:death I died"); + Waypoint waypoint = new Waypoint(player.getUniqueId(), "waypoint", player.getLocation(), "Some Waypoint"); + Waypoint deathpoint = new Waypoint(player.getUniqueId(), "deathpoint", player.getLocation(), "player:death I died"); Assertions.assertFalse(waypoint.isDeathpoint()); Assertions.assertTrue(deathpoint.isDeathpoint()); diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/api/profiles/TestPlayerBackpacks.java b/src/test/java/io/github/thebusybiscuit/slimefun4/api/profiles/TestPlayerBackpacks.java index 3c1ae7175c..07f69761e0 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/api/profiles/TestPlayerBackpacks.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/api/profiles/TestPlayerBackpacks.java @@ -2,9 +2,7 @@ import java.util.Optional; -import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -39,16 +37,12 @@ public static void unload() { void testCreateBackpack() throws InterruptedException { Player player = server.addPlayer(); PlayerProfile profile = TestUtilities.awaitProfile(player); - Assertions.assertFalse(profile.isDirty()); PlayerBackpack backpack = profile.createBackpack(18); Assertions.assertNotNull(backpack); - // Creating a backpack should mark profiles as dirty - Assertions.assertTrue(profile.isDirty()); - - Assertions.assertEquals(profile, backpack.getOwner()); + Assertions.assertEquals(player.getUniqueId(), backpack.getOwnerId()); Assertions.assertEquals(18, backpack.getSize()); Assertions.assertEquals(18, backpack.getInventory().getSize()); } @@ -71,7 +65,6 @@ void testChangeSize() throws InterruptedException { backpack.setSize(27); Assertions.assertEquals(27, backpack.getSize()); - Assertions.assertTrue(profile.isDirty()); } @Test @@ -90,33 +83,4 @@ void testGetBackpackById() throws InterruptedException { Assertions.assertFalse(profile.getBackpack(500).isPresent()); } - - @Test - @DisplayName("Test loading a backpack from file") - void testLoadBackpackFromFile() throws InterruptedException { - Player player = server.addPlayer(); - PlayerProfile profile = TestUtilities.awaitProfile(player); - - profile.getConfig().setValue("backpacks.50.size", 27); - - for (int i = 0; i < 27; i++) { - profile.getConfig().setValue("backpacks.50.contents." + i, new ItemStack(Material.DIAMOND)); - } - - Optional optional = profile.getBackpack(50); - Assertions.assertTrue(optional.isPresent()); - - PlayerBackpack backpack = optional.get(); - Assertions.assertEquals(50, backpack.getId()); - Assertions.assertEquals(27, backpack.getSize()); - Assertions.assertEquals(-1, backpack.getInventory().firstEmpty()); - - backpack.getInventory().setItem(1, new ItemStack(Material.NETHER_STAR)); - - Assertions.assertEquals(new ItemStack(Material.DIAMOND), profile.getConfig().getItem("backpacks.50.contents.1")); - - // Saving should write it to the Config file - backpack.save(); - Assertions.assertEquals(new ItemStack(Material.NETHER_STAR), profile.getConfig().getItem("backpacks.50.contents.1")); - } } diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TestBackpackListener.java b/src/test/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TestBackpackListener.java index 01e83b9e71..443d47c3c7 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TestBackpackListener.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TestBackpackListener.java @@ -13,7 +13,6 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryAction; import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryType.SlotType; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.inventory.Inventory; @@ -119,7 +118,7 @@ void testSetId() throws InterruptedException { Assertions.assertEquals(ChatColor.GRAY + "ID: " + player.getUniqueId() + "#" + id, item.getItemMeta().getLore().get(2)); PlayerBackpack backpack = awaitBackpack(item); - Assertions.assertEquals(player.getUniqueId(), backpack.getOwner().getUUID()); + Assertions.assertEquals(player.getUniqueId(), backpack.getOwnerId()); Assertions.assertEquals(id, backpack.getId()); } @@ -132,16 +131,6 @@ void testOpenBackpack() throws InterruptedException { Assertions.assertEquals(backpack.getInventory(), view.getTopInventory()); } - @Test - @DisplayName("Test backpacks being marked dirty on close") - void testCloseBackpack() throws InterruptedException { - Player player = server.addPlayer(); - PlayerBackpack backpack = openMockBackpack(player, "TEST_CLOSE_BACKPACK", 27); - listener.onClose(new InventoryCloseEvent(player.getOpenInventory())); - - Assertions.assertTrue(backpack.getOwner().isDirty()); - } - @Test @DisplayName("Test backpacks not disturbing normal item dropping") void testBackpackDropNormalItem() throws InterruptedException { diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/storage/backend/TestLegacyBackend.java b/src/test/java/io/github/thebusybiscuit/slimefun4/storage/backend/TestLegacyBackend.java new file mode 100644 index 0000000000..1859659999 --- /dev/null +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/storage/backend/TestLegacyBackend.java @@ -0,0 +1,383 @@ +package io.github.thebusybiscuit.slimefun4.storage.backend; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.UUID; + +import org.apache.commons.io.FileUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.NamespacedKey; +import org.bukkit.OfflinePlayer; +import org.bukkit.World; +import org.bukkit.WorldCreator; +import org.bukkit.World.Environment; +import org.bukkit.configuration.serialization.ConfigurationSerialization; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import be.seeseemelk.mockbukkit.MockBukkit; +import be.seeseemelk.mockbukkit.ServerMock; +import io.github.thebusybiscuit.slimefun4.api.gps.Waypoint; +import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; +import io.github.thebusybiscuit.slimefun4.api.researches.Research; +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; +import io.github.thebusybiscuit.slimefun4.storage.backend.legacy.LegacyStorage; +import io.github.thebusybiscuit.slimefun4.storage.data.PlayerData; +import io.github.thebusybiscuit.slimefun4.test.TestUtilities; +import net.md_5.bungee.api.ChatColor; + +class TestLegacyBackend { + + private static ServerMock server; + private static Slimefun plugin; + + @BeforeAll + public static void load() { + server = MockBukkit.mock(); + plugin = MockBukkit.load(Slimefun.class); + + File playerFolder = new File("data-storage/Slimefun/Players"); + playerFolder.mkdirs(); + File waypointFolder = new File("data-storage/Slimefun/waypoints"); + waypointFolder.mkdirs(); + + // Not too sure why this is needed, we don't use it elsewhere, it should just use the ItemStack serialization + // My guess is MockBukkit isn't loading the ConfigurationSerialization class therefore the static block + // within the class isn't being fired (where ItemStack and other classes are registered) + ConfigurationSerialization.registerClass(ItemStack.class); + ConfigurationSerialization.registerClass(ItemMeta.class); + + setupResearches(); + } + + @AfterAll + public static void unload() throws IOException { + MockBukkit.unmock(); + FileUtils.deleteDirectory(new File("data-storage")); + } + + // Test simple loading and saving of player data + @Test + void testLoadingResearches() throws IOException { + // Create a player file which we can load + UUID uuid = UUID.randomUUID(); + File playerFile = new File("data-storage/Slimefun/Players/" + uuid + ".yml"); + Files.writeString(playerFile.toPath(), """ + researches: + '0': true + '1': true + '2': true + '3': true + '4': true + '5': true + '6': true + '7': true + '8': true + '9': true + """); + + // Load the player data + LegacyStorage storage = new LegacyStorage(); + PlayerData data = storage.loadPlayerData(uuid); + + // Check if the data is correct + Assertions.assertEquals(10, data.getResearches().size()); + for (int i = 0; i < 10; i++) { + Assertions.assertTrue(data.getResearches().contains(Slimefun.getRegistry().getResearches().get(i))); + } + } + + // There's some issues with deserializing items in tests, I spent quite a while debugging this + // and didn't really get anywhere. So commenting this out for now. + /* + @Test + void testLoadingBackpacks() throws IOException { + // Create a player file which we can load + UUID uuid = UUID.randomUUID(); + File playerFile = new File("data-storage/Slimefun/Players/" + uuid + ".yml"); + Files.writeString(playerFile.toPath(), """ + backpacks: + '0': + size: 9 + contents: + '0': + ==: org.bukkit.inventory.ItemStack + v: 1 + type: IRON_BLOCK + meta: + ==: org.bukkit.inventory.meta.ItemMeta + enchants: {} + damage: 0 + persistentDataContainer: + slimefun:slimefun_item: TEST + displayName: §6Test block + itemFlags: !!set {} + unbreakable: false + repairCost: 0 + """); + + // Load the player data + LegacyStorage storage = new LegacyStorage(); + PlayerData data = storage.loadPlayerData(uuid); + + // Check if the data is correct + Assertions.assertEquals(1, data.getBackpacks().size()); + Assertions.assertEquals(9, data.getBackpacks().get(0).getSize()); + + // Validate item deserialization + System.out.println( + Arrays.stream(data.getBackpack(0).getInventory().getContents()) + .map((item) -> item == null ? "null" : item.getType().name()) + .collect(Collectors.joining(", ")) + ); + ItemStack stack = data.getBackpack(0).getInventory().getItem(0); + Assertions.assertNotNull(stack); + Assertions.assertEquals("IRON_BLOCK", stack.getType().name()); + Assertions.assertEquals(1, stack.getAmount()); + Assertions.assertEquals(ChatColor.GREEN + "Test block", stack.getItemMeta().getDisplayName()); + } + */ + + @Test + void testLoadingWaypoints() throws IOException { + // Create mock world + server.createWorld(WorldCreator.name("world").environment(Environment.NORMAL)); + + // Create a player file which we can load + UUID uuid = UUID.randomUUID(); + File waypointFile = new File("data-storage/Slimefun/waypoints/" + uuid + ".yml"); + Files.writeString(waypointFile.toPath(), """ + TEST: + x: -173.0 + y: 75.0 + z: -11.0 + pitch: 0.0 + yaw: 178.0 + world: world + name: test + """); + + // Load the player data + LegacyStorage storage = new LegacyStorage(); + PlayerData data = storage.loadPlayerData(uuid); + + // Check if the data is correct + Assertions.assertEquals(1, data.getWaypoints().size()); + + // Validate waypoint deserialization + Waypoint waypoint = data.getWaypoints().iterator().next(); + + Assertions.assertEquals("test", waypoint.getName()); + Assertions.assertEquals(-173.0, waypoint.getLocation().getX()); + Assertions.assertEquals(75.0, waypoint.getLocation().getY()); + Assertions.assertEquals(-11.0, waypoint.getLocation().getZ()); + Assertions.assertEquals(178.0, waypoint.getLocation().getYaw()); + Assertions.assertEquals(0.0, waypoint.getLocation().getPitch()); + Assertions.assertEquals("world", waypoint.getLocation().getWorld().getName()); + } + + @Test + void testSavingResearches() throws InterruptedException { + // Create a player file which we can load + UUID uuid = UUID.randomUUID(); + File playerFile = new File("data-storage/Slimefun/Players/" + uuid + ".yml"); + + OfflinePlayer player = Bukkit.getOfflinePlayer(uuid); + + PlayerProfile profile = TestUtilities.awaitProfile(player); + + for (Research research : Slimefun.getRegistry().getResearches()) { + profile.setResearched(research, true); + } + + // Save the player data + LegacyStorage storage = new LegacyStorage(); + storage.savePlayerData(uuid, profile.getPlayerData()); + + // Assert the file exists and data is correct + Assertions.assertTrue(playerFile.exists()); + PlayerData assertion = storage.loadPlayerData(uuid); + Assertions.assertEquals(10, assertion.getResearches().size()); + for (int i = 0; i < 10; i++) { + Assertions.assertTrue(assertion.getResearches().contains(Slimefun.getRegistry().getResearches().get(i))); + } + } + + // There's some issues with deserializing items in tests, I spent quite a while debugging this + // and didn't really get anywhere. So commenting this out for now. + /* + @Test + void testSavingBackpacks() throws InterruptedException { + // Create a player file which we can load + UUID uuid = UUID.randomUUID(); + File playerFile = new File("data-storage/Slimefun/Players/" + uuid + ".yml"); + + OfflinePlayer player = Bukkit.getOfflinePlayer(uuid); + + PlayerProfile profile = TestUtilities.awaitProfile(player); + + PlayerBackpack backpack = profile.createBackpack(9); + backpack.getInventory().addItem(SlimefunItems.AIR_RUNE); + + // Save the player data + LegacyStorage storage = new LegacyStorage(); + storage.savePlayerData(uuid, profile.getPlayerData()); + + // Assert the file exists and data is correct + Assertions.assertTrue(playerFile.exists()); + PlayerData assertion = storage.loadPlayerData(uuid); + Assertions.assertEquals(1, assertion.getBackpacks().size()); + } + */ + + @Test + void testSavingWaypoints() throws InterruptedException { + // Create mock world + World world = server.createWorld(WorldCreator.name("world").environment(Environment.NORMAL)); + + // Create a player file which we can load + UUID uuid = UUID.randomUUID(); + File playerFile = new File("data-storage/Slimefun/Players/" + uuid + ".yml"); + + OfflinePlayer player = Bukkit.getOfflinePlayer(uuid); + PlayerProfile profile = TestUtilities.awaitProfile(player); + + profile.addWaypoint(new Waypoint( + player.getUniqueId(), + "test", + new Location(world, 1, 2, 3, 4, 5), + ChatColor.GREEN + "Test waypoint") + ); + + // Save the player data + LegacyStorage storage = new LegacyStorage(); + storage.savePlayerData(uuid, profile.getPlayerData()); + + // Assert the file exists and data is correct + Assertions.assertTrue(playerFile.exists()); + PlayerData assertion = storage.loadPlayerData(uuid); + Assertions.assertEquals(1, assertion.getWaypoints().size()); + + // Validate waypoint deserialization + Waypoint waypoint = assertion.getWaypoints().iterator().next(); + + Assertions.assertEquals(ChatColor.GREEN + "Test waypoint", waypoint.getName()); + Assertions.assertEquals(1, waypoint.getLocation().getX()); + Assertions.assertEquals(2, waypoint.getLocation().getY()); + Assertions.assertEquals(3, waypoint.getLocation().getZ()); + Assertions.assertEquals(4, waypoint.getLocation().getYaw()); + Assertions.assertEquals(5, waypoint.getLocation().getPitch()); + Assertions.assertEquals("world", waypoint.getLocation().getWorld().getName()); + } + + // Test realistic situations + @Test + void testResearchChanges() throws InterruptedException { + UUID uuid = UUID.randomUUID(); + File playerFile = new File("data-storage/Slimefun/Players/" + uuid + ".yml"); + + OfflinePlayer player = Bukkit.getOfflinePlayer(uuid); + PlayerProfile profile = TestUtilities.awaitProfile(player); + + // Unlock all researches + for (Research research : Slimefun.getRegistry().getResearches()) { + profile.setResearched(research, true); + } + + // Save the player data + LegacyStorage storage = new LegacyStorage(); + storage.savePlayerData(uuid, profile.getPlayerData()); + + // Assert the file exists and data is correct + Assertions.assertTrue(playerFile.exists()); + PlayerData assertion = storage.loadPlayerData(uuid); + Assertions.assertEquals(10, assertion.getResearches().size()); + for (int i = 0; i < 10; i++) { + Assertions.assertTrue(assertion.getResearches().contains(Slimefun.getRegistry().getResearches().get(i))); + } + + // Now let's change the data and save it again + profile.setResearched(Slimefun.getRegistry().getResearches().get(3), false); + + // Save the player data + storage.savePlayerData(uuid, profile.getPlayerData()); + + // Assert the file exists and data is correct + Assertions.assertTrue(playerFile.exists()); + System.out.println("update assertion"); + assertion = storage.loadPlayerData(uuid); + Assertions.assertEquals(9, assertion.getResearches().size()); + for (int i = 0; i < 10; i++) { + if (i != 3) { + Assertions.assertTrue(assertion.getResearches().contains(Slimefun.getRegistry().getResearches().get(i))); + } + } + } + + // Test realistic situations - when we fix the serialization issue + // @Test + // void testBackpackChanges() throws InterruptedException {} + + @Test + void testWaypointChanges() throws InterruptedException { + // Create mock world + World world = server.createWorld(WorldCreator.name("world").environment(Environment.NORMAL)); + + // Create a player file which we can load + UUID uuid = UUID.randomUUID(); + File playerFile = new File("data-storage/Slimefun/Players/" + uuid + ".yml"); + + OfflinePlayer player = Bukkit.getOfflinePlayer(uuid); + PlayerProfile profile = TestUtilities.awaitProfile(player); + + profile.addWaypoint(new Waypoint( + player.getUniqueId(), + "test", + new Location(world, 1, 2, 3, 4, 5), + ChatColor.GREEN + "Test waypoint" + )); + + Waypoint test2 = new Waypoint( + player.getUniqueId(), + "test2", + new Location(world, 10, 20, 30, 40, 50), + ChatColor.GREEN + "Test 2 waypoint" + ); + profile.addWaypoint(test2); + + // Save the player data + LegacyStorage storage = new LegacyStorage(); + storage.savePlayerData(uuid, profile.getPlayerData()); + + // Assert the file exists and data is correct + Assertions.assertTrue(playerFile.exists()); + PlayerData assertion = storage.loadPlayerData(uuid); + Assertions.assertEquals(2, assertion.getWaypoints().size()); + + // Remove one + profile.removeWaypoint(test2); + + // Save the player data + storage.savePlayerData(uuid, profile.getPlayerData()); + + // Assert the file exists and data is correct + Assertions.assertTrue(playerFile.exists()); + assertion = storage.loadPlayerData(uuid); + Assertions.assertEquals(1, assertion.getWaypoints().size()); + } + + // Utils + private static void setupResearches() { + for (int i = 0; i < 10; i++) { + NamespacedKey key = new NamespacedKey(plugin, "test_" + i); + Research research = new Research(key, i, "Test " + i, 100); + research.register(); + } + } +} diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/test/mocks/MockProfile.java b/src/test/java/io/github/thebusybiscuit/slimefun4/test/mocks/MockProfile.java index 8afad75e12..9a7837d00a 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/test/mocks/MockProfile.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/test/mocks/MockProfile.java @@ -1,15 +1,22 @@ package io.github.thebusybiscuit.slimefun4.test.mocks; +import java.util.HashMap; +import java.util.Set; + import javax.annotation.Nonnull; import org.bukkit.OfflinePlayer; import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; +import io.github.thebusybiscuit.slimefun4.storage.data.PlayerData; public class MockProfile extends PlayerProfile { public MockProfile(@Nonnull OfflinePlayer p) { - super(p); + this(p, new PlayerData(Set.of(), new HashMap<>(), Set.of())); } + public MockProfile(@Nonnull OfflinePlayer p, @Nonnull PlayerData data) { + super(p, data); + } } From e33950383c38d6682e50095fdc16a559f8030ee7 Mon Sep 17 00:00:00 2001 From: J3fftw <44972470+J3fftw1@users.noreply.github.com> Date: Wed, 3 Jan 2024 20:12:45 +0100 Subject: [PATCH 131/131] temporarily diable senstive blocks check (#4077) Co-authored-by: Daniel Walsh --- .../slimefun4/implementation/listeners/BlockListener.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index 1db923bebc..c214c33a2c 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -303,8 +303,11 @@ private void checkForSensitiveBlockAbove(Player player, Block block, ItemStack i * @param count * The amount of times this has been recursively called */ + // Disabled for now due to #4069 - Servers crashing due to this check + // There is additionally a second bug with `getMaxChainedNeighborUpdates` not existing in 1.17 @ParametersAreNonnullByDefault private void checkForSensitiveBlocks(Block block, Integer count, boolean isDropItems) { + /* if (count >= Bukkit.getServer().getMaxChainedNeighborUpdates()) { return; } @@ -326,6 +329,7 @@ private void checkForSensitiveBlocks(Block block, Integer count, boolean isDropI // Set the BlockData back: this makes it so containers and spawners drop correctly. This is a hacky fix. block.setBlockData(state.getBlockData(), false); state.update(true, false); + */ } /**