Add pet level data to /firm pv
This commit is contained in:
92
src/main/kotlin/moe/nea/firmament/repo/ExpLadder.kt
Normal file
92
src/main/kotlin/moe/nea/firmament/repo/ExpLadder.kt
Normal file
@@ -0,0 +1,92 @@
|
||||
package moe.nea.firmament.repo
|
||||
|
||||
import com.google.common.cache.CacheBuilder
|
||||
import com.google.common.cache.CacheLoader
|
||||
import io.github.moulberry.repo.IReloadable
|
||||
import io.github.moulberry.repo.NEURepository
|
||||
import io.github.moulberry.repo.constants.PetLevelingBehaviourOverride
|
||||
import io.github.moulberry.repo.data.Rarity
|
||||
|
||||
object ExpLadders : IReloadable {
|
||||
|
||||
data class PetLevel(
|
||||
val currentLevel: Int,
|
||||
val maxLevel: Int,
|
||||
val expRequiredForNextLevel: Long,
|
||||
val expRequiredForMaxLevel: Long,
|
||||
val expInCurrentLevel: Float,
|
||||
var expTotal: Float,
|
||||
) {
|
||||
val percentageToNextLevel: Float = expInCurrentLevel / expRequiredForNextLevel
|
||||
}
|
||||
|
||||
data class ExpLadder(
|
||||
val individualLevelCost: List<Long>,
|
||||
) {
|
||||
val cumulativeLevelCost = individualLevelCost.runningFold(0F) { a, b -> a + b }.map { it.toLong() }
|
||||
fun getPetLevel(currentExp: Double): PetLevel {
|
||||
val currentOneIndexedLevel = cumulativeLevelCost.indexOfLast { it <= currentExp } + 1
|
||||
val expForNextLevel = if (currentOneIndexedLevel > individualLevelCost.size) { // Max leveled pet
|
||||
individualLevelCost.last()
|
||||
} else {
|
||||
individualLevelCost[currentOneIndexedLevel - 1]
|
||||
}
|
||||
val expInCurrentLevel =
|
||||
if (currentOneIndexedLevel >= cumulativeLevelCost.size)
|
||||
currentExp.toFloat() - cumulativeLevelCost.last()
|
||||
else
|
||||
(expForNextLevel - (cumulativeLevelCost[currentOneIndexedLevel] - currentExp.toFloat())).coerceAtLeast(
|
||||
0F
|
||||
)
|
||||
return PetLevel(
|
||||
currentLevel = currentOneIndexedLevel,
|
||||
maxLevel = cumulativeLevelCost.size,
|
||||
expRequiredForNextLevel = expForNextLevel,
|
||||
expRequiredForMaxLevel = cumulativeLevelCost.last(),
|
||||
expInCurrentLevel = expInCurrentLevel,
|
||||
expTotal = currentExp.toFloat()
|
||||
)
|
||||
}
|
||||
|
||||
fun getPetExpForLevel(level: Int): Long {
|
||||
if (level < 2) return 0L
|
||||
if (level >= cumulativeLevelCost.size) return cumulativeLevelCost.last()
|
||||
return cumulativeLevelCost[level - 1]
|
||||
}
|
||||
}
|
||||
|
||||
private data class Key(val petIdWithoutRarity: String, val rarity: Rarity)
|
||||
|
||||
private val expLadders = CacheBuilder.newBuilder()
|
||||
.build(object : CacheLoader<Key, ExpLadder>() {
|
||||
override fun load(key: Key): ExpLadder {
|
||||
val pld = RepoManager.neuRepo.constants.petLevelingData
|
||||
var exp = pld.petExpCostForLevel
|
||||
var offset = pld.petLevelStartOffset[key.rarity]!!
|
||||
var maxLevel = 100
|
||||
val override = pld.petLevelingBehaviourOverrides[key.petIdWithoutRarity]
|
||||
if (override != null) {
|
||||
maxLevel = override.maxLevel ?: maxLevel
|
||||
offset = override.petLevelStartOffset?.get(key.rarity) ?: offset
|
||||
when (override.petExpCostModifierType) {
|
||||
PetLevelingBehaviourOverride.PetExpModifierType.APPEND ->
|
||||
exp = exp + override.petExpCostModifier
|
||||
|
||||
PetLevelingBehaviourOverride.PetExpModifierType.REPLACE ->
|
||||
exp = override.petExpCostModifier
|
||||
|
||||
null -> {}
|
||||
}
|
||||
}
|
||||
return ExpLadder(exp.drop(offset).take(maxLevel - 1).map { it.toLong() })
|
||||
}
|
||||
})
|
||||
|
||||
override fun reload(repository: NEURepository?) {
|
||||
expLadders.invalidateAll()
|
||||
}
|
||||
|
||||
fun getExpLadder(petId: String, rarity: Rarity): ExpLadder {
|
||||
return expLadders.get(Key(petId, rarity))
|
||||
}
|
||||
}
|
||||
@@ -41,12 +41,15 @@ import net.minecraft.item.Items
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import net.minecraft.nbt.NbtElement
|
||||
import net.minecraft.nbt.NbtHelper
|
||||
import net.minecraft.nbt.NbtList
|
||||
import net.minecraft.nbt.NbtOps
|
||||
import net.minecraft.nbt.NbtString
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.util.LegacyTagParser
|
||||
import moe.nea.firmament.util.SkyblockId
|
||||
import moe.nea.firmament.util.appendLore
|
||||
import moe.nea.firmament.util.getOrCreateList
|
||||
import moe.nea.firmament.util.item.MinecraftProfileTextureKt
|
||||
import moe.nea.firmament.util.item.MinecraftTexturesPayloadKt
|
||||
import moe.nea.firmament.util.item.setTextures
|
||||
@@ -103,16 +106,46 @@ object ItemCache : IReloadable {
|
||||
}
|
||||
}
|
||||
|
||||
fun NEUItem?.asItemStack(idHint: SkyblockId? = null): ItemStack {
|
||||
fun NEUItem?.asItemStack(idHint: SkyblockId? = null, loreReplacements: Map<String, String>? = null): ItemStack {
|
||||
if (this == null) return brokenItemStack(null, idHint)
|
||||
var s = cache[this.skyblockItemId]
|
||||
if (s == null) {
|
||||
s = asItemStackNow()
|
||||
cache[this.skyblockItemId] = s
|
||||
}
|
||||
if (!loreReplacements.isNullOrEmpty()) {
|
||||
s.applyLoreReplacements(loreReplacements)
|
||||
s.setCustomName(s.name.applyLoreReplacements(loreReplacements))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
fun ItemStack.applyLoreReplacements(loreReplacements: Map<String, String>) {
|
||||
val component = getOrCreateSubNbt("display")
|
||||
val lore = component.getOrCreateList("Lore", NbtString.STRING_TYPE)
|
||||
val newLore = NbtList()
|
||||
lore.forEach {
|
||||
newLore.add(
|
||||
NbtString.of(
|
||||
Text.Serializer.toJson(
|
||||
Text.Serializer.fromJson(it.asString())!!.applyLoreReplacements(loreReplacements)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
component["Lore"] = newLore
|
||||
}
|
||||
|
||||
fun Text.applyLoreReplacements(loreReplacements: Map<String, String>): Text {
|
||||
assert(this.siblings.isEmpty())
|
||||
var string = this.string
|
||||
loreReplacements.forEach { (find, replace) ->
|
||||
string = string.replace("{$find}", replace)
|
||||
}
|
||||
return Text.literal(string).styled { this.style }
|
||||
}
|
||||
|
||||
|
||||
fun NEUItem.getIdentifier() = skyblockId.identifier
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import io.github.moulberry.repo.NEURepository
|
||||
import io.github.moulberry.repo.NEURepositoryException
|
||||
import io.github.moulberry.repo.data.NEUItem
|
||||
import io.github.moulberry.repo.data.NEURecipe
|
||||
import io.github.moulberry.repo.data.Rarity
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
|
||||
import kotlinx.coroutines.launch
|
||||
import net.minecraft.client.MinecraftClient
|
||||
@@ -31,9 +32,10 @@ import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.Firmament.logger
|
||||
import moe.nea.firmament.hud.ProgressBar
|
||||
import moe.nea.firmament.util.SkyblockId
|
||||
import moe.nea.firmament.gui.config.ManagedConfig
|
||||
import moe.nea.firmament.hud.ProgressBar
|
||||
import moe.nea.firmament.rei.PetData
|
||||
import moe.nea.firmament.util.SkyblockId
|
||||
|
||||
object RepoManager {
|
||||
object Config : ManagedConfig("repo") {
|
||||
@@ -59,6 +61,7 @@ object RepoManager {
|
||||
|
||||
val neuRepo: NEURepository = NEURepository.of(RepoDownloadManager.repoSavedLocation).apply {
|
||||
registerReloadListener(ItemCache)
|
||||
registerReloadListener(ExpLadders)
|
||||
registerReloadListener {
|
||||
if (!trySendClientboundUpdateRecipesPacket()) {
|
||||
logger.warn("Failed to issue a ClientboundUpdateRecipesPacket (to reload REI). This may lead to an outdated item list.")
|
||||
@@ -121,4 +124,19 @@ object RepoManager {
|
||||
}
|
||||
}
|
||||
|
||||
fun getPotentialStubPetData(skyblockId: SkyblockId): PetData? {
|
||||
val parts = skyblockId.neuItem.split(";")
|
||||
if (parts.size != 2) {
|
||||
return null
|
||||
}
|
||||
val (petId, rarityIndex) = parts
|
||||
if (!rarityIndex.all { it.isDigit() }) {
|
||||
return null
|
||||
}
|
||||
val intIndex = rarityIndex.toInt()
|
||||
if (intIndex !in rarityIndex.indices) return null
|
||||
if (petId !in neuRepo.constants.petNumbers) return null
|
||||
return PetData(Rarity.values()[intIndex], petId, 0.0)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user