Skip to content

Commit

Permalink
feat(plugin): improvements for the chance tag
Browse files Browse the repository at this point in the history
- use ThreadLocalRandom
- switch from double to float for chance
- add option to limit the chance to another value than 100
  • Loading branch information
iGabyTM committed Jul 31, 2024
1 parent ec91508 commit 6254c9a
Showing 1 changed file with 18 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package me.gabytm.minecraft.arcanevouchers.actions.tags

import me.gabytm.minecraft.arcanevouchers.functions.debug
import me.gabytm.util.actions.actions.Context
import me.gabytm.util.actions.components.Component
import me.gabytm.util.actions.placeholders.PlaceholderManager
import org.bukkit.entity.Player
import java.util.*
import java.util.concurrent.ThreadLocalRandom

class ChanceTag(stringValue: String, placeholderManager: PlaceholderManager) : Component<Player, String>(
stringValue,
Expand All @@ -13,6 +14,7 @@ class ChanceTag(stringValue: String, placeholderManager: PlaceholderManager) : C

private val elements: Set<Pair<String, String>>
private val default: String
private val limitChanceToMax: Boolean

init {
// Example: {50=COAL,25=DIAMOND,25=EMERALD,default=STONE}
Expand All @@ -31,33 +33,40 @@ class ChanceTag(stringValue: String, placeholderManager: PlaceholderManager) : C
""
}

limitChanceToMax = default == "#limit-max-chance"

elements = pairs.toSet()
}

override fun parse(player: Player, context: Context<Player>): String {
// Map all elements into Pair<Chance, Element>
val set = elements.map {
val chance = placeholderManager.replace(player, it.first, context).toDoubleOrNull()
val chance = placeholderManager.replace(player, it.first, context).toFloatOrNull()
?: throw IllegalArgumentException("(chance tag) '${it.first}' is not a number")
chance to placeholderManager.replace(player, it.second, context)
}
val chance = RANDOM.nextDouble(101.0) // Generate random chance between 0 and 100
val valid = set.filter { chance <= it.first } // Filter the elements
val chance = if (limitChanceToMax) {
ThreadLocalRandom.current().nextFloat() * set.maxOf { it.first } // Variable max chance
} else {
ThreadLocalRandom.current().nextFloat() * 100.00001f // Generate random chance between 0 and 100
}
val possible = set.filter { chance <= it.first }
debug(player, "(chance tag) elements = $elements, set = $set")
debug(player, "(chance tag) chance = $chance, possible = $possible")

return if (valid.isEmpty()) {
return if (possible.isEmpty()) {
default
} else if (valid.size == 1) {
valid.first().second
} else if (possible.size == 1) {
possible.first().second
} else {
valid.elementAt(RANDOM.nextInt(valid.size)).second
possible.elementAt(ThreadLocalRandom.current().nextInt(possible.size)).second
}
}

@Suppress("unused")
companion object {

private const val ID: String = "chance"
private val RANDOM = SplittableRandom()

}

Expand Down

0 comments on commit 6254c9a

Please sign in to comment.