Skip to content

Commit

Permalink
add custom currency selection, fix paths for configs (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
makeevrserg authored Sep 13, 2024
1 parent 18c98de commit edbde56
Show file tree
Hide file tree
Showing 16 changed files with 110 additions and 34 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ makeevrserg.java.ktarget=21
# Project
makeevrserg.project.name=AstraShop
makeevrserg.project.group=ru.astrainteractive.astrashop
makeevrserg.project.version.string=4.11.7
makeevrserg.project.version.string=4.12.0
makeevrserg.project.description=Shop plugin for EmpireSMP
makeevrserg.project.developers=makeevrserg|Makeev Roman|[email protected]
makeevrserg.project.url=https://empireprojekt.ru
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ minecraft-spigot = "1.21-R0.1-SNAPSHOT" # https://github.com/PaperMC/Paper
minecraft-papi = "2.11.6" # https://github.com/PlaceholderAPI/PlaceholderAPI
minecraft-protocollib = "5.1.0" # https://github.com/dmulloy2/ProtocolLib
minecraft-vault = "1.7.1" # https://github.com/MilkBowl/VaultAPI
minecraft-astralibs = "3.12.2" # https://github.com/Astra-Interactive/AstraLibs
minecraft-astralibs = "3.14.1" # https://github.com/Astra-Interactive/AstraLibs
minecraft-bstats = "3.0.2" # https://github.com/Bastian/bStats
minecraft-mockbukkit = "3.108.0" #https://github.com/MockBukkit/MockBukkit

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,17 @@ internal class SpigotShopApi(

override suspend fun fetchShopList(): List<ShopConfig> {
return withContext(limitedDispatcher) {
getYmlFiles(plugin)
.mapNotNull(::shopFileOrNull)
getYmlFiles(plugin).mapNotNull(::shopFileOrNull)
}
}

override suspend fun fetchShop(shopFileName: String): ShopConfig {
return withContext(limitedDispatcher) {
shopItemParser.parseShopFile(plugin.dataFolder.resolve(shopFileName))
shopItemParser.parseShopFile(
plugin.dataFolder
.resolve("shops")
.resolve(shopFileName)
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ internal interface ShopItemParser {
/**
* Parse shop file from [File]
*/
fun parseShopFile(fileManager: File): ShopConfig
fun parseShopFile(file: File): ShopConfig
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,16 @@ internal class ShopItemParserImpl(
itemSection?.set("is_purchase_infinite", item.isPurchaseInfinite)
itemSection?.set("is_for_purchase", item.isForPurchase)
itemSection?.set("is_for_sell", item.isForSell)
itemSection?.set("sell_currency_id", item.sellCurrencyId)
itemSection?.set("buy_currency_id", item.buyCurrencyId)
}
fileConfiguration.save(file)
}

override fun parseShopFile(file: File): ShopConfig {
val fileConfiguration = YamlConfiguration.loadConfiguration(file)
val optionsSections = fileConfiguration.getConfigurationSection("options")
?: throw ShopParseException("No options section in ${fileConfiguration.name}")
?: throw ShopParseException("No options section in ${fileConfiguration.name} -> ${file.name}")
val itemsSection = fileConfiguration.getConfigurationSection("items")

val options = parseOption(optionsSections)
Expand Down Expand Up @@ -150,7 +152,9 @@ internal class ShopItemParserImpl(
price = price,
isForSell = s.getBoolean("is_for_sell", true),
isForPurchase = s.getBoolean("is_for_purchase", true),
isPurchaseInfinite = s.getBoolean("is_purchase_infinite", false)
isPurchaseInfinite = s.getBoolean("is_purchase_infinite", false),
sellCurrencyId = s.getString("sell_currency_id"),
buyCurrencyId = s.getString("buy_currency_id"),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ data class ShopConfig(

data class ShopItem(
val itemIndex: Int,
val sellCurrencyId: String? = null,
val buyCurrencyId: String? = null,
val isForSell: Boolean,
val isPurchaseInfinite: Boolean,
val isForPurchase: Boolean,
Expand Down
2 changes: 1 addition & 1 deletion modules/core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ dependencies {
implementation(libs.minecraft.astralibs.core.bukkit)
implementation(libs.klibs.mikro)
// Spigot dependencies
compileOnly(libs.minecraft.paper.api)
implementation(libs.minecraft.bstats)
compileOnly(libs.minecraft.paper.api)
compileOnly(libs.minecraft.papi)
compileOnly(libs.minecraft.vaultapi)
implementation(libs.minecraft.bstats)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import org.bukkit.plugin.java.JavaPlugin
import ru.astrainteractive.astralibs.async.AsyncComponent
import ru.astrainteractive.astralibs.async.BukkitDispatchers
import ru.astrainteractive.astralibs.async.DefaultBukkitDispatchers
import ru.astrainteractive.astralibs.economy.EconomyProvider
import ru.astrainteractive.astralibs.economy.EconomyProviderFactory
import ru.astrainteractive.astralibs.event.EventListener
import ru.astrainteractive.astralibs.kyori.KyoriComponentSerializer
import ru.astrainteractive.astralibs.menu.event.DefaultInventoryClickEvent
import ru.astrainteractive.astralibs.serialization.StringFormatExt.parse
import ru.astrainteractive.astralibs.serialization.StringFormatExt.writeIntoFile
import ru.astrainteractive.astralibs.serialization.YamlStringFormat
import ru.astrainteractive.astrashop.core.PluginTranslation
import ru.astrainteractive.astrashop.core.di.factory.CurrencyEconomyProviderFactory
import ru.astrainteractive.astrashop.core.di.factory.CurrencyEconomyProviderFactoryImpl
import ru.astrainteractive.klibs.kdi.Lateinit
import ru.astrainteractive.klibs.kdi.Reloadable
import ru.astrainteractive.klibs.kdi.Single
Expand All @@ -21,11 +21,11 @@ import ru.astrainteractive.klibs.kdi.getValue
interface CoreModule {
val plugin: Lateinit<JavaPlugin>
val translation: Reloadable<PluginTranslation>
val economyProvider: Single<EconomyProvider>
val dispatchers: Single<BukkitDispatchers>
val scope: Single<AsyncComponent>
val inventoryClickEvent: Single<EventListener>
val kyoriComponentSerializer: Reloadable<KyoriComponentSerializer>
val currencyEconomyProviderFactory: CurrencyEconomyProviderFactory

class Default : CoreModule {
override val plugin: Lateinit<JavaPlugin> = Lateinit()
Expand All @@ -38,9 +38,6 @@ interface CoreModule {
.getOrElse { PluginTranslation() }
.also { serializer.writeIntoFile(it, config) }
}
override val economyProvider: Single<EconomyProvider> = Single {
EconomyProviderFactory(plugin.value).create()
}
override val dispatchers: Single<BukkitDispatchers> = Single {
val plugin by plugin
DefaultBukkitDispatchers(plugin)
Expand All @@ -54,5 +51,8 @@ interface CoreModule {
override val kyoriComponentSerializer: Reloadable<KyoriComponentSerializer> = Reloadable {
KyoriComponentSerializer.Legacy
}
override val currencyEconomyProviderFactory: CurrencyEconomyProviderFactory by lazy {
CurrencyEconomyProviderFactoryImpl(plugin.value)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package ru.astrainteractive.astrashop.core.di.factory

import net.milkbowl.vault.economy.Economy
import org.bukkit.Bukkit
import org.bukkit.plugin.java.JavaPlugin
import ru.astrainteractive.astralibs.economy.EconomyProvider
import ru.astrainteractive.astralibs.economy.EssentialsEconomyProvider
import ru.astrainteractive.astralibs.economy.VaultEconomyProvider
import ru.astrainteractive.astralibs.logging.JUtiltLogger
import ru.astrainteractive.astralibs.logging.Logger

interface CurrencyEconomyProviderFactory {
fun findByCurrencyId(currencyId: String): EconomyProvider?
fun findDefault(): EconomyProvider?
}

internal class CurrencyEconomyProviderFactoryImpl(
private val plugin: JavaPlugin,
) : CurrencyEconomyProviderFactory,
Logger by JUtiltLogger("CurrencyEconomyProviderFactory") {
override fun findByCurrencyId(currencyId: String): EconomyProvider? {
val registrations = Bukkit.getServer().servicesManager.getRegistrations(Economy::class.java)
info { "#findEconomyProviderByCurrency registrations: ${registrations.size}" }
val specificEconomyProvider = registrations
.firstOrNull { it.provider.currencyNameSingular() == currencyId }
?.provider
?.let(::VaultEconomyProvider)
if (specificEconomyProvider == null) {
error { "#economyProvider could not find economy with currency: $currencyId" }
}
return specificEconomyProvider
}

override fun findDefault(): EconomyProvider? {
return kotlin.runCatching {
VaultEconomyProvider(plugin)
}.getOrNull() ?: kotlin.runCatching {
if (!Bukkit.getServer().pluginManager.isPluginEnabled("Essentials")) {
error("Essentials not enabled")
} else {
EssentialsEconomyProvider
}
}.getOrNull()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ interface DomainModule {
}
override val buyUseCase: BuyUseCase by Provider {
BuyUseCase(
economy = coreModule.economyProvider.value,
currencyEconomyProviderFactory = coreModule.currencyEconomyProviderFactory,
playerBridge = playerBridge,
translation = coreModule.translation.value
)
Expand All @@ -45,7 +45,7 @@ interface DomainModule {
}
override val sellUseCase: SellUseCase by Provider {
SellUseCase(
economy = coreModule.economyProvider.value,
currencyEconomyProviderFactory = coreModule.currencyEconomyProviderFactory,
playerBridge = playerBridge,
translation = coreModule.translation.value
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package ru.astrainteractive.astrashop.domain.usecase

import ru.astrainteractive.astralibs.economy.EconomyProvider
import ru.astrainteractive.astralibs.logging.BukkitLogger
import ru.astrainteractive.astralibs.logging.Logger
import ru.astrainteractive.astrashop.api.model.ShopConfig
import ru.astrainteractive.astrashop.core.PluginTranslation
import ru.astrainteractive.astrashop.core.di.factory.CurrencyEconomyProviderFactory
import ru.astrainteractive.astrashop.domain.bridge.PlayerBridge
import ru.astrainteractive.klibs.mikro.core.domain.UseCase
import java.util.UUID

class BuyUseCase(
private val economy: EconomyProvider,
private val currencyEconomyProviderFactory: CurrencyEconomyProviderFactory,
private val playerBridge: PlayerBridge,
private val translation: PluginTranslation
) : UseCase.Suspended<BuyUseCase.Param, BuyUseCase.Result>,
Expand All @@ -31,7 +31,14 @@ class BuyUseCase(
val item = input.shopItem
val amount = input.amount
val playerName = playerBridge.getName(input.playerUUID)

val economy = when (val currencyId = input.shopItem.buyCurrencyId) {
null -> currencyEconomyProviderFactory.findDefault()
else -> currencyEconomyProviderFactory.findByCurrencyId(currencyId)
}
if (economy == null) {
error { "#invoke could not find currency with id ${input.shopItem.buyCurrencyId} (or default currency)" }
return Result.Failure
}
// Is item for sale

val totalPrice = PriceCalculator.calculateBuyPrice(item, amount)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package ru.astrainteractive.astrashop.domain.usecase

import ru.astrainteractive.astralibs.economy.EconomyProvider
import ru.astrainteractive.astralibs.logging.BukkitLogger
import ru.astrainteractive.astralibs.logging.Logger
import ru.astrainteractive.astrashop.api.model.ShopConfig
import ru.astrainteractive.astrashop.core.PluginTranslation
import ru.astrainteractive.astrashop.core.di.factory.CurrencyEconomyProviderFactory
import ru.astrainteractive.astrashop.domain.bridge.PlayerBridge
import ru.astrainteractive.astrashop.domain.usecase.BuyUseCase.Result
import ru.astrainteractive.klibs.mikro.core.domain.UseCase
import java.util.UUID

class SellUseCase(
private val economy: EconomyProvider,
private val currencyEconomyProviderFactory: CurrencyEconomyProviderFactory,
private val playerBridge: PlayerBridge,
private val translation: PluginTranslation
) : UseCase.Suspended<SellUseCase.Param, SellUseCase.Result>,
Expand All @@ -31,7 +32,14 @@ class SellUseCase(
val item = input.shopItem
val amount = input.amount
val playerName = playerBridge.getName(input.playerUUID)

val economy = when (val currencyId = input.shopItem.buyCurrencyId) {
null -> currencyEconomyProviderFactory.findDefault()
else -> currencyEconomyProviderFactory.findByCurrencyId(currencyId)
}
if (economy == null) {
error { "#invoke could not find currency with id ${input.shopItem.buyCurrencyId} (or default currency)" }
return Result.Failure
}
// Is item purchasing
val totalSellPrice = PriceCalculator.calculateSellPrice(item, amount)
if (totalSellPrice <= 0) {
Expand Down
2 changes: 1 addition & 1 deletion plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ minecraftMultiplatform {
implementation(projects.modules.api.bukkitMain)
}
}
val destination = File("D:\\Minecraft Servers\\Servers\\conf.smp\\smp\\plugins")
val destination = File("/home/makeevrserg/Desktop/server/data/plugins")
.takeIf(File::exists)
?: File(rootDir, "jars")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package ru.astrainteractive.astrashop.command.shop

import ru.astrainteractive.astralibs.command.api.context.BukkitCommandContext
import ru.astrainteractive.astralibs.command.api.error.ErrorHandler
import ru.astrainteractive.astralibs.command.api.exception.NoPermissionException
import ru.astrainteractive.astralibs.command.api.exception.DefaultCommandException
import ru.astrainteractive.astrashop.command.di.CommandManagerDependencies

internal class ShopCommandErrorHandler(
Expand All @@ -12,7 +12,7 @@ internal class ShopCommandErrorHandler(
override fun handle(commandContext: BukkitCommandContext, throwable: Throwable) {
val commandSender = commandContext.sender
when (throwable) {
is NoPermissionException ->
is DefaultCommandException.NoPermissionException ->
kyoriComponentSerializer
.toComponent(translation.general.noPermission)
.run(commandSender::sendMessage)
Expand All @@ -27,7 +27,7 @@ internal class ShopCommandErrorHandler(
.toComponent(translation.general.wrongUsage)
.run(commandSender::sendMessage)

else -> Unit
else -> error("Unhandled error $throwable::class")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import ru.astrainteractive.astralibs.async.AsyncComponent
import ru.astrainteractive.astralibs.economy.EconomyProvider
import ru.astrainteractive.astrashop.api.ShopApi
import ru.astrainteractive.astrashop.api.model.ShopConfig
import ru.astrainteractive.astrashop.core.di.factory.CurrencyEconomyProviderFactory
import ru.astrainteractive.astrashop.domain.interactor.BuyInteractor
import ru.astrainteractive.astrashop.domain.interactor.SellInteractor
import ru.astrainteractive.astrashop.gui.buy.presentation.BuyComponent.Model
Expand All @@ -18,7 +18,7 @@ class DefaultBuyComponent(
private val shopItem: ShopConfig.ShopItem,
private val playerUUID: UUID,
private val shopApi: ShopApi,
private val economy: EconomyProvider,
private val currencyEconomyProviderFactory: CurrencyEconomyProviderFactory,
private val sellInteractor: SellInteractor,
private val buyInteractor: BuyInteractor
) : AsyncComponent(), BuyComponent {
Expand All @@ -39,11 +39,18 @@ class DefaultBuyComponent(
if (item == null) {
model.value = Model.Error
} else {
val economy = when (val currencyId = item.buyCurrencyId) {
null -> currencyEconomyProviderFactory.findDefault()
else -> currencyEconomyProviderFactory.findByCurrencyId(currencyId)
}
if (economy == null) {
error { "#invoke could not find currency with id ${item.buyCurrencyId} (or default currency)" }
}
model.value = Model.Loaded(
item,
shopConfig.options,
shopConfig,
economy.getBalance(playerUUID)?.toInt() ?: 0
item = item,
shopConfig = shopConfig.options,
instance = shopConfig,
playerBalance = economy.getBalance(playerUUID)?.toInt() ?: 0
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ internal class GuiRouterImpl(
shopFileName = route.shopConfig.configName,
shopApi = apiModule.shopApi,
sellInteractor = domainModule.sellInteractor,
economy = coreModule.economyProvider.value,
currencyEconomyProviderFactory = coreModule.currencyEconomyProviderFactory,
buyInteractor = domainModule.buyInteractor,
playerUUID = route.playerHolder.player.uniqueId,
shopItem = route.shopItem
Expand Down

0 comments on commit edbde56

Please sign in to comment.