From bbe51ed0ed840979f78dd60e2c10cdf4e9a73867 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Sat, 15 Nov 2025 20:25:48 +0100 Subject: [PATCH 1/5] Add economy dependency --- build.gradle.kts | 26 ++++++++++++++----- .../parcellockers/ParcelLockers.java | 21 +++++++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index e8a122c6..f595d1fc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,5 @@ +import net.minecrell.pluginyml.paper.PaperPluginDescription + plugins { `java-library` id("de.eldoria.plugin-yml.paper") version "0.8.0" @@ -10,12 +12,13 @@ version = "0.0.2-SNAPSHOT" repositories { gradlePluginPortal() - maven { url = uri("https://maven-central.storage-download.googleapis.com/maven2/")} + maven("https://maven-central.storage-download.googleapis.com/maven2/") // maven central mirror - maven { url = uri("https://repo.triumphteam.dev/snapshots/")} - maven { url = uri("https://repo.papermc.io/repository/maven-public/") } - maven { url = uri("https://repo.eternalcode.pl/releases") } - maven { url = uri("https://storehouse.okaeri.eu/repository/maven-public/") } + maven("https://repo.triumphteam.dev/snapshots/") + maven("https://jitpack.io") + maven("https://repo.papermc.io/repository/maven-public/") + maven("https://repo.eternalcode.pl/releases") + maven("https://storehouse.okaeri.eu/repository/maven-public/") } dependencies { @@ -73,6 +76,9 @@ dependencies { // caffeine paperLibrary("com.github.ben-manes.caffeine:caffeine:3.2.3") + // vault + compileOnly("com.github.MilkBowl:VaultAPI:1.7.1") + testImplementation("org.junit.jupiter:junit-jupiter-api:6.0.1") testImplementation("org.junit.jupiter:junit-jupiter-params:6.0.1") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:6.0.1") @@ -98,6 +104,12 @@ paper { loader = "com.eternalcode.parcellockers.ParcelLockersLibraryLoader" generateLibrariesJson = true foliaSupported = false + serverDependencies { + register("Vault") { + required = true + load = PaperPluginDescription.RelativeLoadOrder.BEFORE + } + } } tasks.withType { @@ -110,7 +122,9 @@ tasks.withType { tasks { runServer { minecraftVersion("1.21.10") - downloadPlugins.modrinth("luckperms", "v5.5.0-bukkit") + downloadPlugins.modrinth("luckperms", "v5.5.17-bukkit") + downloadPlugins.modrinth("vaultunlocked", "2.17.0") + // TODO add eternaleconomy } test { diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index 3449f798..76d7494d 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -59,9 +59,11 @@ import java.util.ArrayList; import java.util.stream.Stream; import net.kyori.adventure.text.minimessage.MiniMessage; +import net.milkbowl.vault.economy.Economy; import org.bstats.bukkit.Metrics; import org.bukkit.Server; import org.bukkit.command.CommandSender; +import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.java.JavaPlugin; public final class ParcelLockers extends JavaPlugin { @@ -69,6 +71,7 @@ public final class ParcelLockers extends JavaPlugin { private LiteCommands liteCommands; private SkullAPI skullAPI; private DatabaseManager databaseManager; + private Economy economy; @Override public void onEnable() { @@ -84,6 +87,12 @@ public void onEnable() { NoticeService noticeService = new NoticeService(messageConfig, miniMessage); Scheduler scheduler = new BukkitSchedulerImpl(this); + if (!this.setupEconomy()) { + this.getLogger().severe("No economy provider registered! Disabling..."); + server.getPluginManager().disablePlugin(this); + return; + } + DatabaseManager databaseManager = new DatabaseManager(config, this.getLogger(), this.getDataFolder()); this.databaseManager = databaseManager; @@ -207,6 +216,18 @@ public void onDisable() { this.skullAPI.shutdown(); } } + + private boolean setupEconomy() { + if (this.getServer().getPluginManager().getPlugin("Vault") == null) { + return false; + } + RegisteredServiceProvider rsp = this.getServer().getServicesManager().getRegistration(Economy.class); + if (rsp == null) { + return false; + } + this.economy = rsp.getProvider(); + return this.economy != null; + } } From 32cd596bb36ea699827ab3bf9b26a909cca91cfe Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Sat, 15 Nov 2025 20:37:13 +0100 Subject: [PATCH 2/5] Add parcel fees --- .../implementation/MessageConfig.java | 8 +++++ .../implementation/PluginConfig.java | 9 +++++ .../parcel/ParcelServiceImpl.java | 36 ++++++++++++++++++- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/eternalcode/parcellockers/configuration/implementation/MessageConfig.java b/src/main/java/com/eternalcode/parcellockers/configuration/implementation/MessageConfig.java index 1ffd0ae9..2da416f6 100644 --- a/src/main/java/com/eternalcode/parcellockers/configuration/implementation/MessageConfig.java +++ b/src/main/java/com/eternalcode/parcellockers/configuration/implementation/MessageConfig.java @@ -111,6 +111,14 @@ public static class ParcelMessages extends OkaeriConfig { .chat("&2✔ &aParcel deleted successfully.") .sound(Sound.ENTITY_ITEM_BREAK.key()) .build(); + public Notice insufficientFunds = Notice.builder() + .chat("&4✘ &cYou do not have enough funds to send this parcel! Required: &6${AMOUNT}&c.") + .sound(Sound.ENTITY_VILLAGER_NO.key()) + .build(); + public Notice feeWithdrawn = Notice.builder() + .chat("&2✔ &a${AMOUNT} has been withdrawn from your account to cover the parcel sending fee.") + .sound(Sound.ENTITY_EXPERIENCE_ORB_PICKUP.key()) + .build(); @Comment({"", "# The parcel info message." }) public Notice parcelInfoMessages = Notice.builder() diff --git a/src/main/java/com/eternalcode/parcellockers/configuration/implementation/PluginConfig.java b/src/main/java/com/eternalcode/parcellockers/configuration/implementation/PluginConfig.java index 7818b1ae..fe0dd866 100644 --- a/src/main/java/com/eternalcode/parcellockers/configuration/implementation/PluginConfig.java +++ b/src/main/java/com/eternalcode/parcellockers/configuration/implementation/PluginConfig.java @@ -61,6 +61,15 @@ public static class Settings extends OkaeriConfig { @Comment({"", "# Maximum number of parcels that can be stored in a single locker"}) public int maxParcelsPerLocker = 30; + + @Comment({"", "# Small parcel fee in in-game currency"}) + public double smallParcelFee = 10.0; + + @Comment({"", "# Medium parcel fee in in-game currency"}) + public double mediumParcelFee = 25.0; + + @Comment({"", "# Large parcel fee in in-game currency"}) + public double largeParcelFee = 50.0; } public static class GuiSettings extends OkaeriConfig { diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/ParcelServiceImpl.java b/src/main/java/com/eternalcode/parcellockers/parcel/ParcelServiceImpl.java index 29129a63..942e93d3 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/ParcelServiceImpl.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/ParcelServiceImpl.java @@ -4,6 +4,7 @@ import com.eternalcode.commons.bukkit.ItemUtil; import com.eternalcode.commons.scheduler.Scheduler; +import com.eternalcode.parcellockers.configuration.implementation.PluginConfig; import com.eternalcode.parcellockers.content.ParcelContent; import com.eternalcode.parcellockers.content.repository.ParcelContentRepository; import com.eternalcode.parcellockers.notification.NoticeService; @@ -19,16 +20,21 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; +import net.milkbowl.vault.economy.Economy; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; public class ParcelServiceImpl implements ParcelService { + private static final String PARCEL_FEE_BYPASS_PERMISSION = "parcellockers.fee.bypass"; + private final NoticeService noticeService; private final ParcelRepository parcelRepository; private final ParcelContentRepository parcelContentRepository; private final Scheduler scheduler; + private final PluginConfig config; + private final Economy economy; private final Cache parcelsByUuid; private final Cache> parcelsBySender; @@ -38,12 +44,14 @@ public ParcelServiceImpl( NoticeService noticeService, ParcelRepository parcelRepository, ParcelContentRepository parcelContentRepository, - Scheduler scheduler + Scheduler scheduler, PluginConfig config, Economy economy ) { this.noticeService = noticeService; this.parcelRepository = parcelRepository; this.parcelContentRepository = parcelContentRepository; this.scheduler = scheduler; + this.config = config; + this.economy = economy; this.parcelsByUuid = Caffeine.newBuilder() .expireAfterAccess(3, TimeUnit.HOURS) @@ -65,6 +73,32 @@ public ParcelServiceImpl( @Override public CompletableFuture send(Player sender, Parcel parcel, List items) { + if (!sender.hasPermission(PARCEL_FEE_BYPASS_PERMISSION)) { + double fee = switch (parcel.size()) { + case SMALL -> this.config.settings.smallParcelFee; + case MEDIUM -> this.config.settings.mediumParcelFee; + case LARGE -> this.config.settings.largeParcelFee; + }; + + if (fee > 0) { + boolean success = this.economy.withdrawPlayer(sender, fee).transactionSuccess(); + if (!success) { + this.noticeService.create() + .notice(messages -> messages.parcel.insufficientFunds) + .player(sender.getUniqueId()) + .placeholder("{AMOUNT}", String.format("%.2f", fee)) + .send(); + return CompletableFuture.completedFuture(null); + } + + this.noticeService.create() + .notice(messages -> messages.parcel.feeWithdrawn) + .player(sender.getUniqueId()) + .placeholder("{AMOUNT}", String.format("%.2f", fee)) + .send(); + } + } + return this.parcelRepository.save(parcel).whenComplete((unused, throwable) -> { if (throwable != null) { this.noticeService.create() From 7d947d0f4f12128bbaedf54b53ae9d77527ebd87 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 9 Dec 2025 21:53:04 +0100 Subject: [PATCH 3/5] Fix build, add missing AND clause in statement builder --- build.gradle.kts | 2 +- .../java/com/eternalcode/parcellockers/ParcelLockers.java | 4 +++- .../parcel/repository/ParcelRepositoryOrmLite.java | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3e97e957..4acb6f1b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -124,7 +124,7 @@ tasks { minecraftVersion("1.21.10") downloadPlugins.modrinth("luckperms", "v5.5.17-bukkit") downloadPlugins.modrinth("vaultunlocked", "2.17.0") - // TODO add eternaleconomy + downloadPlugins.modrinth("essentialsx", "2.21.2") } test { diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index 76d7494d..3bec8b3c 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -124,7 +124,9 @@ public void onEnable() { noticeService, parcelRepository, parcelContentRepository, - scheduler + scheduler, + config, + this.economy ); UserValidationService userValidationService = new UserValidator(); diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java index d54fd677..21de780a 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java @@ -78,6 +78,7 @@ public CompletableFuture countByDestinationLocker(UUID destinationLocke long count = dao.queryBuilder() .where() .eq(DESTINATION_LOCKER_COLUMN, destinationLocker) + .and() .eq("status", ParcelStatus.DELIVERED) .countOf(); return (int) count; From aad43f6947201735e392d7a581572fbccc597f04 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Fri, 12 Dec 2025 15:48:06 +0100 Subject: [PATCH 4/5] Add null checks to PlaceholderUtil --- .../parcellockers/parcel/util/PlaceholderUtil.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/util/PlaceholderUtil.java b/src/main/java/com/eternalcode/parcellockers/parcel/util/PlaceholderUtil.java index 802df830..a152c8d5 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/util/PlaceholderUtil.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/util/PlaceholderUtil.java @@ -14,7 +14,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import org.apache.commons.lang3.StringUtils; -import org.jetbrains.annotations.Blocking; public class PlaceholderUtil { @@ -37,11 +36,11 @@ public static CompletableFuture> replaceParcelPlaceholdersAsync( (senderName, receiverName, lockerOptional) -> { Formatter formatter = new Formatter() - .register("{UUID}", parcel.uuid().toString()) - .register("{NAME}", parcel.name()) + .register("{UUID}", parcel.uuid() != null ? parcel.uuid().toString() : "-") + .register("{NAME}", parcel.name() != null ? parcel.name() : "-") .register("{SENDER}", senderName) .register("{RECEIVER}", receiverName) - .register("{SIZE}", StringUtils.capitalize(parcel.size().toString().toLowerCase())) + .register("{SIZE}", parcel.size() != null ? StringUtils.capitalize(parcel.size().toString().toLowerCase()) : "-") .register("{PRIORITY}", parcel.priority() ? "&aYes" : "&cNo") .register("{DESCRIPTION}", parcel.description() != null ? parcel.description() : "-"); From fe8854db3fd6bc6dcd5b9281c32ff71c8ad7d55f Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Sat, 13 Dec 2025 13:45:32 +0100 Subject: [PATCH 5/5] Implement proper CF success handling --- .../com/eternalcode/parcellockers/gui/GuiManager.java | 9 +++++++-- .../eternalcode/parcellockers/parcel/ParcelService.java | 2 +- .../parcellockers/parcel/ParcelServiceImpl.java | 7 ++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/gui/GuiManager.java b/src/main/java/com/eternalcode/parcellockers/gui/GuiManager.java index ddc49245..d43caf28 100644 --- a/src/main/java/com/eternalcode/parcellockers/gui/GuiManager.java +++ b/src/main/java/com/eternalcode/parcellockers/gui/GuiManager.java @@ -71,8 +71,13 @@ public void sendParcel(Player sender, Parcel parcel, List items) { : this.config.settings.parcelSendDuration; this.parcelService.send(sender, parcel, items) - .thenAccept(v -> this.deliveryManager.create(parcel.uuid(), Instant.now().plus(delay))) - .thenRun(() -> { + .thenAccept(success -> { + if (!success) { + return; + } + + this.deliveryManager.create(parcel.uuid(), Instant.now().plus(delay)); + ParcelSendTask task = new ParcelSendTask( parcel, this.parcelService, diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/ParcelService.java b/src/main/java/com/eternalcode/parcellockers/parcel/ParcelService.java index 5249fb15..2ae52a42 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/ParcelService.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/ParcelService.java @@ -13,7 +13,7 @@ public interface ParcelService { - CompletableFuture send(Player sender, Parcel parcel, List items); + CompletableFuture send(Player sender, Parcel parcel, List items); CompletableFuture update(Parcel parcel); diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/ParcelServiceImpl.java b/src/main/java/com/eternalcode/parcellockers/parcel/ParcelServiceImpl.java index 942e93d3..1a9701d2 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/ParcelServiceImpl.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/ParcelServiceImpl.java @@ -72,7 +72,7 @@ public ParcelServiceImpl( } @Override - public CompletableFuture send(Player sender, Parcel parcel, List items) { + public CompletableFuture send(Player sender, Parcel parcel, List items) { if (!sender.hasPermission(PARCEL_FEE_BYPASS_PERMISSION)) { double fee = switch (parcel.size()) { case SMALL -> this.config.settings.smallParcelFee; @@ -88,7 +88,7 @@ public CompletableFuture send(Player sender, Parcel parcel, List send(Player sender, Parcel parcel, List { + return this.parcelRepository.save(parcel).handle((unused, throwable) -> { if (throwable != null) { this.noticeService.create() .notice(messages -> messages.parcel.cannotSend) @@ -113,6 +113,7 @@ public CompletableFuture send(Player sender, Parcel parcel, List messages.parcel.sent) .player(sender.getUniqueId()) .send(); + return true; }); }