diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecojobs/jobs/Job.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecojobs/jobs/Job.kt index 775628d..a43455c 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecojobs/jobs/Job.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecojobs/jobs/Job.kt @@ -6,13 +6,16 @@ import com.willfp.eco.core.data.keys.PersistentDataKey import com.willfp.eco.core.data.keys.PersistentDataKeyType import com.willfp.eco.core.items.Items import com.willfp.eco.core.items.builder.ItemStackBuilder +import com.willfp.eco.core.placeholder.InjectablePlaceholder import com.willfp.eco.core.placeholder.PlayerPlaceholder import com.willfp.eco.core.placeholder.PlayerStaticPlaceholder import com.willfp.eco.core.placeholder.PlayerlessPlaceholder +import com.willfp.eco.core.placeholder.StaticPlaceholder import com.willfp.eco.core.price.ConfiguredPrice import com.willfp.eco.core.price.impl.PriceEconomy import com.willfp.eco.core.registry.Registrable import com.willfp.eco.util.NumberUtils +import com.willfp.eco.util.NumberUtils.evaluateExpression import com.willfp.eco.util.formatEco import com.willfp.eco.util.toNiceString import com.willfp.ecojobs.EcoJobsPlugin @@ -32,12 +35,11 @@ import com.willfp.libreforge.effects.EffectList import com.willfp.libreforge.effects.Effects import org.bukkit.Bukkit import org.bukkit.OfflinePlayer +import org.bukkit.configuration.InvalidConfigurationException import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack import java.time.Duration import java.util.Objects -import java.util.concurrent.TimeUnit -import kotlin.math.max class Job( val id: String, @@ -49,8 +51,11 @@ class Job( .build() val name = config.getFormattedString("name") + val description = config.getFormattedString("description") + val isUnlockedByDefault = config.getBool("unlocked-by-default") + val resetsOnQuit = config.getBool("reset-on-quit") val joinPrice = ConfiguredPrice.create(config.getSubsection("join-price")) ?: ConfiguredPrice( @@ -71,9 +76,11 @@ class Job( EcoJobsPlugin.instance.namespacedKeyFactory.create("${id}_xp"), PersistentDataKeyType.DOUBLE, 0.0 ) - private val levelXpRequirements = listOf(0) + config.getInts("level-xp-requirements") + private val xpFormula = config.getStringOrNull("xp-formula") - val maxLevel = levelXpRequirements.size + private val levelXpRequirements = config.getDoublesOrNull("level-xp-requirements") + + val maxLevel = config.getIntOrNull("max-level") ?: levelXpRequirements?.size ?: Int.MAX_VALUE val levelGUI = JobLevelGUI(plugin, this) @@ -106,6 +113,10 @@ class Job( } init { + if (xpFormula == null && levelXpRequirements == null) { + throw InvalidConfigurationException("Skill $id has no requirements or xp formula") + } + config.injectPlaceholders(PlayerStaticPlaceholder( "level" ) { p -> @@ -352,9 +363,23 @@ class Job( return Int.MAX_VALUE } - return levelXpRequirements[level - 1] + // Use levelXpRequirements if it exists and covers the level + if (levelXpRequirements != null && levelXpRequirements.size >= level) { + return levelXpRequirements[level - 1].toInt() + } + + // Fallback to using the xpFormula if it exists + if (xpFormula != null) { + return evaluateExpression( + xpFormula.replace("%level%", level.toString()) + ).toInt() + } + + // Default fallback if neither configuration is usable + return Int.MAX_VALUE } + fun executeLevelCommands(player: Player, level: Int) { val commands = levelCommands[level] ?: emptyList() @@ -409,43 +434,3 @@ private fun Collection.format(string: String, level: Int): Str fun OfflinePlayer.getJobLevelObject(job: Job): JobLevel = job.getLevel(this.getJobLevel(job)) -private val expMultiplierCache = Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.SECONDS).build { - it.cacheJobExperienceMultiplier() -} - -val Player.jobExperienceMultiplier: Double - get() = expMultiplierCache.get(this) - -private fun Player.cacheJobExperienceMultiplier(): Double { - if (this.hasPermission("ecojobs.xpmultiplier.quadruple")) { - return 4.0 - } - - if (this.hasPermission("ecojobs.xpmultiplier.triple")) { - return 3.0 - } - - if (this.hasPermission("ecojobs.xpmultiplier.double")) { - return 2.0 - } - - if (this.hasPermission("ecojobs.xpmultiplier.50percent")) { - return 1.5 - } - - return 1 + getNumericalPermission("ecojobs.xpmultiplier", 0.0) / 100 -} - -fun Player.getNumericalPermission(permission: String, default: Double): Double { - var highest: Double? = null - - for (permissionAttachmentInfo in this.effectivePermissions) { - val perm = permissionAttachmentInfo.permission - if (perm.startsWith(permission)) { - val found = perm.substring(perm.lastIndexOf(".") + 1).toDoubleOrNull() ?: continue - highest = max(highest ?: Double.MIN_VALUE, found) - } - } - - return highest ?: default -} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecojobs/jobs/JobXPAccumulator.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecojobs/jobs/JobXPAccumulator.kt index cf2cd6a..47e5e47 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecojobs/jobs/JobXPAccumulator.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecojobs/jobs/JobXPAccumulator.kt @@ -1,9 +1,12 @@ package com.willfp.ecojobs.jobs +import com.github.benmanes.caffeine.cache.Caffeine import com.willfp.ecojobs.api.giveJobExperience import com.willfp.ecojobs.api.hasJobActive import com.willfp.libreforge.counters.Accumulator import org.bukkit.entity.Player +import java.util.concurrent.TimeUnit +import kotlin.math.max class JobXPAccumulator( private val job: Job @@ -16,3 +19,44 @@ class JobXPAccumulator( player.giveJobExperience(job, count) } } + +private val expMultiplierCache = Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.SECONDS).build { + it.cacheJobExperienceMultiplier() +} + +val Player.jobExperienceMultiplier: Double + get() = expMultiplierCache.get(this) + +private fun Player.cacheJobExperienceMultiplier(): Double { + if (this.hasPermission("ecojobs.xpmultiplier.quadruple")) { + return 4.0 + } + + if (this.hasPermission("ecojobs.xpmultiplier.triple")) { + return 3.0 + } + + if (this.hasPermission("ecojobs.xpmultiplier.double")) { + return 2.0 + } + + if (this.hasPermission("ecojobs.xpmultiplier.50percent")) { + return 1.5 + } + + return 1 + getNumericalPermission("ecojobs.xpmultiplier", 0.0) / 100 +} + +fun Player.getNumericalPermission(permission: String, default: Double): Double { + var highest: Double? = null + + for (permissionAttachmentInfo in this.effectivePermissions) { + val perm = permissionAttachmentInfo.permission + if (perm.startsWith(permission)) { + val found = perm.substring(perm.lastIndexOf(".") + 1).toDoubleOrNull() ?: continue + highest = max(highest ?: Double.MIN_VALUE, found) + } + } + + return highest ?: default +}