Fix currency items disappearing on pick up when inventory is almost full and reorder functions called in onDisable #51

Merged
SKBotNL merged 4 commits from master into master 2026-09-19 16:16:21 -04:00
13 changed files with 367 additions and 50 deletions

No files matched your search

@@ -100,26 +100,7 @@ internal class DiamondBankOG : JavaPlugin() {
this.server.pluginManager.registerEvents(Events(), this)
this.getCommand("deposit")?.setExecutor(Deposit())
this.getCommand("withdraw")?.setExecutor(Withdraw())
this.getCommand("setbankbalance")?.setExecutor(SetBankBalance())
this.getCommand("setbankbal")?.setExecutor(SetBankBalance())
this.getCommand("pay")?.setExecutor(Pay())
this.getCommand("balancetop")?.setExecutor(Balancetop())
this.getCommand("baltop")?.setExecutor(Balancetop())
this.getCommand("balance")?.setExecutor(Balance())
this.getCommand("bal")?.setExecutor(Balance())
this.getCommand("compress")?.setExecutor(Compress())
this.getCommand("autocompress")?.setExecutor(AutoCompress())
this.getCommand("autodeposit")?.setExecutor(AutoDeposit())
this.getCommand("diamondbankreload")?.setExecutor(DiamondBankReload())
this.getCommand("diamondbankhelp")?.setExecutor(DiamondBankHelp())
this.getCommand("enableeconomy")?.setExecutor(EnableEconomy())
this.getCommand("disableeconomy")?.setExecutor(DisableEconomy())
this.getCommand("dbogtoggledebug")?.setExecutor(ToggleDebug())
setUpCommands()
Shard.createCraftingRecipes()
@@ -140,7 +121,34 @@ internal class DiamondBankOG : JavaPlugin() {
)
}
fun setUpCommands() {
this.getCommand("deposit")?.setExecutor(Deposit())
this.getCommand("withdraw")?.setExecutor(Withdraw())
this.getCommand("setbankbalance")?.setExecutor(SetBankBalance())
this.getCommand("setbankbal")?.setExecutor(SetBankBalance())
this.getCommand("pay")?.setExecutor(Pay())
this.getCommand("balancetop")?.setExecutor(Balancetop())
this.getCommand("baltop")?.setExecutor(Balancetop())
this.getCommand("balance")?.setExecutor(Balance())
this.getCommand("bal")?.setExecutor(Balance())
this.getCommand("compress")?.setExecutor(Compress())
this.getCommand("autocompress")?.setExecutor(AutoCompress())
this.getCommand("autodeposit")?.setExecutor(AutoDeposit())
this.getCommand("diamondbankreload")?.setExecutor(DiamondBankReload())
this.getCommand("diamondbankhelp")?.setExecutor(DiamondBankHelp())
this.getCommand("enableeconomy")?.setExecutor(EnableEconomy())
this.getCommand("disableeconomy")?.setExecutor(DisableEconomy())
this.getCommand("dbogtoggledebug")?.setExecutor(ToggleDebug())
}
override fun onDisable() {
scope.cancel()
runBlocking { scope.coroutineContext[Job]?.join() }
if (isRedisInitialized()) {
redis.shutdown()
}
@@ -149,10 +157,6 @@ internal class DiamondBankOG : JavaPlugin() {
balanceManager.shutdown()
}
scope.cancel()
runBlocking { scope.coroutineContext[Job]?.join() }
transactionLock.removeAllLocks()
}
}
@@ -145,7 +145,7 @@ internal class Events : Listener {
}
}
@EventHandler(priority = EventPriority.HIGHEST)
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
fun onEntityPickupItem(event: EntityPickupItemEvent) {
val player = event.entity as? Player ?: return
val worldName = player.world.name
@@ -178,7 +178,7 @@ internal class Events : Listener {
}
if (redis.getValue("diamondbankog:${player.uniqueId}:autodeposit") == "true") {
deposit(player, event.item)
deposit(player, event.item, event.remaining)
}
scope.launch {
@@ -197,7 +197,7 @@ internal class Events : Listener {
}
}
@EventHandler(priority = EventPriority.HIGHEST)
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
fun onPlayerDropItem(event: PlayerDropItemEvent) {
val worldName = event.player.world.name
if (!vanillaWorlds.contains(worldName)) return
@@ -239,7 +239,7 @@ internal class Events : Listener {
}
}
@EventHandler(priority = EventPriority.HIGHEST)
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
fun onInventoryClickEvent(event: InventoryClickEvent) {
val player = event.whoClicked as? Player ?: return
val worldName = player.world.name
@@ -317,7 +317,7 @@ internal class Events : Listener {
}
}
@EventHandler(priority = EventPriority.HIGHEST)
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
fun onPlayerInteractEntity(event: PlayerInteractEntityEvent) {
val player = event.player
val worldName = player.world.name
@@ -13,7 +13,7 @@ import org.bukkit.entity.Item
import org.bukkit.entity.Player
internal object AutoDeposit {
fun deposit(player: Player, item: Item) {
fun deposit(player: Player, item: Item, remaining: Int) {
val worldName = player.world.name
if (worldName != "world" && worldName != "world_nether" && worldName != "world_the_end") {
return
@@ -24,7 +24,7 @@ internal object AutoDeposit {
return
}
val itemStack = item.itemStack
val itemStack = item.itemStack.clone().apply { amount += remaining }
val shards =
if (itemStack.type == Material.DIAMOND_BLOCK) {
(itemStack.amount * 9 * 9).toLong()
@@ -1,12 +1,12 @@
package net.trueog.diamondbankog.balance.command
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import net.kyori.adventure.text.minimessage.MiniMessage
import net.trueog.diamondbankog.DiamondBankOG
import net.trueog.diamondbankog.DiamondBankOG.Companion.balanceManager
import net.trueog.diamondbankog.DiamondBankOG.Companion.config
import net.trueog.diamondbankog.DiamondBankOG.Companion.economyDisabled
import net.trueog.diamondbankog.DiamondBankOG.Companion.mm
import net.trueog.diamondbankog.DiamondBankOG.Companion.scope
import net.trueog.diamondbankog.balance.BalanceManager
import net.trueog.diamondbankog.config.Config
import net.trueog.diamondbankog.transaction.CommonOperations
import net.trueog.diamondbankog.util.PlayerPrefix.getPrefix
import org.bukkit.command.Command
@@ -14,7 +14,12 @@ import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
internal class Balance : CommandExecutor {
internal class Balance(
val config: Config = DiamondBankOG.config,
val balanceManager: BalanceManager = DiamondBankOG.balanceManager,
val mm: MiniMessage = DiamondBankOG.mm,
val scope: CoroutineScope = DiamondBankOG.scope,
) : CommandExecutor {
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>?): Boolean {
scope.launch {
if (economyDisabled) {
@@ -1,13 +1,13 @@
package net.trueog.diamondbankog.balance.command
import kotlin.math.ceil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import net.kyori.adventure.text.minimessage.MiniMessage
import net.trueog.diamondbankog.DiamondBankOG
import net.trueog.diamondbankog.DiamondBankOG.Companion.balanceManager
import net.trueog.diamondbankog.DiamondBankOG.Companion.config
import net.trueog.diamondbankog.DiamondBankOG.Companion.economyDisabled
import net.trueog.diamondbankog.DiamondBankOG.Companion.mm
import net.trueog.diamondbankog.DiamondBankOG.Companion.scope
import net.trueog.diamondbankog.balance.BalanceManager
import net.trueog.diamondbankog.config.Config
import net.trueog.diamondbankog.transaction.CommonOperations
import net.trueog.diamondbankog.util.PlayerPrefix.getPrefix
import org.bukkit.Bukkit
@@ -16,7 +16,12 @@ import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
internal class Balancetop : CommandExecutor {
internal class Balancetop(
val config: Config = DiamondBankOG.config,
val balanceManager: BalanceManager = DiamondBankOG.balanceManager,
val mm: MiniMessage = DiamondBankOG.mm,
val scope: CoroutineScope = DiamondBankOG.scope,
) : CommandExecutor {
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>?): Boolean {
scope.launch {
if (economyDisabled) {
@@ -1,13 +1,13 @@
package net.trueog.diamondbankog.balance.command
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import net.kyori.adventure.text.minimessage.MiniMessage
import net.trueog.diamondbankog.DiamondBankOG
import net.trueog.diamondbankog.DiamondBankOG.Companion.balanceManager
import net.trueog.diamondbankog.DiamondBankOG.Companion.config
import net.trueog.diamondbankog.DiamondBankOG.Companion.economyDisabled
import net.trueog.diamondbankog.DiamondBankOG.Companion.mm
import net.trueog.diamondbankog.DiamondBankOG.Companion.scope
import net.trueog.diamondbankog.balance.BalanceManager
import net.trueog.diamondbankog.balance.shard.ShardType
import net.trueog.diamondbankog.config.Config
import net.trueog.diamondbankog.transaction.CommonOperations
import net.trueog.diamondbankog.util.ErrorHandler.handleError
import net.trueog.diamondbankog.util.PlayerPrefix.getPrefix
@@ -16,7 +16,12 @@ import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
internal class SetBankBalance : CommandExecutor {
internal class SetBankBalance(
val config: Config = DiamondBankOG.config,
val balanceManager: BalanceManager = DiamondBankOG.balanceManager,
val mm: MiniMessage = DiamondBankOG.mm,
val scope: CoroutineScope = DiamondBankOG.scope,
) : CommandExecutor {
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>?): Boolean {
scope.launch {
if (economyDisabled) {
@@ -0,0 +1,98 @@
package net.trueog.diamondbankog.commands
import io.mockk.MockKAnnotations
import io.mockk.Runs
import io.mockk.confirmVerified
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.just
import io.mockk.slot
import io.mockk.verify
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.test.runTest
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.minimessage.MiniMessage
import net.trueog.diamondbankog.BukkitMock
import net.trueog.diamondbankog.Constants.playerUuid
import net.trueog.diamondbankog.Utils.waitForCoroutines
import net.trueog.diamondbankog.balance.BalanceManager
import net.trueog.diamondbankog.balance.command.Balance
import net.trueog.diamondbankog.config.Config
import org.bukkit.Bukkit
import org.bukkit.Server
import org.bukkit.command.Command
import org.bukkit.entity.Player
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertAll
class BalanceTest {
@MockK private lateinit var config: Config
@MockK private lateinit var balanceManager: BalanceManager
@MockK private lateinit var mm: MiniMessage
@MockK private lateinit var player: Player
@MockK private lateinit var command: Command
val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
@BeforeEach
fun setup() {
MockKAnnotations.init(this)
every { config.prefix } returns "DiamondBank-OG"
val inputSlot = slot<String>()
every { mm.deserialize(capture(inputSlot)) } answers { Component.text(inputSlot.captured) }
every { player.uniqueId } returns playerUuid
every { player.world.name } returns "world"
every { player.hasPermission("diamondbank-og.balance") } returns true
every { Bukkit.getPlayer("player") } returns player
every { server.getPlayer("player") } returns player
every { Bukkit.getPlayer(playerUuid) } returns player
every { server.getPlayer(playerUuid) } returns player
every { player.sendMessage(any<Component>()) } just Runs
}
companion object {
lateinit var server: Server
@JvmStatic
@BeforeAll
fun setupBukkit() {
server = BukkitMock.mockBukkit()
}
}
@Test
@DisplayName("Balance with no permission should fail")
fun balanceNoPermission() = runTest {
every { player.hasPermission("diamondbank-og.balance") } returns false
val balance = Balance(config, balanceManager, mm, scope)
balance.onCommand(player, command, "balance", arrayOf())
waitForCoroutines(scope)
assertAll(
{ verify { player.hasPermission("diamondbank-og.balance") } },
{
verify {
player.sendMessage(
Component.text("DiamondBank-OG<reset>: <red>You do not have permission to use this command.")
)
}
},
{ confirmVerified(player) },
)
}
}
@@ -0,0 +1,98 @@
package net.trueog.diamondbankog.commands
import io.mockk.MockKAnnotations
import io.mockk.Runs
import io.mockk.confirmVerified
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.just
import io.mockk.slot
import io.mockk.verify
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.test.runTest
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.minimessage.MiniMessage
import net.trueog.diamondbankog.BukkitMock
import net.trueog.diamondbankog.Constants.playerUuid
import net.trueog.diamondbankog.Utils.waitForCoroutines
import net.trueog.diamondbankog.balance.BalanceManager
import net.trueog.diamondbankog.balance.command.Balancetop
import net.trueog.diamondbankog.config.Config
import org.bukkit.Bukkit
import org.bukkit.Server
import org.bukkit.command.Command
import org.bukkit.entity.Player
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertAll
class BalancetopTest {
@MockK private lateinit var config: Config
@MockK private lateinit var balanceManager: BalanceManager
@MockK private lateinit var mm: MiniMessage
@MockK private lateinit var player: Player
@MockK private lateinit var command: Command
val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
@BeforeEach
fun setup() {
MockKAnnotations.init(this)
every { config.prefix } returns "DiamondBank-OG"
val inputSlot = slot<String>()
every { mm.deserialize(capture(inputSlot)) } answers { Component.text(inputSlot.captured) }
every { player.uniqueId } returns playerUuid
every { player.world.name } returns "world"
every { player.hasPermission("diamondbank-og.balance") } returns true
every { Bukkit.getPlayer("player") } returns player
every { server.getPlayer("player") } returns player
every { Bukkit.getPlayer(playerUuid) } returns player
every { server.getPlayer(playerUuid) } returns player
every { player.sendMessage(any<Component>()) } just Runs
}
companion object {
lateinit var server: Server
@JvmStatic
@BeforeAll
fun setupBukkit() {
server = BukkitMock.mockBukkit()
}
}
@Test
@DisplayName("Balancetop with no permission should fail")
fun balancetopNoPermission() = runTest {
every { player.hasPermission("diamondbank-og.balancetop") } returns false
val balancetop = Balancetop(config, balanceManager, mm, scope)
balancetop.onCommand(player, command, "balancetop", arrayOf())
waitForCoroutines(scope)
assertAll(
{ verify { player.hasPermission("diamondbank-og.balancetop") } },
{
verify {
player.sendMessage(
Component.text("DiamondBank-OG<reset>: <red>You do not have permission to use this command.")
)
}
},
{ confirmVerified(player) },
)
}
}
@@ -1,4 +1,4 @@
package net.trueog.diamondbankog
package net.trueog.diamondbankog.commands
import io.mockk.MockKAnnotations
import io.mockk.Runs
@@ -17,6 +17,7 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.test.runTest
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.minimessage.MiniMessage
import net.trueog.diamondbankog.BukkitMock
import net.trueog.diamondbankog.Constants.playerUuid
import net.trueog.diamondbankog.Utils.mockPlayerInventory
import net.trueog.diamondbankog.Utils.waitForCoroutines
@@ -1,4 +1,4 @@
package net.trueog.diamondbankog
package net.trueog.diamondbankog.commands
import io.mockk.*
import io.mockk.impl.annotations.MockK
@@ -11,6 +11,7 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.test.runTest
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.minimessage.MiniMessage
import net.trueog.diamondbankog.BukkitMock
import net.trueog.diamondbankog.Constants.playerUuid
import net.trueog.diamondbankog.Utils.mockPlayerInventory
import net.trueog.diamondbankog.Utils.waitForCoroutines
@@ -1,4 +1,4 @@
package net.trueog.diamondbankog
package net.trueog.diamondbankog.commands
import io.mockk.*
import io.mockk.impl.annotations.MockK
@@ -15,6 +15,7 @@ import net.kyori.adventure.text.minimessage.MiniMessage
import net.luckperms.api.LuckPerms
import net.luckperms.api.model.user.User
import net.luckperms.api.node.Node
import net.trueog.diamondbankog.BukkitMock
import net.trueog.diamondbankog.Constants.otherPlayerUuid
import net.trueog.diamondbankog.Constants.playerUuid
import net.trueog.diamondbankog.Utils.mockPlayerInventory
@@ -0,0 +1,98 @@
package net.trueog.diamondbankog.commands
import io.mockk.MockKAnnotations
import io.mockk.Runs
import io.mockk.coVerify
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.just
import io.mockk.slot
import io.mockk.verify
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.test.runTest
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.minimessage.MiniMessage
import net.trueog.diamondbankog.BukkitMock
import net.trueog.diamondbankog.Constants.playerUuid
import net.trueog.diamondbankog.Utils.waitForCoroutines
import net.trueog.diamondbankog.balance.BalanceManager
import net.trueog.diamondbankog.balance.command.SetBankBalance
import net.trueog.diamondbankog.config.Config
import org.bukkit.Bukkit
import org.bukkit.Server
import org.bukkit.command.Command
import org.bukkit.entity.Player
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertAll
class SetBankBalanceTest {
@MockK private lateinit var config: Config
@MockK private lateinit var balanceManager: BalanceManager
@MockK private lateinit var mm: MiniMessage
@MockK private lateinit var player: Player
@MockK private lateinit var command: Command
val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
@BeforeEach
fun setup() {
MockKAnnotations.init(this)
every { config.prefix } returns "DiamondBank-OG"
val inputSlot = slot<String>()
every { mm.deserialize(capture(inputSlot)) } answers { Component.text(inputSlot.captured) }
every { player.uniqueId } returns playerUuid
every { player.world.name } returns "world"
every { player.hasPermission("diamondbank-og.setbankbalance") } returns true
every { Bukkit.getPlayer("player") } returns player
every { server.getPlayer("player") } returns player
every { Bukkit.getPlayer(playerUuid) } returns player
every { server.getPlayer(playerUuid) } returns player
every { player.sendMessage(any<Component>()) } just Runs
}
companion object {
lateinit var server: Server
@JvmStatic
@BeforeAll
fun setupBukkit() {
server = BukkitMock.mockBukkit()
}
}
@Test
@DisplayName("SetBankBalance with no permission should fail")
fun setBankBalanceNoPermission() = runTest {
every { player.hasPermission("diamondbank-og.setbankbalance") } returns false
val setBankBalance = SetBankBalance(config, balanceManager, mm, scope)
setBankBalance.onCommand(player, command, "setbankbalance", arrayOf())
waitForCoroutines(scope)
assertAll(
{ verify { player.hasPermission("diamondbank-og.setbankbalance") } },
{
verify {
player.sendMessage(
Component.text("DiamondBank-OG<reset>: <red>You do not have permission to use this command.")
)
}
},
{ coVerify(exactly = 0) { balanceManager.setPlayerShards(any(), any(), any()) } },
)
}
}
@@ -1,4 +1,4 @@
package net.trueog.diamondbankog
package net.trueog.diamondbankog.commands
import io.mockk.*
import io.mockk.impl.annotations.MockK
@@ -11,6 +11,7 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.test.runTest
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.minimessage.MiniMessage
import net.trueog.diamondbankog.BukkitMock
import net.trueog.diamondbankog.Constants.playerUuid
import net.trueog.diamondbankog.Utils.mockPlayerInventory
import net.trueog.diamondbankog.Utils.waitForCoroutines