From dd09597a5274a4b2f383a98262f9474ae77d8437 Mon Sep 17 00:00:00 2001 From: NotAlexNoyle Date: Thu, 21 May 2026 10:03:11 -0400 Subject: [PATCH] Experimental advancements GUI --- .gitmodules | 5 +- build.gradle.kts | 1 + libs/GxUI-OG | 1 + libs/Utilities-OG | 2 +- .../kotlin/net/trueog/questsOG/ClaimQuest.kt | 60 +++++++++++------- .../net/trueog/questsOG/QuestGuiCommand.kt | 62 +++++++++++++++++++ .../kotlin/net/trueog/questsOG/QuestsOG.kt | 14 +++-- .../net/trueog/questsOG/quests/HomesFive.kt | 11 +++- .../net/trueog/questsOG/quests/HomesFour.kt | 11 +++- .../net/trueog/questsOG/quests/HomesSix.kt | 11 +++- .../net/trueog/questsOG/quests/HomesThree.kt | 11 +++- .../net/trueog/questsOG/quests/HomesTwo.kt | 11 +++- src/main/resources/plugin.yml | 3 + 13 files changed, 158 insertions(+), 45 deletions(-) create mode 160000 libs/GxUI-OG create mode 100644 src/main/kotlin/net/trueog/questsOG/QuestGuiCommand.kt diff --git a/.gitmodules b/.gitmodules index beeb198..d665fe2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,4 +3,7 @@ url = https://github.com/true-og/DiamondBank-OG [submodule "libs/Utilities-OG"] path = libs/Utilities-OG - url = https://github.com/true-og/Utilities-OG \ No newline at end of file + url = https://github.com/true-og/Utilities-OG +[submodule "libs/GxUI-OG"] + path = libs/GxUI-OG + url = https://github.com/true-og/GxUI-OG diff --git a/build.gradle.kts b/build.gradle.kts index e690a38..bafeff0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -83,6 +83,7 @@ dependencies { compileOnlyApi(project(":libs:DiamondBank-OG")) { attributes { attribute(kotlinAttribute, true) } } // Import TrueOG network DiamondBank-OG Kotlin API (from source). + implementation(project(":libs:GxUI-OG")) // Shade TrueOG Network GxUI-OG advancement menu API into this plugin. } /* ---------------------- Reproducible jars ---------------------------- */ diff --git a/libs/GxUI-OG b/libs/GxUI-OG new file mode 160000 index 0000000..24b385d --- /dev/null +++ b/libs/GxUI-OG @@ -0,0 +1 @@ +Subproject commit 24b385d3f795f0c74a193a9da3277af00936af59 diff --git a/libs/Utilities-OG b/libs/Utilities-OG index 3e26fb1..9273a40 160000 --- a/libs/Utilities-OG +++ b/libs/Utilities-OG @@ -1 +1 @@ -Subproject commit 3e26fb1a84cd46754a57fc1e67d90fcc82d11ad5 +Subproject commit 9273a4011e699b4c13ab78cd9da96cd89731a128 diff --git a/src/main/kotlin/net/trueog/questsOG/ClaimQuest.kt b/src/main/kotlin/net/trueog/questsOG/ClaimQuest.kt index 629d1cb..1d939bb 100644 --- a/src/main/kotlin/net/trueog/questsOG/ClaimQuest.kt +++ b/src/main/kotlin/net/trueog/questsOG/ClaimQuest.kt @@ -10,44 +10,56 @@ import org.bukkit.entity.Player class ClaimQuest : CommandExecutor { override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array?): Boolean { + QuestsOG.plugin.logger.info("/claimquest invoked by ${sender.name}") if (sender !is Player) { sender.sendMessage("ERROR: You can only execute this command as a player.") return true } val nextQuest = HomesProgression.getNextQuest(sender) + QuestsOG.plugin.logger.info("/claimquest nextQuest=${nextQuest?.javaClass?.simpleName}") if (nextQuest == null) { UtilitiesOG.trueogMessage(sender, "You have completed all available quests.") return true } QuestsOG.scope.launch { - val isEligible = nextQuest.isEligible(sender) - if (isEligible == null) { - UtilitiesOG.trueogMessage( - sender, - "Something went wrong while checking your quest eligibility. Contact an administrator.", - ) - return@launch - } - - if (isEligible) { - val successful = nextQuest.consumeQuestItems(sender) - if (!successful) { - UtilitiesOG.trueogMessage(sender, "Something wrong while trying to consume the quest items.") + try { + QuestsOG.plugin.logger.info("/claimquest coroutine entered for ${sender.name}") + val isEligible = nextQuest.isEligible(sender) + QuestsOG.plugin.logger.info("/claimquest isEligible=$isEligible") + if (isEligible == null) { + UtilitiesOG.trueogMessage( + sender, + "Something went wrong while checking your quest eligibility. Contact an administrator.", + ) return@launch } - nextQuest.reward(sender) - val homeCount = HomesProgression.getHomeCount(nextQuest) - val questName = nextQuest::class.simpleName - UtilitiesOG.logToConsole("[Quests-OG]", "${sender.name} claimed quest $questName") - UtilitiesOG.trueogMessage( - sender, - "Claimed quest! You now have $homeCount homes.", - ) - return@launch - } else { - UtilitiesOG.trueogMessage(sender, "You must meet all the quest's requirements first.") + + if (isEligible) { + val successful = nextQuest.consumeQuestItems(sender) + if (!successful) { + UtilitiesOG.trueogMessage( + sender, + "Something wrong while trying to consume the quest items.", + ) + return@launch + } + nextQuest.reward(sender) + val homeCount = HomesProgression.getHomeCount(nextQuest) + val questName = nextQuest::class.simpleName + UtilitiesOG.logToConsole("[Quests-OG]", "${sender.name} claimed quest $questName") + UtilitiesOG.trueogMessage( + sender, + "Claimed quest! You now have $homeCount homes.", + ) + return@launch + } else { + UtilitiesOG.trueogMessage(sender, "You must meet all the quest's requirements first.") + } + } catch (t: Throwable) { + QuestsOG.plugin.logger.severe("/claimquest failed: ${t.message}") + t.printStackTrace() } } return true diff --git a/src/main/kotlin/net/trueog/questsOG/QuestGuiCommand.kt b/src/main/kotlin/net/trueog/questsOG/QuestGuiCommand.kt new file mode 100644 index 0000000..2588b78 --- /dev/null +++ b/src/main/kotlin/net/trueog/questsOG/QuestGuiCommand.kt @@ -0,0 +1,62 @@ +package net.trueog.questsOG + +import kotlinx.coroutines.launch +import net.trueog.gxui.advancements.AdvancementMenu +import net.trueog.gxui.advancements.AdvancementState +import net.trueog.questsOG.progression.HomesProgression +import net.trueog.questsOG.quests.Quest +import org.bukkit.command.Command +import org.bukkit.command.CommandExecutor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +class QuestGuiCommand : CommandExecutor { + override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array?): Boolean { + QuestsOG.plugin.logger.info("/questgui invoked by ${sender.name}") + if (sender !is Player) { + sender.sendMessage("ERROR: You can only execute this command as a player.") + return true + } + + QuestsOG.scope.launch { + try { + QuestsOG.plugin.logger.info("/questgui coroutine entered for ${sender.name}") + val nextQuest = HomesProgression.getNextQuest(sender) + QuestsOG.plugin.logger.info("/questgui nextQuest=${nextQuest?.javaClass?.simpleName}") + val builder = AdvancementMenu.builder(QuestsOG.plugin, sender, "&6Home Quests") + + HomesProgression.quests.forEach { quest -> + builder.add(questName(quest), stateFor(quest, nextQuest)) + quest.getRequirements(sender)?.forEach { requirement -> + when (requirement) { + is ProgressRequirement -> + builder.progress(requirement.name, requirement.current, requirement.target) + is BooleanRequirement -> builder.bool(requirement.name, requirement.met) + } + } + if (quest == nextQuest) builder.footer("&7Use &e/claimquest &7when ready.") + } + + QuestsOG.plugin.logger.info("/questgui dispatching builder.open on main thread") + MainThreadBlock.runOnMainThread { builder.open(args) } + QuestsOG.plugin.logger.info("/questgui done") + } catch (t: Throwable) { + QuestsOG.plugin.logger.severe("/questgui failed: ${t.message}") + t.printStackTrace() + } + } + + return true + } + + private fun questName(quest: Quest): String = "Home ${HomesProgression.getHomeCount(quest)} Quest" + + private fun stateFor(quest: Quest, nextQuest: Quest?): AdvancementState = + when { + nextQuest == null -> AdvancementState.COMPLETE + quest == nextQuest -> AdvancementState.IN_PROGRESS + HomesProgression.quests.indexOf(quest) < HomesProgression.quests.indexOf(nextQuest) -> + AdvancementState.COMPLETE + else -> AdvancementState.LOCKED + } +} diff --git a/src/main/kotlin/net/trueog/questsOG/QuestsOG.kt b/src/main/kotlin/net/trueog/questsOG/QuestsOG.kt index c843527..3105009 100644 --- a/src/main/kotlin/net/trueog/questsOG/QuestsOG.kt +++ b/src/main/kotlin/net/trueog/questsOG/QuestsOG.kt @@ -6,19 +6,19 @@ import net.kyori.adventure.text.minimessage.MiniMessage import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver import net.kyori.adventure.text.minimessage.tag.standard.StandardTags import net.luckperms.api.LuckPerms -import net.trueog.diamondbankog.api.DiamondBankAPIKotlin +import net.trueog.diamondbankog.api.DiamondBankAPIJava import org.bukkit.Bukkit import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin class QuestsOG : JavaPlugin() { companion object { - val scope = CoroutineScope(Dispatchers.Default + SupervisorJob()) + lateinit var scope: CoroutineScope lateinit var plugin: QuestsOG lateinit var config: Config lateinit var redis: Redis - lateinit var diamondBankAPI: DiamondBankAPIKotlin + lateinit var diamondBankAPI: DiamondBankAPIJava lateinit var luckPerms: LuckPerms lateinit var duels: Duels lateinit var mobHeads: Plugin @@ -32,6 +32,11 @@ class QuestsOG : JavaPlugin() { override fun onEnable() { plugin = this + val exceptionHandler = CoroutineExceptionHandler { _, throwable -> + logger.severe("Uncaught coroutine exception: ${throwable.message}") + throwable.printStackTrace() + } + scope = CoroutineScope(Dispatchers.Default + SupervisorJob() + exceptionHandler) Companion.config = Config.create() @@ -47,7 +52,7 @@ class QuestsOG : JavaPlugin() { return } - val diamondBankAPIProvider = server.servicesManager.getRegistration(DiamondBankAPIKotlin::class.java) + val diamondBankAPIProvider = server.servicesManager.getRegistration(DiamondBankAPIJava::class.java) if (diamondBankAPIProvider == null) { logger.severe("DiamondBank-OG API is null") Bukkit.getPluginManager().disablePlugin(this) @@ -81,6 +86,7 @@ class QuestsOG : JavaPlugin() { this.server.pluginManager.registerEvents(Events(), this) getCommand("claimquest")?.setExecutor(ClaimQuest()) + getCommand("questgui")?.setExecutor(QuestGuiCommand()) } override fun onDisable() { diff --git a/src/main/kotlin/net/trueog/questsOG/quests/HomesFive.kt b/src/main/kotlin/net/trueog/questsOG/quests/HomesFive.kt index 3df4388..33733b2 100644 --- a/src/main/kotlin/net/trueog/questsOG/quests/HomesFive.kt +++ b/src/main/kotlin/net/trueog/questsOG/quests/HomesFive.kt @@ -1,6 +1,7 @@ package net.trueog.questsOG.quests import net.luckperms.api.node.types.PermissionNode +import net.trueog.diamondbankog.DiamondBankException import net.trueog.questsOG.BooleanRequirement import net.trueog.questsOG.MainThreadBlock.runOnMainThread import net.trueog.questsOG.ProgressRequirement @@ -54,7 +55,9 @@ class HomesFive : Quest { private suspend fun fetchRequirements(player: Player): Requirements? { val totalShards = - QuestsOG.diamondBankAPI.getTotalShards(player.uniqueId).getOrElse { + try { + QuestsOG.diamondBankAPI.getTotalShards(player.uniqueId) + } catch (e: DiamondBankException) { return null } @@ -138,14 +141,16 @@ class HomesFive : Quest { override suspend fun consumeQuestItems(player: Player): Boolean { val requiredShards = 2500L * 9 - val withdrawResult = + try { QuestsOG.diamondBankAPI.consumeFromPlayer( player.uniqueId, requiredShards, "Home five quest claimed by ${player.name} (${player.uniqueId})", "Quests-OG /claimquest", ) - if (withdrawResult.isFailure) return false + } catch (e: DiamondBankException) { + return false + } runOnMainThread { player.level -= 200 } diff --git a/src/main/kotlin/net/trueog/questsOG/quests/HomesFour.kt b/src/main/kotlin/net/trueog/questsOG/quests/HomesFour.kt index 19ed5ff..1e31d04 100644 --- a/src/main/kotlin/net/trueog/questsOG/quests/HomesFour.kt +++ b/src/main/kotlin/net/trueog/questsOG/quests/HomesFour.kt @@ -1,6 +1,7 @@ package net.trueog.questsOG.quests import net.luckperms.api.node.types.PermissionNode +import net.trueog.diamondbankog.DiamondBankException import net.trueog.questsOG.BooleanRequirement import net.trueog.questsOG.MainThreadBlock.runOnMainThread import net.trueog.questsOG.ProgressRequirement @@ -33,7 +34,9 @@ class HomesFour : Quest { private suspend fun fetchRequirements(player: Player): Requirements? { val totalShards = - QuestsOG.diamondBankAPI.getTotalShards(player.uniqueId).getOrElse { + try { + QuestsOG.diamondBankAPI.getTotalShards(player.uniqueId) + } catch (e: DiamondBankException) { return null } @@ -107,14 +110,16 @@ class HomesFour : Quest { override suspend fun consumeQuestItems(player: Player): Boolean { val requiredShards = 1000L * 9 - val withdrawResult = + try { QuestsOG.diamondBankAPI.consumeFromPlayer( player.uniqueId, requiredShards, "Home four quest claimed by ${player.name} (${player.uniqueId})", "Quests-OG /claimquest", ) - if (withdrawResult.isFailure) return false + } catch (e: DiamondBankException) { + return false + } runOnMainThread { player.level -= 150 } diff --git a/src/main/kotlin/net/trueog/questsOG/quests/HomesSix.kt b/src/main/kotlin/net/trueog/questsOG/quests/HomesSix.kt index f1fa056..529fc48 100644 --- a/src/main/kotlin/net/trueog/questsOG/quests/HomesSix.kt +++ b/src/main/kotlin/net/trueog/questsOG/quests/HomesSix.kt @@ -1,6 +1,7 @@ package net.trueog.questsOG.quests import net.luckperms.api.node.types.PermissionNode +import net.trueog.diamondbankog.DiamondBankException import net.trueog.questsOG.MainThreadBlock.runOnMainThread import net.trueog.questsOG.ProgressRequirement import net.trueog.questsOG.QuestsOG @@ -46,7 +47,9 @@ class HomesSix : Quest { private suspend fun fetchRequirements(player: Player): Requirements? { val totalShards = - QuestsOG.diamondBankAPI.getTotalShards(player.uniqueId).getOrElse { + try { + QuestsOG.diamondBankAPI.getTotalShards(player.uniqueId) + } catch (e: DiamondBankException) { return null } @@ -116,14 +119,16 @@ class HomesSix : Quest { override suspend fun consumeQuestItems(player: Player): Boolean { val requiredShards = 5000L * 9 - val withdrawResult = + try { QuestsOG.diamondBankAPI.consumeFromPlayer( player.uniqueId, requiredShards, "Home six quest claimed by ${player.name} (${player.uniqueId})", "Quests-OG /claimquest", ) - if (withdrawResult.isFailure) return false + } catch (e: DiamondBankException) { + return false + } return runOnMainThread { player.level -= 250 diff --git a/src/main/kotlin/net/trueog/questsOG/quests/HomesThree.kt b/src/main/kotlin/net/trueog/questsOG/quests/HomesThree.kt index 4bb1e2b..45f6c5e 100644 --- a/src/main/kotlin/net/trueog/questsOG/quests/HomesThree.kt +++ b/src/main/kotlin/net/trueog/questsOG/quests/HomesThree.kt @@ -1,6 +1,7 @@ package net.trueog.questsOG.quests import net.luckperms.api.node.types.PermissionNode +import net.trueog.diamondbankog.DiamondBankException import net.trueog.questsOG.BooleanRequirement import net.trueog.questsOG.MainThreadBlock.runOnMainThread import net.trueog.questsOG.ProgressRequirement @@ -27,7 +28,9 @@ class HomesThree : Quest { private suspend fun fetchRequirements(player: Player): Requirements? { val totalShards = - QuestsOG.diamondBankAPI.getTotalShards(player.uniqueId).getOrElse { + try { + QuestsOG.diamondBankAPI.getTotalShards(player.uniqueId) + } catch (e: DiamondBankException) { return null } @@ -85,14 +88,16 @@ class HomesThree : Quest { override suspend fun consumeQuestItems(player: Player): Boolean { val requiredShards = 250L * 9 - val withdrawResult = + try { QuestsOG.diamondBankAPI.consumeFromPlayer( player.uniqueId, requiredShards, "Home three quest claimed by ${player.name} (${player.uniqueId})", "Quests-OG /claimquest", ) - if (withdrawResult.isFailure) return false + } catch (e: DiamondBankException) { + return false + } runOnMainThread { player.level -= 100 } diff --git a/src/main/kotlin/net/trueog/questsOG/quests/HomesTwo.kt b/src/main/kotlin/net/trueog/questsOG/quests/HomesTwo.kt index 39ab7c8..649df1a 100644 --- a/src/main/kotlin/net/trueog/questsOG/quests/HomesTwo.kt +++ b/src/main/kotlin/net/trueog/questsOG/quests/HomesTwo.kt @@ -1,6 +1,7 @@ package net.trueog.questsOG.quests import net.luckperms.api.node.types.PermissionNode +import net.trueog.diamondbankog.DiamondBankException import net.trueog.questsOG.MainThreadBlock.runOnMainThread import net.trueog.questsOG.ProgressRequirement import net.trueog.questsOG.QuestsOG @@ -19,7 +20,9 @@ class HomesTwo : Quest { private suspend fun fetchRequirements(player: Player): Requirements? { val totalShards = - QuestsOG.diamondBankAPI.getTotalShards(player.uniqueId).getOrElse { + try { + QuestsOG.diamondBankAPI.getTotalShards(player.uniqueId) + } catch (e: DiamondBankException) { return null } @@ -74,14 +77,16 @@ class HomesTwo : Quest { override suspend fun consumeQuestItems(player: Player): Boolean { val requiredShards = 100L * 9 - val withdrawResult = + try { QuestsOG.diamondBankAPI.consumeFromPlayer( player.uniqueId, requiredShards, "Home two quest claimed by ${player.name} (${player.uniqueId})", "Quests-OG /claimquest", ) - if (withdrawResult.isFailure) return false + } catch (e: DiamondBankException) { + return false + } runOnMainThread { player.level -= 100 } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index d0b99b3..2c1e220 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -10,3 +10,6 @@ commands: claimquest: description: Claims a quest, duh usage: /claimquest + questgui: + description: Open the homes quest menu. Optional page argument (e.g. /questgui 2). + usage: /questgui [page]