add checks in order to make sure negative coins don't occur

add configurable price
use persistent data containers to keep track of items
This commit is contained in:
taah 2022-06-18 01:19:24 -07:00
parent c4743c97cb
commit fb09c7a906
7 changed files with 97 additions and 7 deletions

View File

@ -30,7 +30,7 @@ class ShopModule : PlexModule() {
}
override fun enable() {
ShopMenu.registerItem(18, FireballItem(
ShopMenu.registerItem(22, FireballItem(
ItemBuilder(Material.FIRE_CHARGE).displayName(SafeMiniMessage.mmDeserialize("<!italic><red>Fireball")).build(),
getConfig().getDouble("shop.prices.fireball", 0.0)
))

View File

@ -1,5 +1,6 @@
package dev.plex.commands
import dev.plex.ShopModule
import dev.plex.cache.DataUtils
import dev.plex.command.PlexCommand
import dev.plex.command.annotation.CommandParameters

View File

@ -1,5 +1,7 @@
package dev.plex.listener
import dev.plex.cache.DataUtils
import dev.plex.shop.ShopMenu
import dev.plex.util.minimessage.SafeMiniMessage
import net.kyori.adventure.text.Component
import org.bukkit.event.EventHandler
@ -17,7 +19,11 @@ class ShopListener : PlexListener()
return
}
event.isCancelled = true
if (!ShopMenu.ITEMS.containsKey(event.slot))
{
return
}
ShopMenu.ITEMS[event.slot]!!.purchase(DataUtils.getPlayer(event.whoClicked.uniqueId))
}
}

View File

@ -1,14 +1,23 @@
package dev.plex.shop
import com.google.common.collect.Lists
import com.google.common.collect.Maps
import dev.plex.Plex
import dev.plex.ShopModule
import dev.plex.player.PlexPlayer
import dev.plex.shop.item.AbstractItem
import dev.plex.util.item.ItemBuilder
import dev.plex.util.minimessage.SafeMiniMessage
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.minimessage.MiniMessage
import org.bukkit.Bukkit
import org.bukkit.Material
import org.bukkit.NamespacedKey
import org.bukkit.entity.Player
import org.bukkit.inventory.Inventory
import org.bukkit.inventory.meta.ItemMeta
import org.bukkit.persistence.PersistentDataContainer
import org.bukkit.persistence.PersistentDataType
/**
* @author Taah
@ -23,17 +32,26 @@ class ShopMenu
val ITEMS: HashMap<Int, AbstractItem> = Maps.newHashMap()
fun registerItem(index: Int, item: AbstractItem)
{
ITEMS.put(index, item);
val meta: ItemMeta = item.item.itemMeta
val dataContainer: PersistentDataContainer = meta.persistentDataContainer
dataContainer.set(item.itemTag, PersistentDataType.STRING, item.itemTag.key)
val lore = meta.lore() ?: Lists.newArrayList()
lore.add(Component.empty())
lore.add(MiniMessage.miniMessage().deserialize("<!italic><gold>Price: ${item.cost}"))
meta.lore(lore)
item.item.itemMeta = meta
ITEMS[index] = item;
ShopModule.get().registerListener(item)
}
fun open(plexPlayer: PlexPlayer)
{
val player: Player? = plexPlayer.player
val inventory: Inventory = constructInventory()
val inventory: Inventory = constructInventory(plexPlayer)
player?.openInventory(inventory)
}
private fun constructInventory(): Inventory
private fun constructInventory(plexPlayer: PlexPlayer): Inventory
{
val inventory: Inventory = Bukkit.createInventory(null, 54, SafeMiniMessage.mmDeserialize("<gold>Shop"))
ITEMS.forEach { (t, u) -> inventory.setItem(t, u.item) }
@ -44,6 +62,7 @@ class ShopMenu
inventory.setItem(i, ItemBuilder(Material.GRAY_STAINED_GLASS_PANE).displayName(SafeMiniMessage.mmDeserialize("<!italic> ")).build())
}
}
inventory.setItem(53, ItemBuilder(Material.SUNFLOWER).displayName(SafeMiniMessage.mmDeserialize("<!italic>${plexPlayer.coins} Coins")).build())
return inventory
}
}

View File

@ -1,18 +1,67 @@
package dev.plex.shop.item
import dev.plex.cache.DataUtils
import dev.plex.listener.PlexListener
import dev.plex.player.PlexPlayer
import dev.plex.util.PlexLog
import dev.plex.util.minimessage.SafeMiniMessage
import org.bukkit.Material
import org.bukkit.NamespacedKey
import org.bukkit.event.EventHandler
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.inventory.EquipmentSlot
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta
import org.bukkit.persistence.PersistentDataContainer
import java.util.concurrent.CompletableFuture
abstract class AbstractItem(val item: ItemStack, private val cost: Double)
abstract class AbstractItem(val item: ItemStack, val cost: Double, val itemTag: NamespacedKey) : PlexListener()
{
fun purchase(player: PlexPlayer)
{
if (player.coins < this.cost) {
player.player?.sendMessage(SafeMiniMessage.mmDeserialize("<red>You need ${this.cost - player.coins} more coins to purchase this!"))
return
}
if (player.player?.inventory!!.filter { it?.type != Material.AIR }.size == 53)
{
player.player?.sendMessage(SafeMiniMessage.mmDeserialize("<red>Your inventory is currently full!"))
return
}
player.coins.minus(this.cost);
player.player?.inventory?.addItem(this.item);
CompletableFuture.runAsync {
DataUtils.update(player);
}
}
abstract fun interact(event: PlayerInteractEvent)
@EventHandler
fun onInteract(event: PlayerInteractEvent)
{
if (event.hand != EquipmentSlot.HAND)
{
return
}
if (event.item == null)
{
return
}
if (!event.item!!.hasItemMeta())
{
return
}
val meta: ItemMeta = event.item!!.itemMeta
val dataContainer: PersistentDataContainer = meta.persistentDataContainer
if (!dataContainer.has(itemTag))
{
return
}
interact(event)
}
}

View File

@ -1,8 +1,20 @@
package dev.plex.shop.item.impl
import dev.plex.Plex
import dev.plex.shop.item.AbstractItem
import org.bukkit.NamespacedKey
import org.bukkit.entity.Fireball
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.inventory.ItemStack
class FireballItem(item: ItemStack, cost: Double) : AbstractItem(item, cost)
class FireballItem(item: ItemStack, cost: Double) : AbstractItem(item, cost, ITEM_TAG)
{
companion object {
val ITEM_TAG: NamespacedKey = NamespacedKey(Plex.get(), "fireball_item")
}
override fun interact(event: PlayerInteractEvent)
{
event.player.launchProjectile(Fireball::class.java)
}
}

View File

@ -0,0 +1,3 @@
shop:
prices:
fireball: 16