Skip to content

Commit

Permalink
upgrade shop.
Browse files Browse the repository at this point in the history
  • Loading branch information
toxicity188 committed Nov 13, 2023
1 parent 84c8b11 commit 6bc2a8d
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,7 @@ object DialogManager: QuestAdderManager {
}
}


exampleMap.forEach {
val file = File(File(adder.dataFolder, it.key).apply {
mkdir()
Expand All @@ -612,6 +613,9 @@ object DialogManager: QuestAdderManager {
actionMap.values.forEach {
it.unregister()
}
shopMap.values.forEach {
it.cancel()
}

qnaMap.clear()
actionMap.clear()
Expand Down Expand Up @@ -664,6 +668,7 @@ object DialogManager: QuestAdderManager {
send("${qnaMap.size} of QnAs has successfully loaded.")
send("${questNpcMap.size} of NPCs has successfully loaded.")
send("${senderMap.size} of senders has successfully loaded.")
send("${shopMap.size} of shops has successfully loaded.")
}
val iterator = selectedQuestMap.iterator()
while (iterator.hasNext()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@ import kor.toxicity.questadder.extension.*
import kor.toxicity.questadder.manager.DialogManager
import kor.toxicity.questadder.manager.ItemManager
import kor.toxicity.questadder.mechanic.dialog.Dialog
import kor.toxicity.questadder.shop.equation.ShopEquation
import org.bukkit.configuration.ConfigurationSection
import org.bukkit.inventory.ItemStack

data class ShopItemBlueprint(
val stock: Long,
val global: Boolean,
val regenTime: Long,
val tick: Long,
val tickChance: Double,
val builder: () -> ItemStack,

val buyPrice: ShopPrice,
val sellPrice: ShopPrice
) {
companion object {
private val emptyPrice = ShopPrice(-1, emptyList())
private val emptyPrice = ShopPrice(-1, ShopEquation.defaultEquation, emptyList())
private fun buildItem(section: ConfigurationSection) = (section.findString("Item","item") ?: throw RuntimeException("item value not found!")).let {
ItemManager.getItemSupplier(it)?.let { supplier ->
val i = supplier.get()
Expand All @@ -41,6 +45,9 @@ data class ShopItemBlueprint(
constructor(adder: QuestAdderBukkit, section: ConfigurationSection): this(
section.findLong(-1,"stock"),
section.findBoolean("Global","global"),
section.findLong(-1, "regen-time"),
section.findLong(-1, "tick"),
section.findDouble(100.0, "tick-chance"),
buildItem(section),
section.findConfig("Buy","buy")?.let {
ShopPrice(adder, it)
Expand All @@ -52,12 +59,20 @@ data class ShopItemBlueprint(

data class ShopPrice(
val price: Int,
val equation: ShopEquation,
val item: List<ShopItemPrice>,
) {
var dialog: Dialog? = null
private set
constructor(adder: QuestAdderBukkit, section: ConfigurationSection): this(
section.findInt(-1,"Price","price"),
section.getString("equation", "Equation")?.let {
try {
ShopEquation(it)
} catch (ex: Exception) {
null
}
} ?: ShopEquation.defaultEquation,
section.findConfig("Items","item","Item","items")?.let {
it.getKeys(false).mapNotNull { s ->
it.getConfigurationSection(s)?.let { config ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package kor.toxicity.questadder.shop.equation

import kor.toxicity.questadder.shop.implement.ShopItem
import net.objecthunter.exp4j.Expression
import net.objecthunter.exp4j.ExpressionBuilder
import org.bukkit.entity.Player

class ShopEquation(string: String) {

companion object {
val defaultEquation = ShopEquation("t")
}

private val expression = ExpressionBuilder(string)
.variables(
"t",
"b",
"s",
"r",
"k"
)
.build()
fun buyEvaluate(item: ShopItem, player: Player): Double {
return Expression(expression)
.setVariables(mapOf(
"t" to item.blueprint.buyPrice.price.toDouble(),
"b" to item.totalBuy.toDouble(),
"s" to item.totalSell.toDouble(),
"r" to item.buyRandomNumber,
"k" to item.getStock(player).toDouble()
))
.evaluate()
}
fun sellEvaluate(item: ShopItem, player: Player): Double {
return Expression(expression)
.setVariables(mapOf(
"t" to item.blueprint.sellPrice.price.toDouble(),
"b" to item.totalBuy.toDouble(),
"s" to item.totalSell.toDouble(),
"r" to item.sellRandomNumber,
"k" to item.getStock(player).toDouble()
))
.evaluate()
}
}
43 changes: 33 additions & 10 deletions plugin/src/main/java/kor/toxicity/questadder/shop/implement/Shop.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ import net.kyori.adventure.text.Component
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.SkullMeta
import java.text.DecimalFormat

class Shop(private val blueprint: ShopBlueprint, jsonObject: JsonObject): IShop {
companion object {
private val emptyArray = JsonArray()
private val emptyObject = JsonObject()
private val format = DecimalFormat("#,###")
}

private val shopPage: List<ShopPage> = try {
Expand All @@ -46,6 +48,12 @@ class Shop(private val blueprint: ShopBlueprint, jsonObject: JsonObject): IShop
})
}

fun cancel() {
shopPage.forEach {
it.cancel()
}
}

override fun open(player: Player, sender: DialogSender) {
createInventory(blueprint.name.createComponent(player) ?: Component.text("error"), blueprint.size).open(player, object : GuiExecutor {

Expand All @@ -58,22 +66,29 @@ class Shop(private val blueprint: ShopBlueprint, jsonObject: JsonObject): IShop
for (i in 0 until size) {
inv.setItem(i, null)
}
currentShopPage.blueprint.map.forEach {
currentShopPage.shopItem.forEach {
if (it.key >= size - 9) return@forEach
inv.setItem(it.key,it.value.builder().apply {
inv.setItem(it.key,it.value.blueprint.builder().apply {
itemMeta = itemMeta?.apply {
QuestAdderBukkit.platform.setLore(this, QuestAdderBukkit.platform.getLore(this).toMutableList().apply {
val canBuy = it.value.buyPrice.price > 0
val canSell = it.value.sellPrice.price > 0


val buyPrice = it.value.blueprint.buyPrice.equation.buyEvaluate(it.value, player)
val sellPrice = it.value.blueprint.sellPrice.equation.sellEvaluate(it.value, player)

val stock = it.value.getStock(player)

val canBuy = it.value.blueprint.buyPrice.price > 0
val canSell = it.value.blueprint.sellPrice.price > 0

if (canBuy) addAll(ShopManager.loreBuyPrice.mapNotNull { reader ->
reader.createComponent(player, mapOf("\$price" to listOf(Component.text(it.value.buyPrice.price))))
reader.createComponent(player, mapOf("\$price" to listOf(Component.text(format.format(buyPrice)))))
})
if (canSell) addAll(ShopManager.loreSellPrice.mapNotNull { reader ->
reader.createComponent(player, mapOf("\$price" to listOf(Component.text(it.value.sellPrice.price))))
reader.createComponent(player, mapOf("\$price" to listOf(Component.text(format.format(sellPrice)))))
})
if (it.value.stock > 0) addAll(ShopManager.loreRemainStock.mapNotNull { reader ->
reader.createComponent(player, mapOf("\$stock" to listOf(Component.text(it.value.stock))))
if (it.value.blueprint.stock > 0) addAll(ShopManager.loreRemainStock.mapNotNull { reader ->
reader.createComponent(player, mapOf("\$stock" to listOf(Component.text(format.format(stock)))))
})

if (canBuy && canSell) {
Expand Down Expand Up @@ -138,14 +153,22 @@ class Shop(private val blueprint: ShopBlueprint, jsonObject: JsonObject): IShop
} else {
currentShopPage.shopItem[clickedSlot]?.let {
when (button) {
MouseButton.LEFT,MouseButton.SHIFT_LEFT -> {
MouseButton.LEFT -> {
if (it.buy(player, sender, this@Shop)) initialize(data)
Unit
}
MouseButton.RIGHT,MouseButton.SHIFT_RIGHT -> {
MouseButton.SHIFT_LEFT -> {
if (it.buy(player, sender, this@Shop, 64)) initialize(data)
Unit
}
MouseButton.RIGHT -> {
if (it.sell(player, sender, this@Shop)) initialize(data)
Unit
}
MouseButton.SHIFT_RIGHT -> {
if (it.sell(player, sender, this@Shop, 64)) initialize(data)
Unit
}
else -> {}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import kor.toxicity.questadder.shop.stock.GlobalShopStockData
import kor.toxicity.questadder.shop.stock.PlayerShopStockData
import org.bukkit.entity.Player
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ThreadLocalRandom
import kotlin.collections.HashMap

Expand All @@ -22,30 +23,66 @@ class ShopItem(val blueprint: ShopItemBlueprint, jsonObject: JsonObject) {
jsonObject.getAsJsonPrimitive("stock")?.asLong ?: blueprint.stock
} catch (ex: Exception) {
blueprint.stock
})
}, blueprint.regenTime)
} else {
PlayerShopStockData(
try {
HashMap<UUID, Long>().apply {
ConcurrentHashMap<UUID, Long>().apply {
jsonObject.getAsJsonObject("stock")?.entrySet()?.forEach {
put(UUID.fromString(it.key), it.value.asLong)
}
}
} catch (ex: Exception) {
HashMap()
ConcurrentHashMap()
},
blueprint.stock
blueprint.stock,
blueprint.regenTime
)
}
private val shopTask = if (blueprint.tick > 0) QuestAdderBukkit.asyncTaskTimer(blueprint.tick, blueprint.tick) {
if (ThreadLocalRandom.current().nextDouble(100.0) <= blueprint.tickChance) {
sellRandomNumber = ThreadLocalRandom.current().nextDouble()
buyRandomNumber = ThreadLocalRandom.current().nextDouble()
}
} else null

var sellRandomNumber = ThreadLocalRandom.current().nextDouble()
private set
var buyRandomNumber = ThreadLocalRandom.current().nextDouble()
private set

var totalBuy = try {
jsonObject.getAsJsonPrimitive("total-buy")?.asInt ?: 0
} catch (ex: Exception) {
0
}
private set
var totalSell = try {
jsonObject.getAsJsonPrimitive("total-sell")?.asInt ?: 0
} catch (ex: Exception) {
0
}
private set

fun serialize(): JsonElement {
return JsonObject().apply {
if (blueprint.stock > 0) add("stock", stockData.serialize())
if (totalBuy > 0) addProperty("total-buy", totalBuy)
if (totalSell > 0) addProperty("total-sell", totalSell)
}
}

fun buy(player: Player, sender: DialogSender, shop: Shop): Boolean {
val moneyValue = blueprint.buyPrice.price
fun cancel() {
shopTask?.cancel()
stockData.cancel()
}

fun getStock(player: Player): Long {
return stockData.getStock(player)
}

fun buy(player: Player, sender: DialogSender, shop: Shop, buyAmount: Int = 1): Boolean {
val moneyValue = blueprint.buyPrice.equation.buyEvaluate(this, player) * buyAmount
if (moneyValue < 0) {
ShopManager.messageBuyCannotBuying.createComponent(player)?.let {
QuestAdderBukkit.audience.player(player).sendMessage(it)
Expand All @@ -58,14 +95,16 @@ class ShopItem(val blueprint: ShopItemBlueprint, jsonObject: JsonObject) {
}
return false
}
if (blueprint.stock > 0 && stockData.getStock(player) == 0L) {
if (blueprint.stock > 0 && stockData.getStock(player) < buyAmount) {
ShopManager.messageBuyNotHaveStock.createComponent(player)?.let {
QuestAdderBukkit.audience.player(player).sendMessage(it)
}
return false
}
val itemPricePair = blueprint.buyPrice.item.map {
it.item() to it.chance
it.item().apply {
amount *= buyAmount
} to it.chance
}
itemPricePair.forEach {
if (player.totalAmount(it.first) < it.first.amount) {
Expand All @@ -75,8 +114,10 @@ class ShopItem(val blueprint: ShopItemBlueprint, jsonObject: JsonObject) {
return false
}
}
val i = blueprint.builder()
val storage = player.storage(i)
val i = blueprint.builder().apply {
amount *= buyAmount
}
val storage = player.storage(i) * buyAmount
if (storage < i.amount) {
ShopManager.messageBuyNotHaveStorage.createComponent(player, mapOf("\$storage" to listOf((i.amount - storage).toString().asComponent())))?.let { s ->
QuestAdderBukkit.audience.player(player).sendMessage(s)
Expand All @@ -85,13 +126,14 @@ class ShopItem(val blueprint: ShopItemBlueprint, jsonObject: JsonObject) {
}
fun buyTask() {
player.give(i)
player.removeMoney(moneyValue.toDouble())
if (blueprint.stock > 0) stockData.subtractStock(player, 1)
player.removeMoney(moneyValue)
if (blueprint.stock > 0) stockData.subtractStock(player, buyAmount.toLong())
itemPricePair.forEach {
if (ThreadLocalRandom.current().nextDouble(100.0) < it.second) {
player.take(it.first)
}
}
totalBuy += buyAmount
ShopBuyEvent(player, shop, i).call()
}
blueprint.buyPrice.dialog?.let {
Expand All @@ -105,23 +147,27 @@ class ShopItem(val blueprint: ShopItemBlueprint, jsonObject: JsonObject) {
return true
}

fun sell(player: Player, sender: DialogSender, shop: Shop): Boolean {
val moneyValue = blueprint.sellPrice.price
fun sell(player: Player, sender: DialogSender, shop: Shop, sellAmount: Int = 1): Boolean {
val moneyValue = blueprint.sellPrice.equation.sellEvaluate(this, player) * sellAmount
if (moneyValue < 0) {
ShopManager.messageSellCannotSelling.createComponent(player)?.let {
QuestAdderBukkit.audience.player(player).sendMessage(it)
}
return false
}
val item = blueprint.builder()
if (player.totalAmount(item) == 0) {
val item = blueprint.builder().apply {
amount *= sellAmount
}
if (player.totalAmount(item) < sellAmount) {
ShopManager.messageSellNotHaveItem.createComponent(player, mapOf("\$item" to listOf(item.getNameComponent())))?.let {
QuestAdderBukkit.audience.player(player).sendMessage(it)
}
return false
}
val itemPricePair = blueprint.sellPrice.item.map {
it.item() to it.chance
it.item().apply {
amount *= sellAmount
} to it.chance
}
itemPricePair.forEach {
val fir = it.first
Expand All @@ -134,13 +180,14 @@ class ShopItem(val blueprint: ShopItemBlueprint, jsonObject: JsonObject) {
}
fun sellTask() {
player.take(item)
player.addMoney(moneyValue.toDouble())
if (blueprint.stock > 0) stockData.addStock(player, 1)
player.addMoney(moneyValue)
if (blueprint.stock > 0) stockData.addStock(player, sellAmount.toLong())
itemPricePair.forEach {
if (ThreadLocalRandom.current().nextDouble(100.0) < it.second) {
player.give(it.first)
}
}
totalSell += sellAmount
ShopSellEvent(player, shop, item).call()
}
blueprint.sellPrice.dialog?.let {
Expand Down
Loading

0 comments on commit 6bc2a8d

Please sign in to comment.