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() { override fun enable() {
ShopMenu.registerItem(18, FireballItem( ShopMenu.registerItem(22, FireballItem(
ItemBuilder(Material.FIRE_CHARGE).displayName(SafeMiniMessage.mmDeserialize("<!italic><red>Fireball")).build(), ItemBuilder(Material.FIRE_CHARGE).displayName(SafeMiniMessage.mmDeserialize("<!italic><red>Fireball")).build(),
getConfig().getDouble("shop.prices.fireball", 0.0) getConfig().getDouble("shop.prices.fireball", 0.0)
)) ))

View File

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

View File

@ -1,5 +1,7 @@
package dev.plex.listener package dev.plex.listener
import dev.plex.cache.DataUtils
import dev.plex.shop.ShopMenu
import dev.plex.util.minimessage.SafeMiniMessage import dev.plex.util.minimessage.SafeMiniMessage
import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component
import org.bukkit.event.EventHandler import org.bukkit.event.EventHandler
@ -17,7 +19,11 @@ class ShopListener : PlexListener()
return return
} }
event.isCancelled = true 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 package dev.plex.shop
import com.google.common.collect.Lists
import com.google.common.collect.Maps import com.google.common.collect.Maps
import dev.plex.Plex
import dev.plex.ShopModule
import dev.plex.player.PlexPlayer import dev.plex.player.PlexPlayer
import dev.plex.shop.item.AbstractItem import dev.plex.shop.item.AbstractItem
import dev.plex.util.item.ItemBuilder import dev.plex.util.item.ItemBuilder
import dev.plex.util.minimessage.SafeMiniMessage 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.Bukkit
import org.bukkit.Material import org.bukkit.Material
import org.bukkit.NamespacedKey
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.inventory.Inventory import org.bukkit.inventory.Inventory
import org.bukkit.inventory.meta.ItemMeta
import org.bukkit.persistence.PersistentDataContainer
import org.bukkit.persistence.PersistentDataType
/** /**
* @author Taah * @author Taah
@ -23,17 +32,26 @@ class ShopMenu
val ITEMS: HashMap<Int, AbstractItem> = Maps.newHashMap() val ITEMS: HashMap<Int, AbstractItem> = Maps.newHashMap()
fun registerItem(index: Int, item: AbstractItem) 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) fun open(plexPlayer: PlexPlayer)
{ {
val player: Player? = plexPlayer.player val player: Player? = plexPlayer.player
val inventory: Inventory = constructInventory() val inventory: Inventory = constructInventory(plexPlayer)
player?.openInventory(inventory) player?.openInventory(inventory)
} }
private fun constructInventory(): Inventory private fun constructInventory(plexPlayer: PlexPlayer): Inventory
{ {
val inventory: Inventory = Bukkit.createInventory(null, 54, SafeMiniMessage.mmDeserialize("<gold>Shop")) val inventory: Inventory = Bukkit.createInventory(null, 54, SafeMiniMessage.mmDeserialize("<gold>Shop"))
ITEMS.forEach { (t, u) -> inventory.setItem(t, u.item) } 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(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 return inventory
} }
} }

View File

@ -1,18 +1,67 @@
package dev.plex.shop.item package dev.plex.shop.item
import dev.plex.cache.DataUtils import dev.plex.cache.DataUtils
import dev.plex.listener.PlexListener
import dev.plex.player.PlexPlayer 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.ItemStack
import org.bukkit.inventory.meta.ItemMeta
import org.bukkit.persistence.PersistentDataContainer
import java.util.concurrent.CompletableFuture 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) 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.coins.minus(this.cost);
player.player?.inventory?.addItem(this.item); player.player?.inventory?.addItem(this.item);
CompletableFuture.runAsync { CompletableFuture.runAsync {
DataUtils.update(player); 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 package dev.plex.shop.item.impl
import dev.plex.Plex
import dev.plex.shop.item.AbstractItem 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 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