From 8e77f1e223d271eeed96823ad457ce0b532669ad Mon Sep 17 00:00:00 2001 From: ybw0014 Date: Sat, 26 Jul 2025 20:40:00 -0400 Subject: [PATCH 01/23] =?UTF-8?q?feat(WoodcutterAndroid):=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E8=8B=8D=E7=99=BD=E6=A9=A1=E6=9C=A8=20(#1084)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../implementation/items/androids/WoodcutterAndroid.java | 7 ++++--- .../implementation/listeners/GrapplingHookListener.java | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 646b7252e2..badfd00767 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ ${project.basedir}/.mvn/settings.xml - 1.21 + 1.21.4 https://papermc.io/javadocs 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 ec37eb41e4..32f2ab1a0d 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 @@ -1,5 +1,6 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids; +import city.norain.slimefun4.SlimefunExtended; import city.norain.slimefun4.api.menu.UniversalMenu; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.blocks.Vein; @@ -145,10 +146,10 @@ private void replant(@Nonnull Block block) { } } - if (Slimefun.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_20)) { + if (SlimefunExtended.getMinecraftVersion().isAtLeast(1, 21, 2)) { switch (logType) { - case CHERRY_LOG, STRIPPED_CHERRY_LOG -> { - saplingType = Material.CHERRY_SAPLING; + case PALE_OAK_LOG, PALE_OAK_WOOD, STRIPPED_PALE_OAK_LOG, STRIPPED_PALE_OAK_WOOD -> { + saplingType = Material.PALE_OAK_SAPLING; soilRequirement = SlimefunTag.DIRT_VARIANTS::isTagged; } default -> {} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/GrapplingHookListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/GrapplingHookListener.java index d2b4dcc0b5..85c44357b3 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/GrapplingHookListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/GrapplingHookListener.java @@ -163,7 +163,7 @@ public void onLeashBreak(EntityUnleashEvent e) { return; } - for (GrapplingHookEntity hook : activeHooks.values()){ + for (GrapplingHookEntity hook : activeHooks.values()) { if (hook.getLeashTarget() == e.getEntity()) { e.setDropLeash(false); return; From 5f8841e0d42203fe4ff96f5d7d556a1f1e2d6920 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 27 Jul 2025 17:12:17 +0800 Subject: [PATCH 02/23] fix(comp): fallback check for `isConnected` for 1.20- --- .../norain/slimefun4/utils/InventoryUtil.java | 2 +- .../norain/slimefun4/utils/PlayerUtil.java | 16 ++++++++++++++++ .../controller/ProfileDataController.java | 3 ++- .../commands/subcommands/BackpackCommand.java | 4 ++-- .../guide/SurvivalSlimefunGuide.java | 18 +++++------------- .../SlimefunItemInteractListener.java | 4 ++-- 6 files changed, 28 insertions(+), 19 deletions(-) create mode 100644 src/main/java/city/norain/slimefun4/utils/PlayerUtil.java diff --git a/src/main/java/city/norain/slimefun4/utils/InventoryUtil.java b/src/main/java/city/norain/slimefun4/utils/InventoryUtil.java index 095b30717b..03bf021cee 100644 --- a/src/main/java/city/norain/slimefun4/utils/InventoryUtil.java +++ b/src/main/java/city/norain/slimefun4/utils/InventoryUtil.java @@ -19,7 +19,7 @@ public void openInventory(Player p, Inventory inventory) { return; } - if (!p.isConnected()) { + if (!PlayerUtil.isConnected(p)) { Debug.log( TestCase.INVENTORY, "Tried to open an inventory for a player that is not connected: " + p.getName()); diff --git a/src/main/java/city/norain/slimefun4/utils/PlayerUtil.java b/src/main/java/city/norain/slimefun4/utils/PlayerUtil.java new file mode 100644 index 0000000000..bebd2d2ec1 --- /dev/null +++ b/src/main/java/city/norain/slimefun4/utils/PlayerUtil.java @@ -0,0 +1,16 @@ +package city.norain.slimefun4.utils; + +import city.norain.slimefun4.SlimefunExtended; +import lombok.experimental.UtilityClass; +import org.bukkit.OfflinePlayer; + +@UtilityClass +public class PlayerUtil { + public boolean isConnected(OfflinePlayer player) { + if (SlimefunExtended.getMinecraftVersion().isAtLeast(1, 20)) { + return player.isConnected(); + } else { + return player.isOnline(); + } + } +} diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ProfileDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ProfileDataController.java index a373e9661d..42987adde2 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ProfileDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ProfileDataController.java @@ -1,5 +1,6 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.controller; +import city.norain.slimefun4.utils.PlayerUtil; import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; import com.xzavier0722.mc.plugin.slimefun4.storage.common.DataScope; import com.xzavier0722.mc.plugin.slimefun4.storage.common.DataType; @@ -355,7 +356,7 @@ public void run() { return; } - if (Bukkit.getOfflinePlayer(UUID.fromString(pUuid)).isConnected()) { + if (PlayerUtil.isConnected(Bukkit.getOfflinePlayer(UUID.fromString(pUuid)))) { return; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/BackpackCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/BackpackCommand.java index a0a119e385..25ee7949a4 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/BackpackCommand.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/BackpackCommand.java @@ -63,7 +63,7 @@ public void onExecute(@Nonnull CommandSender sender, @Nonnull String[] args) { .getPlayerUuidAsync(args[1], new IAsyncReadCallback<>() { @Override public void onResult(UUID result) { - if (!player.isConnected()) { + if (!player.isOnline()) { return; } openBackpackMenu(Bukkit.getOfflinePlayer(result), player); @@ -105,7 +105,7 @@ public boolean runOnMainThread() { @Override public void onResult(Set result) { - if (!p.isConnected()) { + if (!p.isOnline()) { return; } showBackpackMenu(owner, p, result, 1); 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 7f3d5241ab..267b520fe1 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 @@ -136,19 +136,11 @@ public void openMainMenu(PlayerProfile profile, int page) { Player p = profile.getPlayer(); if (p == null) { - if (!profile.getOwner().isConnected()) { - Debug.log( - TestCase.INVENTORY, - "A disconnected player tried to open guide, id = {}({})", - profile.getOwner().getName(), - profile.getOwner().getUniqueId()); - } else { - Debug.log( - TestCase.INVENTORY, - "A offline player tried to open guide, id = {}({})", - profile.getOwner().getName(), - profile.getOwner().getUniqueId()); - } + Debug.log( + TestCase.INVENTORY, + "A disconnected player tried to open guide, id = {}({})", + profile.getOwner().getName(), + profile.getOwner().getUniqueId()); return; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java index d159a404ce..04c0858f0a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java @@ -170,7 +170,7 @@ public boolean runOnMainThread() { @Override public void onResult(SlimefunUniversalData result) { - if (!p.isConnected()) { + if (!p.isOnline()) { return; } @@ -198,7 +198,7 @@ public boolean runOnMainThread() { @Override public void onResult(SlimefunBlockData result) { - if (!p.isConnected()) { + if (!p.isOnline()) { return; } From 1e0403287e56e28e2887d359494c3922f5341998 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 27 Jul 2025 17:23:33 +0800 Subject: [PATCH 03/23] chore(dev): introduced `javadoc-deploy` --- .github/workflows/javadoc-deploy.yml | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/javadoc-deploy.yml diff --git a/.github/workflows/javadoc-deploy.yml b/.github/workflows/javadoc-deploy.yml new file mode 100644 index 0000000000..40a357a93d --- /dev/null +++ b/.github/workflows/javadoc-deploy.yml @@ -0,0 +1,30 @@ +name: javadoc-deploy.yml +on: + push: + branches: + - release + - dev + paths: + - 'src/**' + workflow_dispatch: + +env: + JAVADOC_TARGET: snapshot + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Check javadoc target + if: github.ref_name == 'release' + run: echo "JAVADOC_TARGET=release" >> $GITHUB_ENV + - name: Deploy JavaDoc 🚀 + uses: MathieuSoysal/Javadoc-publisher.yml@v3.0.2 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + javadoc-branch: ${{ format('javadoc-{0}', env.JAVADOC_TARGET) }} + java-version: 21 + target-folder: ${{ env.JAVADOC_TARGET }} + project: maven From aa642880135099f59506e330c8d971f91cd334b6 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 27 Jul 2025 17:51:54 +0800 Subject: [PATCH 04/23] fix: javadoc --- pom.xml | 65 +++++++++++++++++++ .../norain/slimefun4/VaultIntegration.java | 2 + .../slimefun4/api/items/SlimefunItem.java | 2 + .../items/androids/AndroidType.java | 2 +- .../items/androids/MinerAndroid.java | 4 +- 5 files changed, 72 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index badfd00767..5794ee08cc 100644 --- a/pom.xml +++ b/pom.xml @@ -247,6 +247,71 @@ org.apache.maven.plugins maven-deploy-plugin + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.11.2 + + + ${project.basedir} + javadocs + + Slimefun4 - Javadocs + Slimefun4 - Javadocs + false + -html5 + + + + + Slimefun4 - API + io.github.thebusybiscuit.slimefun4.api* + + + Slimefun4 - 核心类 + io.github.thebusybiscuit.slimefun4.core* + + + Slimefun4 - 实现类 + io.github.thebusybiscuit.slimefun4.implementation* + + + Slimefun4 - 插件兼容相关类 + io.github.thebusybiscuit.slimefun4.integrations* + + + Slimefun4 - 工具类 + io.github.thebusybiscuit.slimefun4.utils* + + + Slimefun4 - 物品 + io.github.thebusybiscuit.slimefun4.implementation.items* + + + Slimefun4 - 多方块结构 + io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks* + + + Slimefun4 - 电器 + io.github.thebusybiscuit.slimefun4.implementation.items.electric* + + + Slimefun4 - 过时包 + me.mrCookieSlime.Slimefun* + + + 数据库相关实现 + com.xzavier0722.mc.plugin.slimefun4* + + + 汉化版额外实现 + city.norain.slimefun4.api* + + + + diff --git a/src/main/java/city/norain/slimefun4/VaultIntegration.java b/src/main/java/city/norain/slimefun4/VaultIntegration.java index 3ad09e334c..fe5e4e6a34 100644 --- a/src/main/java/city/norain/slimefun4/VaultIntegration.java +++ b/src/main/java/city/norain/slimefun4/VaultIntegration.java @@ -8,6 +8,8 @@ import org.bukkit.OfflinePlayer; /** + * Vault 集成类, 用于处理游戏币相关的操作. + * * @author StarWishsama */ public class VaultIntegration { 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 82e8629d70..bd096a8edb 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 @@ -1294,6 +1294,8 @@ public final int hashCode() { /** * Should load the {@link SlimefunBlockData} by default. * If return false, only the item with {@link BlockTicker} will be loaded with {@link ChunkLoadEvent}. + * + * @return true if the data should be loaded by default, false otherwise */ public boolean loadDataByDefault() { return ticking; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidType.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidType.java index b32366e2e0..b97ab10377 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidType.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidType.java @@ -27,7 +27,7 @@ public enum AndroidType { FARMER, /** - * The {@link AdvancedFarmerAndroid} is an extension of the {@link FarmerAndroid}, + * The AdvancedFarmerAndroid is an extension of the {@link FarmerAndroid}, * it can also harvest plants from ExoticGarden. */ ADVANCED_FARMER, diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java index 56091b092c..48f0541de6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java @@ -30,8 +30,8 @@ /** * The {@link MinerAndroid} is a variant of the {@link ProgrammableAndroid} which * is able to break blocks. - * The core functionalities boil down to {@link #dig(Block, BlockMenu, Block)} and - * {@link #moveAndDig(Block, BlockMenu, BlockFace, Block)}. + * The core functionalities boil down to {@link #dig(Block, UniversalMenu, Block)} and + * {@link #moveAndDig(Block, UniversalMenu, BlockFace, Block)}. * Otherwise the functionality is similar to a regular android. *

* The {@link MinerAndroid} will also fire an {@link AndroidMineEvent} when breaking a {@link Block}. From f136450747248948f582074d91d71038db5f448b Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 27 Jul 2025 18:04:32 +0800 Subject: [PATCH 05/23] chore: separate javadoc deployer to single repo --- .github/workflows/javadoc-deploy.yml | 30 ---------------------------- 1 file changed, 30 deletions(-) delete mode 100644 .github/workflows/javadoc-deploy.yml diff --git a/.github/workflows/javadoc-deploy.yml b/.github/workflows/javadoc-deploy.yml deleted file mode 100644 index 40a357a93d..0000000000 --- a/.github/workflows/javadoc-deploy.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: javadoc-deploy.yml -on: - push: - branches: - - release - - dev - paths: - - 'src/**' - workflow_dispatch: - -env: - JAVADOC_TARGET: snapshot - -jobs: - publish: - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - name: Check javadoc target - if: github.ref_name == 'release' - run: echo "JAVADOC_TARGET=release" >> $GITHUB_ENV - - name: Deploy JavaDoc 🚀 - uses: MathieuSoysal/Javadoc-publisher.yml@v3.0.2 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - javadoc-branch: ${{ format('javadoc-{0}', env.JAVADOC_TARGET) }} - java-version: 21 - target-folder: ${{ env.JAVADOC_TARGET }} - project: maven From ab2377733ec604cc0f654a5a6165a9ee100f944b Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 27 Jul 2025 18:39:41 +0800 Subject: [PATCH 06/23] fix: javadoc output dir --- pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5794ee08cc..8acbc8e4d4 100644 --- a/pom.xml +++ b/pom.xml @@ -255,8 +255,7 @@ 3.11.2 - ${project.basedir} - javadocs + ${project.basedir}/javadocs Slimefun4 - Javadocs Slimefun4 - Javadocs From a88d5276df16a6f2498426dda42881439abc814e Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Mon, 28 Jul 2025 16:46:35 +0800 Subject: [PATCH 07/23] chore(javadoc): fix scope --- pom.xml | 2 +- .../slimefun4/implementation/items/androids/MinerAndroid.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8acbc8e4d4..de13579291 100644 --- a/pom.xml +++ b/pom.xml @@ -302,7 +302,7 @@ 数据库相关实现 - com.xzavier0722.mc.plugin.slimefun4* + com.xzavier0722.mc.plugin.slimefun4.storage* 汉化版额外实现 diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java index 48f0541de6..1d17f92730 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java @@ -17,7 +17,6 @@ import java.util.UUID; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; -import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; From a94d9f77d24e4ae84320bf7f01121c26400bd54d Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Tue, 29 Jul 2025 20:35:32 +0800 Subject: [PATCH 08/23] chore(doc): update javadoc --- .../mc/plugin/slimefun4/storage/common/DataType.java | 11 +++++++++++ .../slimefun4/storage/controller/ADataController.java | 6 ++++++ .../storage/controller/ASlimefunDataContainer.java | 9 +++++++++ .../storage/controller/SlimefunBlockData.java | 10 ++++++++++ .../storage/controller/SlimefunChunkData.java | 3 +++ .../mc/plugin/slimefun4/storage/package-info.java | 4 ++++ 6 files changed, 43 insertions(+) create mode 100644 src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/package-info.java diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataType.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataType.java index 85211eb3b8..22a3463a2b 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataType.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataType.java @@ -1,6 +1,17 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.common; +/** + * {@link DataType} 是 Slimefun 数据库控制器的类型, + * 用于区分不同的数据存储类型。 + */ public enum DataType { + /** + * 玩家档案,通常包含研究进度、背包等其他玩家相关数据。 + */ PLAYER_PROFILE, + + /** + * Slimefun 方块数据 + */ BLOCK_STORAGE } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java index 467a3a4590..dd3b1a4c10 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java @@ -22,6 +22,12 @@ import java.util.logging.Logger; import javax.annotation.OverridingMethodsMustInvokeSuper; +/** + * {@link ADataController} 是 Slimefun 数据库控制器的抽象类, + * 提供了对数据源适配器的访问和数据操作的基本方法。 + *
+ * 该类提供了对数据库的增删查改操作以及异步读写的支持。 + */ public abstract class ADataController { private final DataType dataType; private final Map scheduledWriteTasks; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ASlimefunDataContainer.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ASlimefunDataContainer.java index 2faba0b9de..2bfc75638d 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ASlimefunDataContainer.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ASlimefunDataContainer.java @@ -3,6 +3,15 @@ import lombok.Getter; import lombok.Setter; +/** + * Slimefun 数据容器的抽象类. + *

+ * 该类用于存储 Slimefun 特有的数据容器, 包括 Slimefun ID 和是否待删除的标志. + * + * @author NoRainCity + * + * @see ADataController + */ public abstract class ASlimefunDataContainer extends ADataContainer { @Getter private final String sfId; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunBlockData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunBlockData.java index 29138215a1..dcd6588b9c 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunBlockData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunBlockData.java @@ -11,6 +11,16 @@ import org.bukkit.Location; import org.bukkit.inventory.ItemStack; +/** + * {@link SlimefunBlockData} 是 Slimefun 中机器等方块类物品的数据存储容器。 + *
+ * 它包含了方块对应的键值容器、位置信息和菜单, + * 是 Slimefun 中常用的方块数据存储类。 + * + * @author Xzavier0722 + * + * @see ASlimefunDataContainer + */ @ToString public class SlimefunBlockData extends ASlimefunDataContainer { private final Location location; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunChunkData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunChunkData.java index 174b150a8f..3be1aa4b2a 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunChunkData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunChunkData.java @@ -15,6 +15,9 @@ import org.bukkit.Chunk; import org.bukkit.Location; +/** + * {@link SlimefunChunkData} 是 Slimefun 中用于存储区块内所有方块数据的容器类。 + */ public class SlimefunChunkData extends ADataContainer { private static final SlimefunBlockData INVALID_BLOCK_DATA = new SlimefunBlockData( new Location(Bukkit.getWorlds().get(0), Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE), diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/package-info.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/package-info.java new file mode 100644 index 0000000000..b19d8bd06d --- /dev/null +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/package-info.java @@ -0,0 +1,4 @@ +/** + * Slimefun 的数据库存储系统实现与 API + */ +package com.xzavier0722.mc.plugin.slimefun4.storage; From cec0fb03775aca6841c4bc1bce4ab6f2e8625fe5 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Wed, 30 Jul 2025 21:16:06 +0800 Subject: [PATCH 09/23] fix(unidata): closes #1085 fix(cleardata): command doesn't receive input world name, closes #951 --- .../storage/controller/ADataController.java | 4 +- .../controller/BlockDataController.java | 79 ++++++++++--------- .../subcommands/ClearDataCommand.java | 2 + .../items/androids/ProgrammableAndroid.java | 2 - 4 files changed, 45 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java index dd3b1a4c10..11191a64e4 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java @@ -71,8 +71,8 @@ public void init(IDataSourceAdapter dataAdapter, int maxReadThread, int maxWr readExecutor = Executors.newFixedThreadPool(maxReadThread, new DatabaseThreadFactory("SF-DB-Read-Thread #")); writeExecutor = Executors.newFixedThreadPool(maxWriteThread, new DatabaseThreadFactory("SF-DB-Write-Thread #")); callbackExecutor = new ThreadPoolExecutor( - 0, - 128, + 2, + Runtime.getRuntime().availableProcessors(), 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(128), diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 06c21f91c8..3dcd18ef11 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -424,13 +424,14 @@ public void removeUniversalBlockData(UUID uuid) { if (toRemove instanceof SlimefunUniversalBlockData ubd) { ubd.setPendingRemove(true); - removeUniversalBlockDirectly(uuid); var menu = ubd.getMenu(); if (menu != null) { menu.lock(); } + removeUniversalBlockDirectly(uuid); + if (Slimefun.getRegistry().getTickerBlocks().contains(toRemove.getSfId())) { Slimefun.getTickerTask().disableTicker(ubd.getLastPresent().toLocation()); } @@ -916,10 +917,10 @@ public void loadUniversalData(SlimefunUniversalData uniData) { DataUtils.blockDataDebase64(recordSet.get(FieldKey.DATA_VALUE)), false)); - loadedUniversalData.putIfAbsent(uniData.getUUID(), uniData); - uniData.setIsDataLoaded(true); + loadedUniversalData.putIfAbsent(uniData.getUUID(), uniData); + if (uniData instanceof SlimefunUniversalBlockData ubd) { if (ubd.hasTrait(UniversalDataTrait.BLOCK)) { // 初始化 上次出现位置 @@ -936,32 +937,34 @@ public void loadUniversalData(SlimefunUniversalData uniData) { .enableTicker(ubd.getLastPresent().toLocation(), ubd.getUUID()); } } + } - if (ubd.hasTrait(UniversalDataTrait.INVENTORY)) { - // 加载菜单 - var menuPreset = UniversalMenuPreset.getPreset(ubd.getSfId()); - if (menuPreset != null) { - var menuKey = new RecordKey(DataScope.UNIVERSAL_INVENTORY); - menuKey.addCondition(FieldKey.UNIVERSAL_UUID, ubd.getKey()); - menuKey.addField(FieldKey.INVENTORY_SLOT); - menuKey.addField(FieldKey.INVENTORY_ITEM); + if (uniData.hasTrait(UniversalDataTrait.INVENTORY)) { + // 加载菜单 + var menuPreset = UniversalMenuPreset.getPreset(uniData.getSfId()); + if (menuPreset != null) { + var menuKey = new RecordKey(DataScope.UNIVERSAL_INVENTORY); + menuKey.addCondition(FieldKey.UNIVERSAL_UUID, uniData.getKey()); + menuKey.addField(FieldKey.INVENTORY_SLOT); + menuKey.addField(FieldKey.INVENTORY_ITEM); - var inv = new ItemStack[54]; + var inv = new ItemStack[54]; - getData(menuKey) - .forEach(recordSet -> inv[recordSet.getInt(FieldKey.INVENTORY_SLOT)] = - recordSet.getItemStack(FieldKey.INVENTORY_ITEM)); + getData(menuKey) + .forEach(recordSet -> inv[recordSet.getInt(FieldKey.INVENTORY_SLOT)] = + recordSet.getItemStack(FieldKey.INVENTORY_ITEM)); - var location = ubd.hasTrait(UniversalDataTrait.BLOCK) - ? ubd.getLastPresent().toLocation() - : null; + var location = uniData.hasTrait(UniversalDataTrait.BLOCK) + ? ((SlimefunUniversalBlockData) uniData) + .getLastPresent() + .toLocation() + : null; - ubd.setMenu(new UniversalMenu(menuPreset, ubd.getUUID(), location, inv)); + uniData.setMenu(new UniversalMenu(menuPreset, uniData.getUUID(), location, inv)); - var content = ubd.getMenuContents(); - if (content != null) { - invSnapshots.put(ubd.getKey(), InvStorageUtils.getInvSnapshot(content)); - } + var content = uniData.getMenuContents(); + if (content != null) { + invSnapshots.put(uniData.getKey(), InvStorageUtils.getInvSnapshot(content)); } } } @@ -1091,26 +1094,26 @@ public void removeAllDataInWorldAsync(World world, Runnable onFinishedCallback) } public void saveUniversalInventory(@Nonnull SlimefunUniversalData universalData) { - var menu = universalData.getMenu(); var universalID = universalData.getUUID(); - var newInv = universalData.getMenuContents(); + var currentInv = universalData.getMenuContents(); List> lastSave; - if (newInv == null) { + + if (currentInv == null) { lastSave = invSnapshots.remove(universalID.toString()); if (lastSave == null) { return; } } else { - lastSave = invSnapshots.put(universalID.toString(), InvStorageUtils.getInvSnapshot(newInv)); + lastSave = invSnapshots.put(universalID.toString(), InvStorageUtils.getInvSnapshot(currentInv)); } - var changed = InvStorageUtils.getChangedSlots(lastSave, newInv); + var changed = InvStorageUtils.getChangedSlots(lastSave, currentInv); if (changed.isEmpty()) { return; } - changed.forEach(slot -> scheduleDelayedUniversalInvUpdate(universalID, menu, slot)); + changed.forEach(slot -> scheduleDelayedUniversalInvUpdate(universalData, slot)); } public Set getAllLoadedChunkData(World world) { @@ -1177,27 +1180,27 @@ private void scheduleBlockInvUpdate(ScopeKey scopeKey, RecordKey reqKey, String /** * Save universal inventory by async way * - * @param uuid Universal Inventory UUID - * @param menu Universal menu + * @param ubd {@link SlimefunUniversalBlockData} * @param slot updated item slot */ - private void scheduleDelayedUniversalInvUpdate(UUID uuid, UniversalMenu menu, int slot) { - var scopeKey = new UUIDKey(DataScope.NONE, uuid); + private void scheduleDelayedUniversalInvUpdate(SlimefunUniversalData ubd, int slot) { + var scopeKey = new UUIDKey(DataScope.NONE, ubd.getKey()); var reqKey = new RecordKey(DataScope.UNIVERSAL_INVENTORY); - reqKey.addCondition(FieldKey.UNIVERSAL_UUID, uuid.toString()); + reqKey.addCondition(FieldKey.UNIVERSAL_UUID, ubd.getKey()); reqKey.addCondition(FieldKey.INVENTORY_SLOT, slot + ""); reqKey.addField(FieldKey.INVENTORY_ITEM); if (enableDelayedSaving) { scheduleDelayedUpdateTask( new LinkedKey(scopeKey, reqKey), - () -> scheduleUniversalInvUpdate(scopeKey, reqKey, uuid, menu.getContents(), slot)); + () -> scheduleUniversalInvUpdate(scopeKey, reqKey, ubd.getKey(), ubd.getMenuContents(), slot)); } else { - scheduleUniversalInvUpdate(scopeKey, reqKey, uuid, menu.getContents(), slot); + scheduleUniversalInvUpdate(scopeKey, reqKey, ubd.getKey(), ubd.getMenuContents(), slot); } } - private void scheduleUniversalInvUpdate(ScopeKey scopeKey, RecordKey reqKey, UUID uuid, ItemStack[] inv, int slot) { + private void scheduleUniversalInvUpdate( + ScopeKey scopeKey, RecordKey reqKey, String uuid, ItemStack[] inv, int slot) { var item = inv != null && slot < inv.length ? inv[slot] : null; if (item == null) { @@ -1205,7 +1208,7 @@ private void scheduleUniversalInvUpdate(ScopeKey scopeKey, RecordKey reqKey, UUI } else { try { var data = new RecordSet(); - data.put(FieldKey.UNIVERSAL_UUID, uuid.toString()); + data.put(FieldKey.UNIVERSAL_UUID, uuid); data.put(FieldKey.INVENTORY_SLOT, slot + ""); data.put(FieldKey.INVENTORY_ITEM, item); scheduleWriteTask(scopeKey, reqKey, data, true); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/ClearDataCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/ClearDataCommand.java index 6201a7e79b..2160039542 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/ClearDataCommand.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/ClearDataCommand.java @@ -38,6 +38,8 @@ public void onExecute(@Nonnull CommandSender sender, @Nonnull String[] args) { Slimefun.getLocalization().sendMessage(sender, "commands.cleardata.worldNotFound", true); return; } + + worlds.add(toAdd); } if (args[2].equals("*")) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index d1f75bc37b..053a41d0bf 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -128,8 +128,6 @@ public boolean canOpen(Block b, Player p) { public void newInstance(UniversalMenu menu, Block b) { var uniData = StorageCacheUtils.getUniversalBlock(menu.getUuid()); - Objects.requireNonNull(uniData, "Unable to get android's universal data for " + menu.getUuid() + "!"); - menu.replaceExistingItem( 15, new CustomItemStack(HeadTexture.SCRIPT_START.getAsItemStack(), "&a启动/继续运行")); menu.addMenuClickHandler(15, (p, slot, item, action) -> { From d40774bbf0e035629816c0e162b2b06e71ef6c19 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Thu, 31 Jul 2025 07:23:18 +0800 Subject: [PATCH 10/23] chore(ci): set timezone to utf-8 --- .github/workflows/build-ci.yml | 3 +++ .github/workflows/dev-ci.yml | 3 +++ .github/workflows/pr-checker.yml | 3 +++ 3 files changed, 9 insertions(+) diff --git a/.github/workflows/build-ci.yml b/.github/workflows/build-ci.yml index f7c11faa74..a04667d4ea 100644 --- a/.github/workflows/build-ci.yml +++ b/.github/workflows/build-ci.yml @@ -12,6 +12,9 @@ on: - 'pom.xml' workflow_dispatch: +env: + TZ: 'Asia/Shanghai' + jobs: build: runs-on: ubuntu-latest diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 82bc9a819a..eb0f3e6942 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -12,6 +12,9 @@ on: - 'pom.xml' workflow_dispatch: +env: + TZ: 'Asia/Shanghai' + jobs: build: runs-on: ubuntu-latest diff --git a/.github/workflows/pr-checker.yml b/.github/workflows/pr-checker.yml index ccdfca088a..a840b03562 100644 --- a/.github/workflows/pr-checker.yml +++ b/.github/workflows/pr-checker.yml @@ -11,6 +11,9 @@ on: - 'src/**' - 'pom.xml' +env: + TZ: 'Asia/Shanghai' + permissions: contents: read packages: read From c1e08fd571a90ac18c63a330ba022528d605f1cc Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Thu, 31 Jul 2025 12:12:05 +0800 Subject: [PATCH 11/23] fix(unidata): init location info after uni record saved (#1086) refactor(unipreset): make `lastPresent` @Nullable to support machines doesn't need location (#1087) fix(controller): use `ControllerPoolExecutor` to prevent error shading --- .../slimefun4/api/menu/UniversalMenu.java | 10 ++- .../api/menu/UniversalMenuPreset.java | 18 ++++- .../utils/ControllerPoolExecutor.java | 68 +++++++++++++++++++ .../storage/controller/ADataController.java | 33 ++++++--- .../controller/BlockDataController.java | 43 ++++++------ .../storage/controller/LinkedKey.java | 18 ++--- .../controller/SlimefunUniversalData.java | 3 + .../storage/task/DatabaseThreadFactory.java | 2 +- .../storage/task/DelayedSavingLooperTask.java | 12 ++-- .../slimefun4/storage/task/DelayedTask.java | 21 ++++-- .../items/androids/ProgrammableAndroid.java | 26 +++---- .../SlimefunItemInteractListener.java | 4 ++ 12 files changed, 187 insertions(+), 71 deletions(-) create mode 100644 src/main/java/city/norain/slimefun4/utils/ControllerPoolExecutor.java diff --git a/src/main/java/city/norain/slimefun4/api/menu/UniversalMenu.java b/src/main/java/city/norain/slimefun4/api/menu/UniversalMenu.java index c5f7491342..e14e387964 100644 --- a/src/main/java/city/norain/slimefun4/api/menu/UniversalMenu.java +++ b/src/main/java/city/norain/slimefun4/api/menu/UniversalMenu.java @@ -2,6 +2,7 @@ import java.util.UUID; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import lombok.Getter; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu; @@ -20,7 +21,7 @@ public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid) { this(preset, uuid, (Location) null); } - public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, Location lastPresent) { + public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, @Nullable Location lastPresent) { super(preset); this.uuid = uuid; @@ -29,7 +30,10 @@ public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, Lo } public UniversalMenu( - @Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, Location lastPresent, ItemStack[] contents) { + @Nonnull UniversalMenuPreset preset, + @Nonnull UUID uuid, + @Nullable Location lastPresent, + ItemStack[] contents) { super(preset); this.uuid = uuid; @@ -49,7 +53,7 @@ public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, It this(preset, uuid, null, contents); } - public void update(@Nonnull Location lastPresent) { + public void update(@Nullable Location lastPresent) { ((UniversalMenuPreset) preset).clone(this, lastPresent); } diff --git a/src/main/java/city/norain/slimefun4/api/menu/UniversalMenuPreset.java b/src/main/java/city/norain/slimefun4/api/menu/UniversalMenuPreset.java index 5917c4fc5f..482db8b57e 100644 --- a/src/main/java/city/norain/slimefun4/api/menu/UniversalMenuPreset.java +++ b/src/main/java/city/norain/slimefun4/api/menu/UniversalMenuPreset.java @@ -20,7 +20,13 @@ public UniversalMenuPreset(@Nonnull String id, @Nonnull String title) { super(id, title); } - public void newInstance(@Nonnull UniversalMenu menu, @Nonnull Block b) { + /** + * 创建一个新的菜单实例 + * + * @param menu {@link UniversalMenu} 通用菜单 + * @param b 当前实例对应的方块,方块可能为空 + */ + public void newInstance(@Nonnull UniversalMenu menu, @Nullable Block b) { // This method can optionally be overridden by implementations } @@ -37,7 +43,7 @@ protected void clone(@Nonnull DirtyChestMenu menu) { } } - protected void clone(@Nonnull UniversalMenu menu, @Nonnull Location lastPresent) { + protected void clone(@Nonnull UniversalMenu menu, @Nullable Location lastPresent) { menu.setPlayerInventoryClickable(true); for (int slot : occupiedSlots) { @@ -48,7 +54,13 @@ protected void clone(@Nonnull UniversalMenu menu, @Nonnull Location lastPresent) menu.addItem(getSize() - 1, null); } - newInstance(menu, lastPresent.getBlock()); + Block b = null; + + if (lastPresent != null) { + b = lastPresent.getBlock(); + } + + newInstance(menu, b); for (int slot = 0; slot < 54; slot++) { if (getMenuClickHandler(slot) != null) { diff --git a/src/main/java/city/norain/slimefun4/utils/ControllerPoolExecutor.java b/src/main/java/city/norain/slimefun4/utils/ControllerPoolExecutor.java new file mode 100644 index 0000000000..e66d47352b --- /dev/null +++ b/src/main/java/city/norain/slimefun4/utils/ControllerPoolExecutor.java @@ -0,0 +1,68 @@ +package city.norain.slimefun4.utils; + +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.FutureTask; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import javax.annotation.Nonnull; + +public class ControllerPoolExecutor extends ThreadPoolExecutor { + public ControllerPoolExecutor(int corePoolSize, int maximumPoolSize, @Nonnull BlockingQueue workQueue) { + super(corePoolSize, maximumPoolSize, 5, TimeUnit.SECONDS, workQueue); + } + + public ControllerPoolExecutor( + int corePoolSize, + int maximumPoolSize, + @Nonnull BlockingQueue workQueue, + @Nonnull ThreadFactory threadFactory) { + this(corePoolSize, maximumPoolSize, 5, TimeUnit.SECONDS, workQueue, threadFactory); + } + + public ControllerPoolExecutor( + int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + @Nonnull TimeUnit unit, + @Nonnull BlockingQueue workQueue) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); + } + + public ControllerPoolExecutor( + int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + @Nonnull TimeUnit unit, + @Nonnull BlockingQueue workQueue, + @Nonnull ThreadFactory threadFactory) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); + } + + @Override + protected void afterExecute(Runnable r, Throwable t) { + super.afterExecute(r, t); + + if (t != null) { + Slimefun.logger() + .log( + Level.WARNING, + "An error occurred in " + Thread.currentThread().getName(), + t); + } + + if (r instanceof FutureTask future) { + try { + future.get(); + } catch (Exception e) { + Slimefun.logger() + .log( + Level.WARNING, + "An error occurred in " + Thread.currentThread().getName(), + t); + } + } + } +} diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java index 11191a64e4..705a3cdc5b 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java @@ -1,5 +1,6 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.controller; +import city.norain.slimefun4.utils.ControllerPoolExecutor; import city.norain.slimefun4.utils.TaskTimer; import com.xzavier0722.mc.plugin.slimefun4.storage.adapter.IDataSourceAdapter; import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; @@ -15,7 +16,6 @@ import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @@ -68,14 +68,27 @@ public void init(IDataSourceAdapter dataAdapter, int maxReadThread, int maxWr this.dataAdapter = dataAdapter; dataAdapter.initStorage(dataType); dataAdapter.patch(); - readExecutor = Executors.newFixedThreadPool(maxReadThread, new DatabaseThreadFactory("SF-DB-Read-Thread #")); - writeExecutor = Executors.newFixedThreadPool(maxWriteThread, new DatabaseThreadFactory("SF-DB-Write-Thread #")); + readExecutor = new ControllerPoolExecutor( + maxReadThread, + maxReadThread, + 10, + TimeUnit.SECONDS, + new ArrayBlockingQueue<>(32), + new DatabaseThreadFactory("SF-DB-Read-Thread #")); + + writeExecutor = new ControllerPoolExecutor( + maxWriteThread, + maxWriteThread, + 10, + TimeUnit.SECONDS, + new ArrayBlockingQueue<>(32), + new DatabaseThreadFactory("SF-DB-Write-Thread #")); callbackExecutor = new ThreadPoolExecutor( - 2, - Runtime.getRuntime().availableProcessors(), + 1, + Runtime.getRuntime().availableProcessors() / 2, 10, TimeUnit.SECONDS, - new ArrayBlockingQueue<>(128), + new ArrayBlockingQueue<>(64), new DatabaseThreadFactory("SF-DB-CB-Thread #")); } @@ -173,7 +186,7 @@ protected void onError(Throwable e) { }; queuedTask.queue(key, task); scheduledWriteTasks.put(scopeToUse, queuedTask); - writeExecutor.submit(queuedTask); + writeExecutor.execute(queuedTask); } finally { lock.unlock(scopeKey); } @@ -200,18 +213,18 @@ protected void invokeCallback(IAsyncReadCallback callback, T result) { if (callback.runOnMainThread()) { Slimefun.runSync(cb); } else { - callbackExecutor.submit(cb); + callbackExecutor.execute(cb); } } protected void scheduleReadTask(Runnable run) { checkDestroy(); - readExecutor.submit(run); + readExecutor.execute(run); } protected void scheduleWriteTask(Runnable run) { checkDestroy(); - writeExecutor.submit(run); + writeExecutor.execute(run); } protected List getData(RecordKey key) { diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 3dcd18ef11..93adf1a2ef 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -100,7 +100,7 @@ public class BlockDataController extends ADataController { BlockDataController() { super(DataType.BLOCK_STORAGE); - delayedWriteTasks = new HashMap<>(); + delayedWriteTasks = new ConcurrentHashMap<>(); loadedChunk = new ConcurrentHashMap<>(); loadedUniversalData = new ConcurrentHashMap<>(); invSnapshots = new ConcurrentHashMap<>(); @@ -195,17 +195,7 @@ public void initDelayedSaving(Plugin p, int delayedSecond, int forceSavePeriod) .runTaskTimerAsynchronously( p, new DelayedSavingLooperTask( - forceSavePeriod, - () -> { - synchronized (delayedWriteTasks) { - return new HashMap<>(delayedWriteTasks); - } - }, - key -> { - synchronized (delayedWriteTasks) { - delayedWriteTasks.remove(key); - } - }), + forceSavePeriod, () -> new HashMap<>(delayedWriteTasks), delayedWriteTasks::remove), 20, 20); } @@ -282,7 +272,6 @@ public SlimefunUniversalBlockData createUniversalBlock(Location l, String sfId) uniData.setIsDataLoaded(true); uniData.initTraits(); - uniData.initLastPresent(); loadedUniversalData.put(uuid, uniData); @@ -301,6 +290,8 @@ public SlimefunUniversalBlockData createUniversalBlock(Location l, String sfId) Slimefun.getBlockDataService().updateUniversalDataUUID(l.getBlock(), uniData.getKey()); } + uniData.initLastPresent(); + return uniData; } @@ -777,7 +768,10 @@ public void loadUniversalRecord() { for (String traitStr : traitsData.split(",")) { try { traits.add(UniversalDataTrait.valueOf(traitStr.toUpperCase())); - } catch (IllegalArgumentException ignored) { + } catch (IllegalArgumentException e) { + logger.log(Level.WARNING, "Invalid trait '{0}' for universal data {1}.", new Object[] { + traitStr, uuid + }); } } } @@ -932,7 +926,7 @@ public void loadUniversalData(SlimefunUniversalData uniData) { var sfItem = SlimefunItem.getById(ubd.getSfId()); - if (sfItem != null && sfItem.isTicking()) { + if (sfItem != null && sfItem.isTicking() && ubd.getLastPresent() != null) { Slimefun.getTickerTask() .enableTicker(ubd.getLastPresent().toLocation(), ubd.getUUID()); } @@ -954,20 +948,25 @@ public void loadUniversalData(SlimefunUniversalData uniData) { .forEach(recordSet -> inv[recordSet.getInt(FieldKey.INVENTORY_SLOT)] = recordSet.getItemStack(FieldKey.INVENTORY_ITEM)); - var location = uniData.hasTrait(UniversalDataTrait.BLOCK) - ? ((SlimefunUniversalBlockData) uniData) - .getLastPresent() - .toLocation() - : null; + Location location = null; + + if (uniData instanceof SlimefunUniversalBlockData ubd && ubd.hasTrait(UniversalDataTrait.BLOCK)) { + if (ubd.getLastPresent() != null) { + location = ubd.getLastPresent().toLocation(); + } + } uniData.setMenu(new UniversalMenu(menuPreset, uniData.getUUID(), location, inv)); var content = uniData.getMenuContents(); + if (content != null) { invSnapshots.put(uniData.getKey(), InvStorageUtils.getInvSnapshot(content)); } } } + } catch (Exception e) { + logger.log(Level.SEVERE, "Failed to load universal data: " + uniData.getKey(), e); } finally { lock.unlock(key); } @@ -1180,7 +1179,7 @@ private void scheduleBlockInvUpdate(ScopeKey scopeKey, RecordKey reqKey, String /** * Save universal inventory by async way * - * @param ubd {@link SlimefunUniversalBlockData} + * @param ubd {@link SlimefunUniversalBlockData} * @param slot updated item slot */ private void scheduleDelayedUniversalInvUpdate(SlimefunUniversalData ubd, int slot) { @@ -1248,6 +1247,7 @@ void scheduleDelayedUniversalDataUpdate(SlimefunUniversalData universalData, Str var reqKey = new RecordKey(DataScope.UNIVERSAL_DATA); reqKey.addCondition(FieldKey.UNIVERSAL_UUID, universalData.getKey()); reqKey.addCondition(FieldKey.DATA_KEY, key); + if (enableDelayedSaving) { scheduleDelayedUpdateTask( new LinkedKey(scopeKey, reqKey), @@ -1310,6 +1310,7 @@ void scheduleDelayedChunkDataUpdate(SlimefunChunkData chunkData, String key) { private void scheduleDelayedUpdateTask(LinkedKey key, Runnable run) { synchronized (delayedWriteTasks) { var task = delayedWriteTasks.get(key); + if (task != null && !task.isExecuted()) { task.setRunAfter(delayedSecond, TimeUnit.SECONDS); return; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/LinkedKey.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/LinkedKey.java index a6ebd2a893..850efe4114 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/LinkedKey.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/LinkedKey.java @@ -1,10 +1,15 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.controller; import com.xzavier0722.mc.plugin.slimefun4.storage.common.ScopeKey; +import lombok.Getter; +import lombok.Setter; public class LinkedKey extends ScopeKey { private final ScopeKey self; private final int hash; + + @Getter + @Setter private ScopeKey parent; public LinkedKey(ScopeKey self) { @@ -18,14 +23,6 @@ public LinkedKey(ScopeKey parent, ScopeKey self) { this.parent = parent; } - public void setParent(ScopeKey parent) { - this.parent = parent; - } - - public ScopeKey getParent() { - return parent; - } - @Override public int hashCode() { return hash; @@ -35,4 +32,9 @@ public int hashCode() { public boolean equals(Object obj) { return self.equals(obj instanceof LinkedKey linked ? linked.self : obj); } + + @Override + public String toString() { + return getKeyStr() + " -> " + self.toString(); + } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java index 677f032dd6..5adf3da642 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java @@ -12,8 +12,10 @@ import javax.annotation.ParametersAreNonnullByDefault; import lombok.Getter; import lombok.Setter; +import lombok.extern.slf4j.Slf4j; import org.bukkit.inventory.ItemStack; +@Slf4j @Getter public class SlimefunUniversalData extends ASlimefunDataContainer { @Setter @@ -48,6 +50,7 @@ protected void setTraitData(UniversalDataTrait trait, String val) { if (!trait.getReservedKey().isEmpty()) { setCacheInternal(trait.getReservedKey(), val, true); + Slimefun.getDatabaseManager() .getBlockDataController() .scheduleDelayedUniversalDataUpdate(this, trait.getReservedKey()); diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/DatabaseThreadFactory.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/DatabaseThreadFactory.java index 9c9ec07931..f9b3f67e70 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/DatabaseThreadFactory.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/DatabaseThreadFactory.java @@ -20,7 +20,7 @@ public DatabaseThreadFactory(String prefix) { public Thread newThread(@Nonnull Runnable r) { Thread t = new Thread(r, prefix + threadCount.getAndIncrement()); t.setUncaughtExceptionHandler((et, e) -> - Slimefun.logger().log(Level.SEVERE, "A error occurred in database thread " + t.getName(), e)); + Slimefun.logger().log(Level.SEVERE, "A error occurred in database thread " + et.getName(), e)); return t; } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/DelayedSavingLooperTask.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/DelayedSavingLooperTask.java index 822aecc9b8..9deeacd1bf 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/DelayedSavingLooperTask.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/DelayedSavingLooperTask.java @@ -1,21 +1,25 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.task; -import com.xzavier0722.mc.plugin.slimefun4.storage.common.ScopeKey; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.LinkedKey; import java.util.Map; import java.util.function.Consumer; import java.util.function.Supplier; +import lombok.extern.slf4j.Slf4j; +@Slf4j public class DelayedSavingLooperTask implements Runnable { private final long forceSavePeriodInMillis; - private final Supplier> taskGetter; - private final Consumer executeCallback; + private final Supplier> taskGetter; + private final Consumer executeCallback; private long nextForceRun; /** * @param forceSavePeriod: force save period in second */ public DelayedSavingLooperTask( - int forceSavePeriod, Supplier> taskGetter, Consumer executeCallback) { + int forceSavePeriod, + Supplier> taskGetter, + Consumer executeCallback) { this.forceSavePeriodInMillis = forceSavePeriod * 1000L; this.executeCallback = executeCallback; this.taskGetter = taskGetter; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/DelayedTask.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/DelayedTask.java index cdf495ec92..a52d435d9e 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/DelayedTask.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/DelayedTask.java @@ -1,7 +1,9 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.task; import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +@Slf4j public class DelayedTask { private final Runnable task; private long runAfter = 0; @@ -21,9 +23,14 @@ public synchronized boolean tryRun() { return false; } - executed = true; - task.run(); - return true; + try { + executed = true; + task.run(); + return true; + } catch (Exception e) { + log.warn("An error occurred while running delayed task", e); + return false; + } } public synchronized boolean isExecuted() { @@ -31,7 +38,11 @@ public synchronized boolean isExecuted() { } public void runUnsafely() { - executed = true; - task.run(); + try { + executed = true; + task.run(); + } catch (Exception e) { + log.warn("An error occurred while running delayed task", e); + } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index 053a41d0bf..6a991ec017 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -204,7 +204,6 @@ public void onPlayerPlace(BlockPlaceEvent e) { } })); - Slimefun.getBlockDataService().updateUniversalDataUUID(b, universalData.getKey()); PlayerHead.setSkin(b, PlayerSkin.fromBase64(texture), true); } }; @@ -220,22 +219,17 @@ public void onPlayerBreak(BlockBreakEvent e, ItemStack item, List dro var uniData = StorageCacheUtils.getUniversalBlock(b); - if (uniData != null) { - if (!e.getPlayer().hasPermission("slimefun.android.bypass") - && !e.getPlayer().getUniqueId().toString().equals(uniData.getData("owner"))) { - // The Player is not allowed to break this android - e.setCancelled(true); - return; - } + if (!e.getPlayer().hasPermission("slimefun.android.bypass") + && !e.getPlayer().getUniqueId().toString().equals(uniData.getData("owner"))) { + // The Player is not allowed to break this android + e.setCancelled(true); + return; + } - var menu = uniData.getMenu(); - if (menu != null) { - menu.dropItems(b.getLocation(), 43); - menu.dropItems(b.getLocation(), getOutputSlots()); - } - } else { - throw new IllegalStateException( - "Missing universal id android @" + LocationUtils.locationToString(b.getLocation())); + var menu = uniData.getMenu(); + if (menu != null) { + menu.dropItems(b.getLocation(), 43); + menu.dropItems(b.getLocation(), getOutputSlots()); } } }; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java index 04c0858f0a..cda5b6dde5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java @@ -155,6 +155,10 @@ private void openInventory(Player p, SlimefunItem item, Block clickedBlock, Play // We added a manual patch by identify its pdc info to fix it. if (uniData.getData(UniversalDataTrait.BLOCK.getReservedKey()) == null) { uniData.setLastPresent(clickedBlock.getLocation()); + + if (item.isTicking()) { + Slimefun.getTickerTask().enableTicker(clickedBlock.getLocation(), uniData.getUUID()); + } } if (uniData.isDataLoaded()) { From 2894b003d8db33c33db54368c1d9aeac1578cb27 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Thu, 31 Jul 2025 12:32:20 +0800 Subject: [PATCH 12/23] feat(api): introduce `createUniversalData(UUID)` --- .../norain/slimefun4/utils/StringUtil.java | 29 +++++++ .../controller/BlockDataController.java | 83 ++++++++++++++----- .../controller/SlimefunUniversalData.java | 6 ++ 3 files changed, 99 insertions(+), 19 deletions(-) diff --git a/src/main/java/city/norain/slimefun4/utils/StringUtil.java b/src/main/java/city/norain/slimefun4/utils/StringUtil.java index 98d54109c8..04c279c5c4 100644 --- a/src/main/java/city/norain/slimefun4/utils/StringUtil.java +++ b/src/main/java/city/norain/slimefun4/utils/StringUtil.java @@ -1,6 +1,9 @@ package city.norain.slimefun4.utils; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.attributes.UniversalDataTrait; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; +import java.util.HashSet; +import java.util.Set; import org.bukkit.inventory.ItemStack; public class StringUtil { @@ -19,4 +22,30 @@ public static String itemStackToString(ItemStack item) { return String.format("ItemStack (type=%s, amount=%d)", item.getType(), item.getAmount()); } } + + public static Set getTraitsFromStr(String str) { + if (str == null || str.isEmpty()) { + return new HashSet<>(); + } + + var traits = new HashSet(); + + for (String t : str.split(",")) { + try { + var trait = UniversalDataTrait.valueOf(t.toUpperCase()); + traits.add(trait); + } catch (IllegalArgumentException ignored) { + } + } + + return traits; + } + + public static String getTraitsStr(Set traits) { + if (traits == null || traits.isEmpty()) { + return ""; + } + + return String.join(",", traits.stream().map(Enum::name).toList()); + } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 93adf1a2ef..a61d4e7ed2 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -3,6 +3,7 @@ import city.norain.slimefun4.api.menu.UniversalMenu; import city.norain.slimefun4.api.menu.UniversalMenuPreset; import city.norain.slimefun4.utils.InventoryUtil; +import city.norain.slimefun4.utils.StringUtil; import city.norain.slimefun4.utils.TaskUtil; import com.xzavier0722.mc.plugin.slimefun4.storage.adapter.IDataSourceAdapter; import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; @@ -23,7 +24,6 @@ import io.github.bakedlibs.dough.collections.Pair; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; -import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -233,6 +233,7 @@ public SlimefunBlockData createBlock(Location l, String sfId) { /** * 创建一个新的 Slimefun 通用数据 + *
* 提供一个可供读写的 KV 存储 Map * * @param sfId Slimefun 物品 ID {@link SlimefunItem#getId()} @@ -254,6 +255,29 @@ public SlimefunUniversalData createUniversalData(String sfId) { return uniData; } + /** + * 创建一个新的 Slimefun 通用数据 + * 提供一个可供读写的 KV 存储 Map + * + * @param uuid 通用数据的识别 UUID + * @param sfId Slimefun 物品 ID {@link SlimefunItem#getId()} + * @return 通用数据, {@link SlimefunUniversalData} + */ + @Nonnull + public SlimefunUniversalData createUniversalData(UUID uuid, String sfId) { + checkDestroy(); + + var uniData = new SlimefunUniversalData(uuid, sfId); + + uniData.setIsDataLoaded(true); + + loadedUniversalData.put(uuid, uniData); + + Slimefun.getDatabaseManager().getBlockDataController().saveUniversalData(uniData); + + return uniData; + } + /** * 在指定位置创建一个新的 Slimefun 通用方块数据 * @@ -319,8 +343,7 @@ void saveNewBlock(Location l, String sfId) { void saveUniversalData(SlimefunUniversalData universalData) { var uuid = universalData.getKey(); var sfId = universalData.getSfId(); - var traitsStr = String.join( - ",", universalData.getTraits().stream().map(Enum::name).toList()); + var traitsStr = StringUtil.getTraitsStr(universalData.getTraits()); var key = new RecordKey(DataScope.UNIVERSAL_RECORD); @@ -512,16 +535,15 @@ public SlimefunBlockData getBlockDataFromCache(Location l) { } /** - * Get slimefun universal data - * - * @param uuid universal data uuid {@link UUID} + * 从数据库中获取 {@link SlimefunUniversalData} */ - @Nullable public SlimefunUniversalBlockData getUniversalBlockData(@Nonnull UUID uuid) { + @Nullable public SlimefunUniversalData getUniversalData(@Nonnull UUID uuid) { checkDestroy(); var key = new RecordKey(DataScope.UNIVERSAL_RECORD); key.addCondition(FieldKey.UNIVERSAL_UUID, uuid.toString()); key.addField(FieldKey.SLIMEFUN_ID); + key.addField(FieldKey.UNIVERSAL_TRAITS); var result = getData(key); @@ -529,17 +551,30 @@ public SlimefunBlockData getBlockDataFromCache(Location l) { return null; } - var newData = new SlimefunUniversalBlockData(uuid, result.get(0).get(FieldKey.SLIMEFUN_ID)); + var traits = StringUtil.getTraitsFromStr(result.get(0).get(FieldKey.UNIVERSAL_TRAITS)); - Arrays.stream(result.get(0).get(FieldKey.UNIVERSAL_TRAITS).split(",")).forEach(tname -> { - for (UniversalDataTrait trait : UniversalDataTrait.values()) { - if (trait.name().equals(tname)) { - newData.getTraits().add(trait); - } - } - }); + if (traits.contains(UniversalDataTrait.BLOCK)) { + var ubd = new SlimefunUniversalBlockData(uuid, result.get(0).get(FieldKey.SLIMEFUN_ID)); + traits.forEach(ubd::addTrait); + return ubd; + } else { + return new SlimefunUniversalData(uuid, result.get(0).get(FieldKey.SLIMEFUN_ID), traits); + } + } + + /** + * Get slimefun universal data + * + * @param uuid universal data uuid {@link UUID} + */ + @Nullable public SlimefunUniversalBlockData getUniversalBlockData(@Nonnull UUID uuid) { + SlimefunUniversalData universalData = getUniversalData(uuid); - return newData; + if (universalData instanceof SlimefunUniversalBlockData ubd) { + return ubd; + } else { + return null; + } } /** @@ -552,15 +587,25 @@ public void getUniversalBlockData(@Nonnull UUID uuid, IAsyncReadCallback invokeCallback(callback, getUniversalBlockData(uuid))); } + /** + * 从缓存中获取 {@link SlimefunUniversalData} + * + * @param uuid 通用数据 UUID + * @return {@link SlimefunUniversalData} + */ + @Nullable public SlimefunUniversalData getUniversalDataFromCache(@Nonnull UUID uuid) { + checkDestroy(); + + return loadedUniversalData.get(uuid); + } + /** * Get slimefun universal data from cache * * @param uuid universal data uuid {@link UUID} */ @Nullable public SlimefunUniversalBlockData getUniversalBlockDataFromCache(@Nonnull UUID uuid) { - checkDestroy(); - - var cache = loadedUniversalData.get(uuid); + var cache = getUniversalDataFromCache(uuid); if (cache instanceof SlimefunUniversalBlockData ubd) { return ubd; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java index 5adf3da642..110a45fa7c 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java @@ -31,6 +31,12 @@ public class SlimefunUniversalData extends ASlimefunDataContainer { super(uuid.toString(), sfId); } + @ParametersAreNonnullByDefault + SlimefunUniversalData(UUID uuid, String sfId, Set traits) { + super(uuid.toString(), sfId); + this.traits.addAll(traits); + } + @ParametersAreNonnullByDefault public void setData(String key, String val) { checkData(); From 372d6a376fd64aff6afcf2d60d0d4e5ffa8bfd50 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Thu, 31 Jul 2025 12:43:17 +0800 Subject: [PATCH 13/23] chore: cleanup code --- .../storage/controller/BlockDataController.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index a61d4e7ed2..8a2a5680ae 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -241,18 +241,7 @@ public SlimefunBlockData createBlock(Location l, String sfId) { */ @Nonnull public SlimefunUniversalData createUniversalData(String sfId) { - checkDestroy(); - - var uuid = UUID.randomUUID(); - var uniData = new SlimefunUniversalData(uuid, sfId); - - uniData.setIsDataLoaded(true); - - loadedUniversalData.put(uuid, uniData); - - Slimefun.getDatabaseManager().getBlockDataController().saveUniversalData(uniData); - - return uniData; + return createUniversalData(UUID.randomUUID(), sfId); } /** From c4639e959a67a6a9157b8c5974635ffa75fea432 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Thu, 31 Jul 2025 15:14:43 +0800 Subject: [PATCH 14/23] fix(unidata): check uuid before create data --- .../slimefun4/storage/controller/BlockDataController.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 8a2a5680ae..d4aa7c44fd 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -256,6 +256,10 @@ public SlimefunUniversalData createUniversalData(String sfId) { public SlimefunUniversalData createUniversalData(UUID uuid, String sfId) { checkDestroy(); + if (getUniversalDataFromCache(uuid) != null || getUniversalData(uuid) != null) { + throw new IllegalArgumentException("A universal data with this UUID already exists: " + uuid); + } + var uniData = new SlimefunUniversalData(uuid, sfId); uniData.setIsDataLoaded(true); From 8cf6860db8b0288863f614610b6371a8d7335130 Mon Sep 17 00:00:00 2001 From: ybw0014 Date: Thu, 31 Jul 2025 09:49:28 -0400 Subject: [PATCH 15/23] =?UTF-8?q?fix:=20Sound=20=E5=85=BC=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/services/sounds/SoundEffect.java | 3 +- .../utils/compatibility/VersionedSound.java | 71 +++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/utils/compatibility/VersionedSound.java diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/sounds/SoundEffect.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/sounds/SoundEffect.java index 2727df3ec8..3045b94f69 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/sounds/SoundEffect.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/sounds/SoundEffect.java @@ -2,6 +2,7 @@ import com.google.common.base.Preconditions; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; +import io.github.thebusybiscuit.slimefun4.utils.compatibility.VersionedSound; import java.util.logging.Level; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -123,7 +124,7 @@ public enum SoundEffect { Preconditions.checkArgument(volume >= 0, "The volume cannot be a negative number."); Preconditions.checkArgument(pitch >= 0.5, "A pitch below 0.5 has no effect on the sound."); - this.defaultSound = sound.getKey().getKey(); + this.defaultSound = VersionedSound.getSoundName(sound); this.defaultVolume = volume; this.defaultPitch = pitch; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/compatibility/VersionedSound.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/compatibility/VersionedSound.java new file mode 100644 index 0000000000..4ec370c7cd --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/compatibility/VersionedSound.java @@ -0,0 +1,71 @@ +package io.github.thebusybiscuit.slimefun4.utils.compatibility; + +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; +import java.lang.reflect.Method; +import javax.annotation.Nonnull; +import org.bukkit.NamespacedKey; +import org.bukkit.Sound; + +/** + * Sound 多版本兼容。 + *

+ * 1.21.3 Sound 由enum改为interface,需要使用反射获取 Sound 名称。 + * + * @author ybw0014 + */ +public final class VersionedSound { + + private VersionedSound() { + // utility class + } + + private static final boolean IS_ENUM; + private static final Method GET_KEY_METHOD; + + static { + boolean isEnum = false; + Method getKeyMethod = null; + + try { + if (Sound.class.isEnum()) { + isEnum = true; + } else { + getKeyMethod = Sound.class.getMethod("getKey"); + } + } catch (Exception e) { + Slimefun.logger().severe("无法确定 Sound 类型:" + e.getMessage()); + } + + IS_ENUM = isEnum; + GET_KEY_METHOD = getKeyMethod; + } + + public static boolean isEnum() { + return IS_ENUM; + } + + /** + * 获取 Sound 的名称 + * @param sound Sound 对象 + * @return Sound 名称 + */ + @Nonnull + public static String getSoundName(@Nonnull Sound sound) { + try { + if (isEnum()) { + return ((Enum) sound).name(); + } else if (GET_KEY_METHOD != null) { + Object key = GET_KEY_METHOD.invoke(sound); + if (!(key instanceof NamespacedKey nsKey)) { + throw new IllegalStateException("Sound.getKey() 返回的不是 NamespacedKey"); + } + return nsKey.getKey(); + } + } catch (Exception e) { + Slimefun.logger().severe("获取 Sound 名称失败: " + e.getMessage()); + } + + // fallback + return sound.toString(); + } +} From 9622c4188e1ebce7a5514e22a7c4639e16fe4835 Mon Sep 17 00:00:00 2001 From: ybw0014 Date: Thu, 31 Jul 2025 10:23:23 -0400 Subject: [PATCH 16/23] =?UTF-8?q?fix:=20Biome=20=E5=85=BC=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../utils/biomes/BiomeMapParser.java | 4 +- .../utils/compatibility/VersionedBiome.java | 47 +++++++++++++++++++ .../utils/compatibility/VersionedSound.java | 4 +- 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/utils/compatibility/VersionedBiome.java diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/biomes/BiomeMapParser.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/biomes/BiomeMapParser.java index a74c96ff4e..5464d454a2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/biomes/BiomeMapParser.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/biomes/BiomeMapParser.java @@ -15,6 +15,8 @@ import java.util.Set; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; + +import io.github.thebusybiscuit.slimefun4.utils.compatibility.VersionedBiome; import org.apache.commons.lang.Validate; import org.bukkit.NamespacedKey; import org.bukkit.block.Biome; @@ -168,7 +170,7 @@ private void readEntry(@Nonnull JsonObject entry) throws BiomeMapException { String formattedValue = CommonPatterns.COLON.split(value)[1].toUpperCase(Locale.ROOT); try { - Biome biome = Biome.valueOf(formattedValue); + Biome biome = VersionedBiome.valueOf(formattedValue); biomes.add(biome); } catch (IllegalArgumentException x) { // Lenient Parsers will ignore unknown biomes diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/compatibility/VersionedBiome.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/compatibility/VersionedBiome.java new file mode 100644 index 0000000000..4a832249f4 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/compatibility/VersionedBiome.java @@ -0,0 +1,47 @@ +package io.github.thebusybiscuit.slimefun4.utils.compatibility; + +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; +import java.lang.reflect.Method; +import javax.annotation.Nonnull; +import org.bukkit.block.Biome; + +/** + * Biome 多版本兼容 + * + * @author ybw0014 + */ +public final class VersionedBiome { + + private VersionedBiome() { + // utility class + } + + private static final Method VALUE_OF_METHOD; + + static { + Method valueOfMethod = null; + + try { + valueOfMethod = Biome.class.getMethod("valueOf", String.class); + } catch (Exception e) { + Slimefun.logger().severe("初始化 Biome 多版本兼容失败:" + e.getMessage()); + } + + VALUE_OF_METHOD = valueOfMethod; + } + + @Nonnull + public static Biome valueOf(@Nonnull String biomeName) throws IllegalArgumentException { + if (biomeName == null || biomeName.isEmpty()) { + throw new IllegalArgumentException("Biome 名称不能为空"); + } + try { + if (VALUE_OF_METHOD != null) { + return (Biome) VALUE_OF_METHOD.invoke(null, biomeName.toUpperCase()); + } + } catch (Exception e) { + throw new IllegalArgumentException("无法调用 Biome.valueOf: " + biomeName, e); + } + throw new IllegalArgumentException("Biome.valueOf 方法不可用"); + } +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/compatibility/VersionedSound.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/compatibility/VersionedSound.java index 4ec370c7cd..cc8a8604d4 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/compatibility/VersionedSound.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/compatibility/VersionedSound.java @@ -7,9 +7,7 @@ import org.bukkit.Sound; /** - * Sound 多版本兼容。 - *

- * 1.21.3 Sound 由enum改为interface,需要使用反射获取 Sound 名称。 + * Sound 多版本兼容 * * @author ybw0014 */ From 41ee47d4f314c5031246e1ebdb4d0fe5f7ab1212 Mon Sep 17 00:00:00 2001 From: ybw0014 Date: Thu, 31 Jul 2025 11:14:34 -0400 Subject: [PATCH 17/23] chore: update workflow --- .github/workflows/pr-checker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-checker.yml b/.github/workflows/pr-checker.yml index a840b03562..af76e23565 100644 --- a/.github/workflows/pr-checker.yml +++ b/.github/workflows/pr-checker.yml @@ -4,7 +4,7 @@ name: Pull Request Checker on: - pull_request_target: + pull_request: types: [opened, synchronize, reopened] paths: - '.github/workflows/**' @@ -32,7 +32,7 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: ${{ vars.JAVA_CI_VERSION }} + java-version: 21 java-package: jdk architecture: x64 cache: 'maven' From d9ef6ba8e9f892ca19ffd770327efd65a72e780f Mon Sep 17 00:00:00 2001 From: ybw0014 Date: Thu, 31 Jul 2025 11:17:01 -0400 Subject: [PATCH 18/23] chore: spotless --- .../thebusybiscuit/slimefun4/utils/biomes/BiomeMapParser.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/biomes/BiomeMapParser.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/biomes/BiomeMapParser.java index 5464d454a2..91ca42e746 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/biomes/BiomeMapParser.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/biomes/BiomeMapParser.java @@ -8,6 +8,7 @@ import io.github.thebusybiscuit.slimefun4.api.exceptions.BiomeMapException; import io.github.thebusybiscuit.slimefun4.utils.JsonUtils; import io.github.thebusybiscuit.slimefun4.utils.PatternUtils; +import io.github.thebusybiscuit.slimefun4.utils.compatibility.VersionedBiome; import java.util.HashMap; import java.util.HashSet; import java.util.Locale; @@ -15,8 +16,6 @@ import java.util.Set; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; - -import io.github.thebusybiscuit.slimefun4.utils.compatibility.VersionedBiome; import org.apache.commons.lang.Validate; import org.bukkit.NamespacedKey; import org.bukkit.block.Biome; From 8867007993ce2793c65bc7b333b681fb3a9d4293 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Fri, 1 Aug 2025 19:41:18 +0800 Subject: [PATCH 19/23] fix(integrate): removeBlock trigger multiple times in `EditSession` --- .../controller/BlockDataController.java | 33 +++++++++++------ .../integrations/WorldEditIntegration.java | 35 ++++++++++--------- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index d4aa7c44fd..2f3169d10b 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -4,7 +4,6 @@ import city.norain.slimefun4.api.menu.UniversalMenuPreset; import city.norain.slimefun4.utils.InventoryUtil; import city.norain.slimefun4.utils.StringUtil; -import city.norain.slimefun4.utils.TaskUtil; import com.xzavier0722.mc.plugin.slimefun4.storage.adapter.IDataSourceAdapter; import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; import com.xzavier0722.mc.plugin.slimefun4.storage.common.DataScope; @@ -361,12 +360,7 @@ public void removeBlock(Location l) { var removed = getChunkDataCache(l.getChunk(), true).removeBlockData(l); if (removed == null) { - getUniversalBlockDataFromCache(l) - .ifPresentOrElse( - data -> removeUniversalBlockData(data.getUUID()), - () -> TaskUtil.runSyncMethod(() -> Slimefun.getBlockDataService() - .getUniversalDataUUID(l.getBlock()) - .ifPresent(this::removeUniversalBlockData))); + removeUniversalBlockData(l); return; } @@ -375,14 +369,14 @@ public void removeBlock(Location l) { return; } + if (Slimefun.getRegistry().getTickerBlocks().contains(removed.getSfId())) { + Slimefun.getTickerTask().disableTicker(l); + } + var menu = removed.getBlockMenu(); if (menu != null) { menu.lock(); } - - if (Slimefun.getRegistry().getTickerBlocks().contains(removed.getSfId())) { - Slimefun.getTickerTask().disableTicker(l); - } } /** @@ -409,6 +403,23 @@ public void removeBlockData(Location l) { } } + /** + * 移除指定位置对应的可能存在的 Slimefun 通用方块数据 + * + * @param l {@link Location} 位置 + */ + public void removeUniversalBlockData(Location l) { + checkDestroy(); + + var toRemove = getUniversalBlockDataFromCache(l); + + if (toRemove.isEmpty()) { + return; + } + + removeUniversalBlockData(toRemove.get().getUUID()); + } + /** * 移除指定 UUID 对应的 Slimefun 通用方块数据 * diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/integrations/WorldEditIntegration.java b/src/main/java/io/github/thebusybiscuit/slimefun4/integrations/WorldEditIntegration.java index 308030ad79..692fabbbac 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/integrations/WorldEditIntegration.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/integrations/WorldEditIntegration.java @@ -1,5 +1,6 @@ package io.github.thebusybiscuit.slimefun4.integrations; +import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.event.extent.EditSessionEvent; @@ -37,27 +38,29 @@ public void register() { @Subscribe public void wrapForLogging(EditSessionEvent event) { - event.setExtent(new AbstractDelegateExtent(event.getExtent()) { + if (event.getStage() == EditSession.Stage.BEFORE_HISTORY) { + event.setExtent(new AbstractDelegateExtent(event.getExtent()) { - @Override - public > boolean setBlock(BlockVector3 pos, T block) - throws WorldEditException { - if (block.getBlockType().getMaterial().isAir()) { - World world = Bukkit.getWorld(event.getWorld().getName()); + @Override + public > boolean setBlock(BlockVector3 pos, T block) + throws WorldEditException { + if (block.getBlockType().getMaterial().isAir()) { + World world = Bukkit.getWorld(event.getWorld().getName()); - if (world != null) { - Location l = new Location(world, pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()); + if (world != null) { + Location l = new Location(world, pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()); - if (StorageCacheUtils.hasSlimefunBlock(l)) { - Slimefun.getDatabaseManager() - .getBlockDataController() - .removeBlock(l); + if (StorageCacheUtils.hasSlimefunBlock(l)) { + Slimefun.getDatabaseManager() + .getBlockDataController() + .removeBlock(l); + } } } - } - return getExtent().setBlock(pos, block); - } - }); + return getExtent().setBlock(pos, block); + } + }); + } } } From 6ef59be93dff3834f3965a75585ff7099138aee1 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sat, 2 Aug 2025 21:07:26 +0800 Subject: [PATCH 20/23] chore(ci): introduced `spotless-apply` workflow --- .github/workflows/build-ci.yml | 14 +++---- .github/workflows/dev-ci.yml | 14 ++----- .github/workflows/e2e-testing.yml | 4 ++ .github/workflows/pr-checker.yml | 10 ++--- .github/workflows/spotless.yml | 66 +++++++++++++++++++++++++++++++ 5 files changed, 82 insertions(+), 26 deletions(-) create mode 100644 .github/workflows/spotless.yml diff --git a/.github/workflows/build-ci.yml b/.github/workflows/build-ci.yml index a04667d4ea..f5b3820760 100644 --- a/.github/workflows/build-ci.yml +++ b/.github/workflows/build-ci.yml @@ -1,15 +1,11 @@ # This workflow will build a Java project with Maven # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven -name: Slimefun Builder +name: Slimefun Beta Builder on: - push: - branches: - - master - paths: - - 'src/**' - - 'pom.xml' + workflow_call: + secrets: inherit workflow_dispatch: env: @@ -31,9 +27,9 @@ jobs: architecture: x64 cache: maven - name: Codestyle Check - run: mvn -s .mvn/settings.xml -B spotless:check --errors + run: mvn -B spotless:check --errors - name: Build Slimefun - run: mvn -s .mvn/settings.xml -B package --errors + run: mvn -B package --errors - uses: actions/upload-artifact@v4 name: Upload Beta artifact with: diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index eb0f3e6942..e28dae2065 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -1,15 +1,11 @@ # This workflow will build a Java project with Maven # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven -name: Slimefun DEV +name: Slimefun Dev CI on: - push: - branches: - - dev - paths: - - 'src/**' - - 'pom.xml' + workflow_call: + secrets: inherit workflow_dispatch: env: @@ -27,8 +23,6 @@ jobs: java-package: jdk architecture: x64 cache: maven - - name: Codestyle check - run: mvn -s .mvn/settings.xml -B spotless:check --errors - name: Publish snapshots run: | echo "::add-mask::$MAVEN_ACCOUNT" @@ -38,7 +32,7 @@ jobs: MAVEN_ACCOUNT: '${{ vars.MAVEN_ACCOUNT }}' MAVEN_PASSWORD: '${{ secrets.MAVEN_PASSWORD }}' - name: Build Slimefun - run: mvn -s .mvn/settings.xml -B clean package --errors + run: mvn -B clean package --errors - name: Mask Output run: | echo "::add-mask::$CF_API_TOKEN" diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index 66ebc6167d..8efbd5aa6b 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -23,6 +23,10 @@ jobs: javaVersion: '18' - mcVersion: '1.19.4' javaVersion: '19' + - mcVersion: '1.20.6' + javaVersion: '21' + - mcVersion: '1.21.4' + javaVersion: '21' - mcVersion: 'latest' javaVersion: '21' diff --git a/.github/workflows/pr-checker.yml b/.github/workflows/pr-checker.yml index af76e23565..dbae9ecea7 100644 --- a/.github/workflows/pr-checker.yml +++ b/.github/workflows/pr-checker.yml @@ -4,12 +4,8 @@ name: Pull Request Checker on: - pull_request: - types: [opened, synchronize, reopened] - paths: - - '.github/workflows/**' - - 'src/**' - - 'pom.xml' + workflow_call: + secrets: inherit env: TZ: 'Asia/Shanghai' @@ -32,7 +28,7 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 21 + java-version: ${{ vars.JAVA_CI_VERSION }} java-package: jdk architecture: x64 cache: 'maven' diff --git a/.github/workflows/spotless.yml b/.github/workflows/spotless.yml new file mode 100644 index 0000000000..81fa7f4bf8 --- /dev/null +++ b/.github/workflows/spotless.yml @@ -0,0 +1,66 @@ +name: spotless.yml +on: + push: + branches: [ master, dev ] + paths: + - 'src/**' + - 'pom.xml' + pull_request: + types: [ opened, synchronize, reopened ] + paths: + - 'src/**' + - 'pom.xml' + +env: + TZ: 'Asia/Shanghai' + +jobs: + spotless: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 21 + java-package: jdk + architecture: x64 + cache: maven + + - name: Spotless check + id: spotless-check + run: mvn -B spotless:check --errors + continue-on-error: ${{ github.event.action == 'push' }} + + - name: Spotless apply (if needed) + id: spotless-apply + if: ${{ github.event.action == 'push' && failure() && steps.spotless-check.outcome == 'failure' }} + run: mvn -B spotless:apply --errors + + - name: Push changes + uses: EndBug/add-and-commit@v9.1.4 + if: ${{ github.event.action == 'push'}} + with: + github_token: ${{ secrets.ACCESS_TOKEN }} + add: '.' + push: true + message: 'chore(ci): spotless' + author_name: 'noraincity-bot' + author_email: ${{ secrets.BOT_EMAIL }} + committer_name: 'noraincity-bot' + committer_email: ${{ secrets.BOT_EMAIL }} + call-dev-ci: + needs: [ spotless ] + if: ${{ github.event.action == 'push' && github.ref_name == 'dev' }} + uses: ./.github/workflows/dev-ci.yml + call-beta-ci: + needs: [ spotless ] + if: ${{ github.event.action == 'push' && github.ref_name == 'master' }} + uses: ./.github/workflows/build-ci.yml + call-pr-checker: + needs: [ spotless ] + if: ${{ github.event.action == 'pull_request' }} + uses: ./.github/workflows/pr-checker.yml \ No newline at end of file From dde7d420f49b4bf851fe0a3aa4d9edd2ddb94ac1 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sat, 2 Aug 2025 21:40:57 +0800 Subject: [PATCH 21/23] fix(ci): use inherit secrets properly --- .github/workflows/build-ci.yml | 1 - .github/workflows/dev-ci.yml | 1 - .github/workflows/pr-checker.yml | 2 -- .github/workflows/spotless.yml | 5 ++++- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-ci.yml b/.github/workflows/build-ci.yml index f5b3820760..7ab7461591 100644 --- a/.github/workflows/build-ci.yml +++ b/.github/workflows/build-ci.yml @@ -5,7 +5,6 @@ name: Slimefun Beta Builder on: workflow_call: - secrets: inherit workflow_dispatch: env: diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index e28dae2065..8ded8ede74 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -5,7 +5,6 @@ name: Slimefun Dev CI on: workflow_call: - secrets: inherit workflow_dispatch: env: diff --git a/.github/workflows/pr-checker.yml b/.github/workflows/pr-checker.yml index dbae9ecea7..7c46dda9b3 100644 --- a/.github/workflows/pr-checker.yml +++ b/.github/workflows/pr-checker.yml @@ -5,8 +5,6 @@ name: Pull Request Checker on: workflow_call: - secrets: inherit - env: TZ: 'Asia/Shanghai' diff --git a/.github/workflows/spotless.yml b/.github/workflows/spotless.yml index 81fa7f4bf8..82dd71726e 100644 --- a/.github/workflows/spotless.yml +++ b/.github/workflows/spotless.yml @@ -56,11 +56,14 @@ jobs: needs: [ spotless ] if: ${{ github.event.action == 'push' && github.ref_name == 'dev' }} uses: ./.github/workflows/dev-ci.yml + secrets: inherit call-beta-ci: needs: [ spotless ] if: ${{ github.event.action == 'push' && github.ref_name == 'master' }} uses: ./.github/workflows/build-ci.yml + secrets: inherit call-pr-checker: needs: [ spotless ] if: ${{ github.event.action == 'pull_request' }} - uses: ./.github/workflows/pr-checker.yml \ No newline at end of file + uses: ./.github/workflows/pr-checker.yml + secrets: inherit \ No newline at end of file From 88223dd6ec891520c0c3edd5e45fc1f52f3db526 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sat, 2 Aug 2025 22:27:35 +0800 Subject: [PATCH 22/23] fix(ci): wrong condition on validate next ci --- .github/workflows/spotless.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/spotless.yml b/.github/workflows/spotless.yml index 82dd71726e..76241d2e69 100644 --- a/.github/workflows/spotless.yml +++ b/.github/workflows/spotless.yml @@ -33,16 +33,16 @@ jobs: - name: Spotless check id: spotless-check run: mvn -B spotless:check --errors - continue-on-error: ${{ github.event.action == 'push' }} + continue-on-error: ${{ github.event_name == 'push' }} - name: Spotless apply (if needed) id: spotless-apply - if: ${{ github.event.action == 'push' && failure() && steps.spotless-check.outcome == 'failure' }} + if: ${{ github.github.event_name == 'push' && failure() && steps.spotless-check.outcome == 'failure' }} run: mvn -B spotless:apply --errors - name: Push changes uses: EndBug/add-and-commit@v9.1.4 - if: ${{ github.event.action == 'push'}} + if: ${{ github.github.event_name == 'push'}} with: github_token: ${{ secrets.ACCESS_TOKEN }} add: '.' @@ -54,16 +54,16 @@ jobs: committer_email: ${{ secrets.BOT_EMAIL }} call-dev-ci: needs: [ spotless ] - if: ${{ github.event.action == 'push' && github.ref_name == 'dev' }} + if: ${{ github.event_name == 'PushEvent' && github.ref_name == 'dev' }} uses: ./.github/workflows/dev-ci.yml secrets: inherit call-beta-ci: needs: [ spotless ] - if: ${{ github.event.action == 'push' && github.ref_name == 'master' }} + if: ${{ github.event_name == 'push' && github.ref_name == 'master' }} uses: ./.github/workflows/build-ci.yml secrets: inherit call-pr-checker: needs: [ spotless ] - if: ${{ github.event.action == 'pull_request' }} + if: ${{ github.event_name == 'pull_request' }} uses: ./.github/workflows/pr-checker.yml secrets: inherit \ No newline at end of file From 7cd30b44853ea2fb367042e08ca0c060a928d04a Mon Sep 17 00:00:00 2001 From: ybw0014 Date: Mon, 4 Aug 2025 22:24:38 -0400 Subject: [PATCH 23/23] chore: fix jitpack build --- jitpack.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jitpack.yml b/jitpack.yml index 6926d32e7e..c565f83c3d 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -1,6 +1,6 @@ before_install: - - sdk install java 17.0.15-zulu - - sdk use java 17.0.15-zulu + - sdk install java 21.0.8-zulu + - sdk use java 21.0.8-zulu - sdk install maven install: