From 49017b80f5c82714150ce71eeb6b9b672ef08d8d Mon Sep 17 00:00:00 2001 From: Djoey Date: Wed, 25 Mar 2026 20:32:01 +0100 Subject: [PATCH 01/13] feat: add BukkitHourlyClaimBlocksEvent for AxBoosters integration Add a dedicated Bukkit event that fires when players receive hourly claim blocks, allowing booster plugins like AxBoosters to modify the amount via reflection (getPlayer/getAmount/setAmount). The event fires on the main thread before blocks are granted, and the boosted amount flows through the existing max claim blocks cap. --- .../event/BukkitEventDispatcher.java | 18 +++++ .../event/BukkitHourlyClaimBlocksEvent.java | 71 +++++++++++++++++++ .../huskclaims/event/EventDispatcher.java | 5 ++ .../huskclaims/user/ClaimBlocksManager.java | 30 +++++--- 4 files changed, 113 insertions(+), 11 deletions(-) create mode 100644 bukkit/src/main/java/net/william278/huskclaims/event/BukkitHourlyClaimBlocksEvent.java diff --git a/bukkit/src/main/java/net/william278/huskclaims/event/BukkitEventDispatcher.java b/bukkit/src/main/java/net/william278/huskclaims/event/BukkitEventDispatcher.java index a1043b7c..1486e584 100644 --- a/bukkit/src/main/java/net/william278/huskclaims/event/BukkitEventDispatcher.java +++ b/bukkit/src/main/java/net/william278/huskclaims/event/BukkitEventDispatcher.java @@ -30,12 +30,14 @@ import net.william278.huskclaims.user.OnlineUser; import net.william278.huskclaims.user.SavedUserProvider; import net.william278.huskclaims.user.User; +import net.william278.huskclaims.user.BukkitUser; import org.bukkit.event.Cancellable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Map; +import java.util.function.Consumer; public interface BukkitEventDispatcher extends EventDispatcher { @@ -45,6 +47,22 @@ default boolean fireIsCancelled(@NotNull T event) { return event instanceof Cancellable cancellable && cancellable.isCancelled(); } + @Override + default void fireHourlyClaimBlocksEvent(@NotNull OnlineUser user, long amount, + @NotNull Consumer callback) { + if (!(user instanceof BukkitUser bukkitUser)) { + callback.accept(amount); + return; + } + final BukkitHourlyClaimBlocksEvent event = new BukkitHourlyClaimBlocksEvent( + bukkitUser.getBukkitPlayer(), amount + ); + getPlugin().runSync(() -> { + ((BukkitHuskClaims) getPlugin()).getServer().getPluginManager().callEvent(event); + getPlugin().runAsync(() -> callback.accept(event.getAmount())); + }); + } + @Override @NotNull default ClaimBlocksChangeEvent getClaimBlocksChangeEvent(@NotNull User user, long oldBlocks, long newBlocks, diff --git a/bukkit/src/main/java/net/william278/huskclaims/event/BukkitHourlyClaimBlocksEvent.java b/bukkit/src/main/java/net/william278/huskclaims/event/BukkitHourlyClaimBlocksEvent.java new file mode 100644 index 00000000..82822111 --- /dev/null +++ b/bukkit/src/main/java/net/william278/huskclaims/event/BukkitHourlyClaimBlocksEvent.java @@ -0,0 +1,71 @@ +/* + * This file is part of HuskClaims, licensed under the Apache License 2.0. + * + * Copyright (c) William278 + * Copyright (c) contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.william278.huskclaims.event; + +import lombok.Getter; +import lombok.Setter; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; + +/** + * Bukkit event fired when a player receives hourly claim blocks. + *

+ * This event is designed for integration with booster plugins (e.g. AxBoosters) + * that modify values via reflection using getter/setter methods. + *

+ * AxBoosters config example: + *

+ * huskclaims:
+ *   icon: GRASS_BLOCK
+ *   event: net.william278.huskclaims.event.BukkitHourlyClaimBlocksEvent
+ *   player: getPlayer
+ *   getter: getAmount
+ *   setter: setAmount
+ * 
+ */ +@Getter +public class BukkitHourlyClaimBlocksEvent extends Event { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final Player player; + + @Setter + private long amount; + + public BukkitHourlyClaimBlocksEvent(@NotNull Player player, long amount) { + super(false); + this.player = player; + this.amount = amount; + } + + @NotNull + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + +} diff --git a/common/src/main/java/net/william278/huskclaims/event/EventDispatcher.java b/common/src/main/java/net/william278/huskclaims/event/EventDispatcher.java index cb83f140..56ab20f8 100644 --- a/common/src/main/java/net/william278/huskclaims/event/EventDispatcher.java +++ b/common/src/main/java/net/william278/huskclaims/event/EventDispatcher.java @@ -75,6 +75,11 @@ default void fireClaimBlocksChangeEvent(@NotNull User user, long oldClaimBlocks, fireEvent(getClaimBlocksChangeEvent(user, oldClaimBlocks, newClaimBlocks, reason), callback); } + default void fireHourlyClaimBlocksEvent(@NotNull OnlineUser user, long amount, + @NotNull Consumer callback) { + callback.accept(amount); + } + default void fireCreateChildClaimEvent(@NotNull OnlineUser claimer, @NotNull Claim parent, @NotNull Region childRegion, @NotNull ClaimWorld claimWorld, @NotNull Consumer callback) { diff --git a/common/src/main/java/net/william278/huskclaims/user/ClaimBlocksManager.java b/common/src/main/java/net/william278/huskclaims/user/ClaimBlocksManager.java index bb36c257..eeefd5e1 100644 --- a/common/src/main/java/net/william278/huskclaims/user/ClaimBlocksManager.java +++ b/common/src/main/java/net/william278/huskclaims/user/ClaimBlocksManager.java @@ -156,18 +156,26 @@ default void grantHourlyClaimBlocks(@NotNull OnlineUser user) { return; } - try { - // Double-check user is still online right before block editing to minimize TOCTOU window - if (!getPlugin().getOnlineUserMap().containsKey(user.getUuid())) { - return; - } - editClaimBlocks(user, ClaimBlockSource.HOURLY_BLOCKS, (blocks -> blocks + hourlyBlocks)); - } catch (IllegalArgumentException e) { - // Log warning if user data becomes unavailable during execution - // This can happen if user disconnects after validation but before block editing - getPlugin().log(Level.WARNING, "Failed to grant hourly claim blocks to user " + - user.getUuid() + " (user data unavailable): " + e.getMessage()); + if (!getPlugin().getOnlineUserMap().containsKey(user.getUuid())) { + return; } + + // Fire hourly claim blocks event to allow booster plugins (e.g. AxBoosters) to modify the amount + getPlugin().fireHourlyClaimBlocksEvent(user, hourlyBlocks, (adjustedAmount) -> { + try { + // Double-check user is still online right before block editing to minimize TOCTOU window + if (!getPlugin().getOnlineUserMap().containsKey(user.getUuid())) { + return; + } + editClaimBlocks(user, ClaimBlockSource.HOURLY_BLOCKS, + (blocks -> blocks + adjustedAmount)); + } catch (IllegalArgumentException e) { + // Log warning if user data becomes unavailable during execution + // This can happen if user disconnects after validation but before block editing + getPlugin().log(Level.WARNING, "Failed to grant hourly claim blocks to user " + + user.getUuid() + " (user data unavailable): " + e.getMessage()); + } + }); } default void loadClaimBlockScheduler() { From 58134079fe64cb19bb426e593b3fbbd5708c69a2 Mon Sep 17 00:00:00 2001 From: Djoey Date: Sat, 9 May 2026 17:13:19 +0200 Subject: [PATCH 02/13] fix: replace stale BukkitUser cache holding offline Player reference BukkitUserProvider.getOnlineUser(Player) returned cached BukkitUser without verifying it wrapped the current Player object. After a cross-server proxy switch where the previous session's PlayerQuitEvent fires late or is dropped, the cache still held a BukkitUser with a detached Player reference. All subsequent lookups (placeholders, permission checks, claim ownership, event dispatch) operated on the offline Player, causing frozen scoreboard claim info, "no permission" errors on commands like /ignoreclaims, and empty placeholder output until relog. Mirrors the existing FabricUserProvider guard. --- .../net/william278/huskclaims/user/BukkitUserProvider.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bukkit/src/main/java/net/william278/huskclaims/user/BukkitUserProvider.java b/bukkit/src/main/java/net/william278/huskclaims/user/BukkitUserProvider.java index 4bcd130c..be1f4122 100644 --- a/bukkit/src/main/java/net/william278/huskclaims/user/BukkitUserProvider.java +++ b/bukkit/src/main/java/net/william278/huskclaims/user/BukkitUserProvider.java @@ -40,10 +40,9 @@ default BukkitUser getOnlineUser(@Nullable Player player) { throw new IllegalArgumentException("Player is not online"); } BukkitUser user = (BukkitUser) getOnlineUserMap().get(player.getUniqueId()); - if (user == null) { + if (user == null || user.getBukkitPlayer() != player || !user.getBukkitPlayer().isOnline()) { user = BukkitUser.adapt(player, getPlugin()); getOnlineUserMap().put(player.getUniqueId(), user); - return user; } return user; } From 2608536bc056f0af332d71c53ac63f5cc204053d Mon Sep 17 00:00:00 2001 From: Djoey Date: Mon, 25 May 2026 15:25:33 +0200 Subject: [PATCH 03/13] fix: refresh cached claim username on join after Minecraft name change ClaimWorld.userCache (UUID -> name, persisted) was only written by cacheUser() during claim create/trust/ban/transfer. The join path updated the SavedUser record but never the per-world username cache, so claim owner placeholders (CURRENT_CLAIM_OWNER) kept showing the old name after a player changed their Minecraft name mid-session. Workaround was transferring the claim away and back. Add ClaimWorld.refreshUserName, called from onUserJoin, which updates only already-cached users (owners/trustees) and persists worlds whose name actually changed. --- .../huskclaims/claim/ClaimWorld.java | 21 +++++++++++++++++++ .../huskclaims/listener/UserListener.java | 12 +++++++++++ 2 files changed, 33 insertions(+) diff --git a/common/src/main/java/net/william278/huskclaims/claim/ClaimWorld.java b/common/src/main/java/net/william278/huskclaims/claim/ClaimWorld.java index b575ee5e..ee477cbb 100644 --- a/common/src/main/java/net/william278/huskclaims/claim/ClaimWorld.java +++ b/common/src/main/java/net/william278/huskclaims/claim/ClaimWorld.java @@ -381,6 +381,27 @@ public void cacheUser(@NotNull User user) { userCache.put(user.getUuid(), user.getName()); } + /** + * Refresh the cached username for a user already known to this world (e.g. after a Minecraft name change). + *

+ * Only updates users already present in the cache (claim owners and trustees), so this never adds spurious + * entries. Does nothing if the name is unchanged. + * + * @param uuid the UUID of the user + * @param name the user's current username + * @return {@code true} if the cached name was changed, {@code false} otherwise + * @since 1.4 + */ + @ApiStatus.Internal + public boolean refreshUserName(@NotNull UUID uuid, @NotNull String name) { + final String cached = userCache.get(uuid); + if (cached == null || cached.equals(name)) { + return false; + } + userCache.put(uuid, name); + return true; + } + /** * Get the claims a region overlaps with, except for certain claims * diff --git a/common/src/main/java/net/william278/huskclaims/listener/UserListener.java b/common/src/main/java/net/william278/huskclaims/listener/UserListener.java index 0b247d34..929efbf0 100644 --- a/common/src/main/java/net/william278/huskclaims/listener/UserListener.java +++ b/common/src/main/java/net/william278/huskclaims/listener/UserListener.java @@ -32,6 +32,7 @@ public interface UserListener { default void onUserJoin(@NotNull OnlineUser user) { getPlugin().runAsync(() -> { getPlugin().cacheSavedUser(user); + refreshClaimWorldUserName(user); final Preferences prefs = getPlugin().getCachedUserPreferences(user.getUuid()).orElse(Preferences.DEFAULTS); final Settings.ClaimSettings settings = getPlugin().getSettings().getClaims(); @@ -75,6 +76,17 @@ default void onUserSwitchHeldItem(@NotNull OnlineUser user, @NotNull String main } } + // Refresh the user's cached name in all loaded claim worlds, in case they changed their Minecraft name + // while the server was running. Without this, claim owner placeholders show the old name until a claim + // operation (e.g. trust/transfer) rewrites the cache. + private void refreshClaimWorldUserName(@NotNull OnlineUser user) { + getPlugin().getClaimWorlds().values().forEach(world -> { + if (world.refreshUserName(user.getUuid(), user.getName())) { + getPlugin().runQueued(() -> getPlugin().getDatabase().updateClaimWorld(world)); + } + }); + } + // Check if a user is ignoring claims on join and if they can't do so anymore, toggle private void checkIgnoringClaimsOnLogin(@NotNull OnlineUser u) { if (getPlugin().canUseCommand(IgnoreClaimsCommand.class, u)) { From 644b937f08f23a4847d76eac980fee8b9dd9f14f Mon Sep 17 00:00:00 2001 From: Joris van Dorst Date: Mon, 8 Jun 2026 13:08:26 +0200 Subject: [PATCH 04/13] Increase hourly_blocks_updates to 10 to account for division of the numbers and shorter playtime --- .../java/net/william278/huskclaims/user/ClaimBlocksManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/net/william278/huskclaims/user/ClaimBlocksManager.java b/common/src/main/java/net/william278/huskclaims/user/ClaimBlocksManager.java index eeefd5e1..eeb1a27b 100644 --- a/common/src/main/java/net/william278/huskclaims/user/ClaimBlocksManager.java +++ b/common/src/main/java/net/william278/huskclaims/user/ClaimBlocksManager.java @@ -37,7 +37,7 @@ public interface ClaimBlocksManager { // How many times per hour to run the claim block update task for all users - int HOURLY_BLOCKS_UPDATES = 4; + int HOURLY_BLOCKS_UPDATES = 10; // Permission to grant hourly claim blocks String HOURLY_BLOCKS_PERMISSION = "huskclaims.hourly_blocks."; From 5bf02aaa5da7bfb761b86034fec925577060b86e Mon Sep 17 00:00:00 2001 From: Joris van Dorst Date: Mon, 8 Jun 2026 13:11:25 +0200 Subject: [PATCH 05/13] Increase hourly_blocks_updates to 5* to account for division of the numbers and shorter playtime --- .../java/net/william278/huskclaims/user/ClaimBlocksManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/net/william278/huskclaims/user/ClaimBlocksManager.java b/common/src/main/java/net/william278/huskclaims/user/ClaimBlocksManager.java index eeb1a27b..f56fe239 100644 --- a/common/src/main/java/net/william278/huskclaims/user/ClaimBlocksManager.java +++ b/common/src/main/java/net/william278/huskclaims/user/ClaimBlocksManager.java @@ -37,7 +37,7 @@ public interface ClaimBlocksManager { // How many times per hour to run the claim block update task for all users - int HOURLY_BLOCKS_UPDATES = 10; + int HOURLY_BLOCKS_UPDATES = 5; // Permission to grant hourly claim blocks String HOURLY_BLOCKS_PERMISSION = "huskclaims.hourly_blocks."; From 5caae68fb11c8d095ba8e78c5770b4eb8c447277 Mon Sep 17 00:00:00 2001 From: Djoey Date: Wed, 1 Jul 2026 11:12:59 +0200 Subject: [PATCH 06/13] replace arim.space repo with Rosewood mirror for morepaperlib --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d5d49141..63dd687c 100644 --- a/build.gradle +++ b/build.gradle @@ -76,7 +76,7 @@ allprojects { maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' } maven { url 'https://repo.papermc.io/repository/maven-public/' } maven { url 'https://repo.william278.net/releases/' } - maven { url 'https://mvn-repo.arim.space/lesser-gpl3/' } + maven { url 'https://repo.rosewooddev.io/repository/public/' } //replaces https://mvn-repo.arim.space/lesser-gpl3/ till working again maven { url 'https://repo.mikeprimm.com/' } maven { url 'https://repo.minebench.de/' } maven { url 'https://api.modrinth.com/maven/' } From 1320b4e6e54355251da2882f749edeb0e3cdef6a Mon Sep 17 00:00:00 2001 From: Djoey Date: Wed, 1 Jul 2026 11:20:22 +0200 Subject: [PATCH 07/13] remove decommissioned s01.oss.sonatype.org repository --- fabric/build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fabric/build.gradle b/fabric/build.gradle index 55b766af..86652193 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -6,7 +6,6 @@ plugins { loom.serverOnlyMinecraftJar() repositories { - maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' } maven { url 'https://maven.impactdev.net/repository/development/' } maven { url 'https://maven.nucleoid.xyz/' } } @@ -79,4 +78,4 @@ remapJar { archiveClassifier.set('') } -shadowJar.finalizedBy(remapJar) \ No newline at end of file +shadowJar.finalizedBy(remapJar) From a9c1181d6a9fe5a62b5b2ade27dc84f4e66b02a0 Mon Sep 17 00:00:00 2001 From: Djoey Date: Wed, 1 Jul 2026 11:47:04 +0200 Subject: [PATCH 08/13] Test build refresh dependencies --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6e3d780b..71ef7630 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - name: 'Build with Gradle 🏗️' uses: gradle/gradle-build-action@v3 with: - arguments: build test publish + arguments: build test publish --refresh-dependencies env: SNAPSHOTS_MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} SNAPSHOTS_MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} @@ -73,4 +73,4 @@ jobs: target/HuskClaims-Fabric-${{ env.version_name }}+mc.1.21.1.jar target/HuskClaims-Fabric-${{ env.version_name }}+mc.1.21.4.jar target/HuskClaims-Fabric-${{ env.version_name }}+mc.1.21.5.jar - target/HuskClaims-Fabric-${{ env.version_name }}+mc.1.21.7.jar \ No newline at end of file + target/HuskClaims-Fabric-${{ env.version_name }}+mc.1.21.7.jar From 71793f51fbd4e6ef08aedd06f3788055b4c8e839 Mon Sep 17 00:00:00 2001 From: Djoey Date: Wed, 1 Jul 2026 12:03:15 +0200 Subject: [PATCH 09/13] Reverted morepaperlib repo. Rosewood isnt an alternative We need to wait till morepaperlib is back up --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 63dd687c..6ebed3f0 100644 --- a/build.gradle +++ b/build.gradle @@ -76,7 +76,6 @@ allprojects { maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' } maven { url 'https://repo.papermc.io/repository/maven-public/' } maven { url 'https://repo.william278.net/releases/' } - maven { url 'https://repo.rosewooddev.io/repository/public/' } //replaces https://mvn-repo.arim.space/lesser-gpl3/ till working again maven { url 'https://repo.mikeprimm.com/' } maven { url 'https://repo.minebench.de/' } maven { url 'https://api.modrinth.com/maven/' } @@ -85,6 +84,7 @@ allprojects { maven { url 'https://maven.enginehub.org/repo/' } maven { url 'https://repo.william278.net/snapshots/' } maven { url 'https://jitpack.io' } + maven { url 'https://mvn-repo.arim.space/lesser-gpl3/' } } dependencies { From a138d0b27429968b9ca344731c3702dd15685ffd Mon Sep 17 00:00:00 2001 From: Djoey Date: Wed, 1 Jul 2026 12:18:36 +0200 Subject: [PATCH 10/13] Try building morepaperlib directly from github --- bukkit/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bukkit/build.gradle b/bukkit/build.gradle index a2dfe1a9..2e0b7511 100644 --- a/bukkit/build.gradle +++ b/bukkit/build.gradle @@ -7,7 +7,7 @@ dependencies { implementation 'net.kyori:adventure-platform-bukkit:4.4.0' implementation 'io.papermc:paperlib:1.0.8' - implementation 'space.arim.morepaperlib:morepaperlib:0.4.4' + implementation 'com.github.A248:MorePaperLib:0.4.4' implementation 'net.william278.cloplib:cloplib-bukkit:2.0.12' implementation 'net.william278.toilet:toilet-bukkit:1.0.15' implementation 'org.bstats:bstats-bukkit:3.1.0' @@ -59,4 +59,4 @@ shadowJar { relocate 'net.roxeez', 'net.william278.huskclaims.libraries' minimize() -} \ No newline at end of file +} From 32342c8f220cdfcb8b4385e31ab3310dc783828c Mon Sep 17 00:00:00 2001 From: Djoey Date: Wed, 1 Jul 2026 12:24:32 +0200 Subject: [PATCH 11/13] Remove arpim.space because of building from jitpack. breaks other deps --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6ebed3f0..539fa2df 100644 --- a/build.gradle +++ b/build.gradle @@ -84,7 +84,6 @@ allprojects { maven { url 'https://maven.enginehub.org/repo/' } maven { url 'https://repo.william278.net/snapshots/' } maven { url 'https://jitpack.io' } - maven { url 'https://mvn-repo.arim.space/lesser-gpl3/' } } dependencies { From 8aa92de93ce38425ffcac561136b5ddc5033477e Mon Sep 17 00:00:00 2001 From: Djoey Date: Fri, 3 Jul 2026 15:12:04 +0200 Subject: [PATCH 12/13] arim space repo working again --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 539fa2df..6ebed3f0 100644 --- a/build.gradle +++ b/build.gradle @@ -84,6 +84,7 @@ allprojects { maven { url 'https://maven.enginehub.org/repo/' } maven { url 'https://repo.william278.net/snapshots/' } maven { url 'https://jitpack.io' } + maven { url 'https://mvn-repo.arim.space/lesser-gpl3/' } } dependencies { From 2d5598a96cf194df76ccbfacbfe3c2b9ed809fa5 Mon Sep 17 00:00:00 2001 From: Djoey Date: Fri, 3 Jul 2026 15:19:21 +0200 Subject: [PATCH 13/13] Restore space arim --- bukkit/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bukkit/build.gradle b/bukkit/build.gradle index 2e0b7511..01049313 100644 --- a/bukkit/build.gradle +++ b/bukkit/build.gradle @@ -7,7 +7,7 @@ dependencies { implementation 'net.kyori:adventure-platform-bukkit:4.4.0' implementation 'io.papermc:paperlib:1.0.8' - implementation 'com.github.A248:MorePaperLib:0.4.4' + implementation 'space.arim.morepaperlib:morepaperlib:0.4.4' implementation 'net.william278.cloplib:cloplib-bukkit:2.0.12' implementation 'net.william278.toilet:toilet-bukkit:1.0.15' implementation 'org.bstats:bstats-bukkit:3.1.0'