LootTables.kt
Branches > main > 690b0fd > files / src / main / kotlin / net / bowmap / loot / LootTables.kt
package net.bowmap.loot
import org.bukkit.Material
import org.bukkit.inventory.ItemStack
import java.util.concurrent.ThreadLocalRandom
interface Loot {
fun getLoot(): List<ItemStack>
}
data class LootList(val list: List<Loot>) : Loot {
init {
require(list.isNotEmpty()) { "Loot list must not be empty!" }
}
constructor(vararg loots: Loot) : this(loots.toList())
override fun getLoot(): List<ItemStack> {
val i = ThreadLocalRandom.current().nextInt(list.size)
return list[i].getLoot()
}
}
data class MaterialLoot(val material: Material, val min: Int = 1, val max: Int = min) : Loot {
init {
require(min >= 1 && min <= max && max <= material.maxStackSize) {
"Invalid min/max stack sizes!"
}
}
override fun getLoot(): List<ItemStack> {
val amount = ThreadLocalRandom.current().nextInt(min, max + 1)
return listOf(ItemStack(material, amount))
}
}
data class Category(val weight: Int, val loot: Loot) : Loot {
constructor(name: String, weight: Int, vararg loots: Loot) : this(
weight,
LootList(loots.toList())
)
init {
require(weight > 0) { "weight must be > 0" }
}
override fun getLoot(): List<ItemStack> = loot.getLoot()
}
private fun buildLookup(categories: Array<out Category>): Array<Category> {
val totalWeight = totalWeight(categories)
val lookup = ArrayList<Category>(totalWeight)
for (c in categories) {
repeat(c.weight) {
lookup.add(c)
}
}
return lookup.toTypedArray()
}
private fun totalWeight(categories: Array<out Category>): Int {
require(categories.isNotEmpty()) { "Category list must not be empty!" }
val total = categories.sumOf { it.weight }
require(total != 0) { "Weight cannot be 0" }
return total
}
data class WeightedLoot(private val lookup: Array<Category>, private val totalWeight: Int) : Loot {
constructor(vararg categories: Category) : this(buildLookup(categories), totalWeight(categories))
private fun pickRandomCategory(): Category {
val randomWeight = ThreadLocalRandom.current().nextInt(totalWeight)
return lookup[randomWeight]
}
override fun getLoot(): List<ItemStack> {
return pickRandomCategory().getLoot()
}
}