diff --git a/build.gradle.kts b/build.gradle.kts index 1846a541..3e97e957 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; + } } 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()