Add current pet highlighter
This commit is contained in:
@@ -21,6 +21,7 @@ import moe.nea.firmament.features.fixes.CompatibliltyFeatures
|
|||||||
import moe.nea.firmament.features.fixes.Fixes
|
import moe.nea.firmament.features.fixes.Fixes
|
||||||
import moe.nea.firmament.features.inventory.CraftingOverlay
|
import moe.nea.firmament.features.inventory.CraftingOverlay
|
||||||
import moe.nea.firmament.features.inventory.ItemRarityCosmetics
|
import moe.nea.firmament.features.inventory.ItemRarityCosmetics
|
||||||
|
import moe.nea.firmament.features.inventory.PetFeatures
|
||||||
import moe.nea.firmament.features.inventory.PriceData
|
import moe.nea.firmament.features.inventory.PriceData
|
||||||
import moe.nea.firmament.features.inventory.SaveCursorPosition
|
import moe.nea.firmament.features.inventory.SaveCursorPosition
|
||||||
import moe.nea.firmament.features.inventory.SlotLocking
|
import moe.nea.firmament.features.inventory.SlotLocking
|
||||||
@@ -67,6 +68,7 @@ object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "feature
|
|||||||
loadFeature(CompatibliltyFeatures)
|
loadFeature(CompatibliltyFeatures)
|
||||||
loadFeature(AnniversaryFeatures)
|
loadFeature(AnniversaryFeatures)
|
||||||
loadFeature(QuickCommands)
|
loadFeature(QuickCommands)
|
||||||
|
loadFeature(PetFeatures)
|
||||||
loadFeature(SaveCursorPosition)
|
loadFeature(SaveCursorPosition)
|
||||||
loadFeature(CustomSkyBlockTextures)
|
loadFeature(CustomSkyBlockTextures)
|
||||||
loadFeature(PriceData)
|
loadFeature(PriceData)
|
||||||
|
|||||||
40
src/main/kotlin/features/inventory/PetFeatures.kt
Normal file
40
src/main/kotlin/features/inventory/PetFeatures.kt
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package moe.nea.firmament.features.inventory
|
||||||
|
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import moe.nea.firmament.annotations.Subscribe
|
||||||
|
import moe.nea.firmament.events.SlotRenderEvents
|
||||||
|
import moe.nea.firmament.features.FirmamentFeature
|
||||||
|
import moe.nea.firmament.gui.config.ManagedConfig
|
||||||
|
import moe.nea.firmament.util.MC
|
||||||
|
import moe.nea.firmament.util.petData
|
||||||
|
import moe.nea.firmament.util.unformattedString
|
||||||
|
import moe.nea.firmament.util.useMatch
|
||||||
|
|
||||||
|
object PetFeatures : FirmamentFeature {
|
||||||
|
override val identifier: String
|
||||||
|
get() = "pets"
|
||||||
|
|
||||||
|
override val config: ManagedConfig?
|
||||||
|
get() = TConfig
|
||||||
|
|
||||||
|
object TConfig : ManagedConfig(identifier) {
|
||||||
|
val highlightEquippedPet by toggle("highlight-pet") { true }
|
||||||
|
}
|
||||||
|
|
||||||
|
val petMenuTitle = "Pets(?: \\([0-9]+/[0-9]+\\))?".toPattern()
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
fun onSlotRender(event: SlotRenderEvents.Before) {
|
||||||
|
if (!TConfig.highlightEquippedPet) return
|
||||||
|
val stack = event.slot.stack
|
||||||
|
if (stack.petData?.active == true)
|
||||||
|
petMenuTitle.useMatch(MC.screenName ?: return) {
|
||||||
|
event.context.drawSprite(
|
||||||
|
event.slot.x, event.slot.y, 0, 16, 16,
|
||||||
|
MC.guiAtlasManager.getSprite(Identifier.of("firmament:selected_pet_background"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -86,6 +86,7 @@ object MC {
|
|||||||
inline var screen
|
inline var screen
|
||||||
get() = instance.currentScreen
|
get() = instance.currentScreen
|
||||||
set(value) = instance.setScreen(value)
|
set(value) = instance.setScreen(value)
|
||||||
|
val screenName get() = screen?.title?.unformattedString?.trim()
|
||||||
inline val handledScreen: HandledScreen<*>? get() = instance.currentScreen as? HandledScreen<*>
|
inline val handledScreen: HandledScreen<*>? get() = instance.currentScreen as? HandledScreen<*>
|
||||||
inline val window get() = instance.window
|
inline val window get() = instance.window
|
||||||
inline val currentRegistries: RegistryWrapper.WrapperLookup? get() = world?.registryManager
|
inline val currentRegistries: RegistryWrapper.WrapperLookup? get() = world?.registryManager
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
|
|
||||||
|
|
||||||
@file:UseSerializers(DashlessUUIDSerializer::class)
|
@file:UseSerializers(DashlessUUIDSerializer::class)
|
||||||
|
|
||||||
package moe.nea.firmament.util
|
package moe.nea.firmament.util
|
||||||
|
|
||||||
import io.github.moulberry.repo.data.NEUItem
|
import io.github.moulberry.repo.data.NEUItem
|
||||||
import io.github.moulberry.repo.data.Rarity
|
import io.github.moulberry.repo.data.Rarity
|
||||||
|
import java.util.Optional
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.UseSerializers
|
import kotlinx.serialization.UseSerializers
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlin.jvm.optionals.getOrNull
|
||||||
import net.minecraft.component.DataComponentTypes
|
import net.minecraft.component.DataComponentTypes
|
||||||
import net.minecraft.component.type.NbtComponent
|
import net.minecraft.component.type.NbtComponent
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.NbtCompound
|
import net.minecraft.nbt.NbtCompound
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import moe.nea.firmament.repo.set
|
import moe.nea.firmament.repo.set
|
||||||
|
import moe.nea.firmament.util.collections.WeakCache
|
||||||
import moe.nea.firmament.util.json.DashlessUUIDSerializer
|
import moe.nea.firmament.util.json.DashlessUUIDSerializer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,123 +28,126 @@ import moe.nea.firmament.util.json.DashlessUUIDSerializer
|
|||||||
@JvmInline
|
@JvmInline
|
||||||
@Serializable
|
@Serializable
|
||||||
value class SkyblockId(val neuItem: String) {
|
value class SkyblockId(val neuItem: String) {
|
||||||
val identifier
|
val identifier
|
||||||
get() = Identifier.of("skyblockitem",
|
get() = Identifier.of("skyblockitem",
|
||||||
neuItem.lowercase().replace(";", "__")
|
neuItem.lowercase().replace(";", "__")
|
||||||
.replace(":", "___")
|
.replace(":", "___")
|
||||||
.replace(illlegalPathRegex) {
|
.replace(illlegalPathRegex) {
|
||||||
it.value.toCharArray()
|
it.value.toCharArray()
|
||||||
.joinToString("") { "__" + it.code.toString(16).padStart(4, '0') }
|
.joinToString("") { "__" + it.code.toString(16).padStart(4, '0') }
|
||||||
})
|
})
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return neuItem
|
return neuItem
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bazaar stock item id, as returned by the HyPixel bazaar api endpoint.
|
* A bazaar stock item id, as returned by the HyPixel bazaar api endpoint.
|
||||||
* These are not equivalent to the in-game ids, or the NEU repo ids, and in fact, do not refer to items, but instead
|
* These are not equivalent to the in-game ids, or the NEU repo ids, and in fact, do not refer to items, but instead
|
||||||
* to bazaar stocks. The main difference from [SkyblockId]s is concerning enchanted books. There are probably more,
|
* to bazaar stocks. The main difference from [SkyblockId]s is concerning enchanted books. There are probably more,
|
||||||
* but for now this holds.
|
* but for now this holds.
|
||||||
*/
|
*/
|
||||||
@JvmInline
|
@JvmInline
|
||||||
@Serializable
|
@Serializable
|
||||||
value class BazaarStock(val bazaarId: String) {
|
value class BazaarStock(val bazaarId: String) {
|
||||||
fun toRepoId(): SkyblockId {
|
fun toRepoId(): SkyblockId {
|
||||||
bazaarEnchantmentRegex.matchEntire(bazaarId)?.let {
|
bazaarEnchantmentRegex.matchEntire(bazaarId)?.let {
|
||||||
return SkyblockId("${it.groupValues[1]};${it.groupValues[2]}")
|
return SkyblockId("${it.groupValues[1]};${it.groupValues[2]}")
|
||||||
}
|
}
|
||||||
return SkyblockId(bazaarId.replace(":", "-"))
|
return SkyblockId(bazaarId.replace(":", "-"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val COINS: SkyblockId = SkyblockId("SKYBLOCK_COIN")
|
val COINS: SkyblockId = SkyblockId("SKYBLOCK_COIN")
|
||||||
private val bazaarEnchantmentRegex = "ENCHANTMENT_(\\D*)_(\\d+)".toRegex()
|
private val bazaarEnchantmentRegex = "ENCHANTMENT_(\\D*)_(\\d+)".toRegex()
|
||||||
val NULL: SkyblockId = SkyblockId("null")
|
val NULL: SkyblockId = SkyblockId("null")
|
||||||
val PET_NULL: SkyblockId = SkyblockId("null_pet")
|
val PET_NULL: SkyblockId = SkyblockId("null_pet")
|
||||||
private val illlegalPathRegex = "[^a-z0-9_.-/]".toRegex()
|
private val illlegalPathRegex = "[^a-z0-9_.-/]".toRegex()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val NEUItem.skyblockId get() = SkyblockId(skyblockItemId)
|
val NEUItem.skyblockId get() = SkyblockId(skyblockItemId)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class HypixelPetInfo(
|
data class HypixelPetInfo(
|
||||||
val type: String,
|
val type: String,
|
||||||
val tier: Rarity,
|
val tier: Rarity,
|
||||||
val exp: Double = 0.0,
|
val exp: Double = 0.0,
|
||||||
val candyUsed: Int = 0,
|
val candyUsed: Int = 0,
|
||||||
val uuid: UUID? = null,
|
val uuid: UUID? = null,
|
||||||
|
val active: Boolean = false,
|
||||||
) {
|
) {
|
||||||
val skyblockId get() = SkyblockId("${type.uppercase()};${tier.ordinal}")
|
val skyblockId get() = SkyblockId("${type.uppercase()};${tier.ordinal}")
|
||||||
}
|
}
|
||||||
|
|
||||||
private val jsonparser = Json { ignoreUnknownKeys = true }
|
private val jsonparser = Json { ignoreUnknownKeys = true }
|
||||||
|
|
||||||
val ItemStack.extraAttributes: NbtCompound
|
val ItemStack.extraAttributes: NbtCompound
|
||||||
get() {
|
get() {
|
||||||
val customData = get(DataComponentTypes.CUSTOM_DATA) ?: run {
|
val customData = get(DataComponentTypes.CUSTOM_DATA) ?: run {
|
||||||
val component = NbtComponent.of(NbtCompound())
|
val component = NbtComponent.of(NbtCompound())
|
||||||
set(DataComponentTypes.CUSTOM_DATA, component)
|
set(DataComponentTypes.CUSTOM_DATA, component)
|
||||||
component
|
component
|
||||||
}
|
}
|
||||||
return customData.nbt
|
return customData.nbt
|
||||||
}
|
}
|
||||||
|
|
||||||
val ItemStack.skyblockUUIDString: String?
|
val ItemStack.skyblockUUIDString: String?
|
||||||
get() = extraAttributes.getString("uuid")?.takeIf { it.isNotBlank() }
|
get() = extraAttributes.getString("uuid")?.takeIf { it.isNotBlank() }
|
||||||
|
|
||||||
val ItemStack.skyblockUUID: UUID?
|
val ItemStack.skyblockUUID: UUID?
|
||||||
get() = skyblockUUIDString?.let { UUID.fromString(it) }
|
get() = skyblockUUIDString?.let { UUID.fromString(it) }
|
||||||
|
|
||||||
|
private val petDataCache = WeakCache.memoize<ItemStack, Optional<HypixelPetInfo>>("PetInfo") {
|
||||||
|
val jsonString = it.extraAttributes.getString("petInfo")
|
||||||
|
if (jsonString.isNullOrBlank()) return@memoize Optional.empty()
|
||||||
|
runCatching { jsonparser.decodeFromString<HypixelPetInfo>(jsonString) }
|
||||||
|
.getOrElse { null }.intoOptional()
|
||||||
|
}
|
||||||
|
|
||||||
val ItemStack.petData: HypixelPetInfo?
|
val ItemStack.petData: HypixelPetInfo?
|
||||||
get() {
|
get() = petDataCache(this).getOrNull()
|
||||||
val jsonString = extraAttributes.getString("petInfo")
|
|
||||||
if (jsonString.isNullOrBlank()) return null
|
|
||||||
return runCatching { jsonparser.decodeFromString<HypixelPetInfo>(jsonString) }
|
|
||||||
.getOrElse { return null }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ItemStack.setSkyBlockFirmamentUiId(uiId: String) = setSkyBlockId(SkyblockId("FIRMAMENT_UI_$uiId"))
|
fun ItemStack.setSkyBlockFirmamentUiId(uiId: String) = setSkyBlockId(SkyblockId("FIRMAMENT_UI_$uiId"))
|
||||||
fun ItemStack.setSkyBlockId(skyblockId: SkyblockId): ItemStack {
|
fun ItemStack.setSkyBlockId(skyblockId: SkyblockId): ItemStack {
|
||||||
this.extraAttributes["id"] = skyblockId.neuItem
|
this.extraAttributes["id"] = skyblockId.neuItem
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
val ItemStack.skyBlockId: SkyblockId?
|
val ItemStack.skyBlockId: SkyblockId?
|
||||||
get() {
|
get() {
|
||||||
return when (val id = extraAttributes.getString("id")) {
|
return when (val id = extraAttributes.getString("id")) {
|
||||||
"" -> {
|
"" -> {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
"PET" -> {
|
"PET" -> {
|
||||||
petData?.skyblockId ?: SkyblockId.PET_NULL
|
petData?.skyblockId ?: SkyblockId.PET_NULL
|
||||||
}
|
}
|
||||||
|
|
||||||
"RUNE", "UNIQUE_RUNE" -> {
|
"RUNE", "UNIQUE_RUNE" -> {
|
||||||
val runeData = extraAttributes.getCompound("runes")
|
val runeData = extraAttributes.getCompound("runes")
|
||||||
val runeKind = runeData.keys.singleOrNull()
|
val runeKind = runeData.keys.singleOrNull()
|
||||||
if (runeKind == null) SkyblockId("RUNE")
|
if (runeKind == null) SkyblockId("RUNE")
|
||||||
else SkyblockId("${runeKind.uppercase()}_RUNE;${runeData.getInt(runeKind)}")
|
else SkyblockId("${runeKind.uppercase()}_RUNE;${runeData.getInt(runeKind)}")
|
||||||
}
|
}
|
||||||
|
|
||||||
"ABICASE" -> {
|
"ABICASE" -> {
|
||||||
SkyblockId("ABICASE_${extraAttributes.getString("model").uppercase()}")
|
SkyblockId("ABICASE_${extraAttributes.getString("model").uppercase()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
"ENCHANTED_BOOK" -> {
|
"ENCHANTED_BOOK" -> {
|
||||||
val enchantmentData = extraAttributes.getCompound("enchantments")
|
val enchantmentData = extraAttributes.getCompound("enchantments")
|
||||||
val enchantName = enchantmentData.keys.singleOrNull()
|
val enchantName = enchantmentData.keys.singleOrNull()
|
||||||
if (enchantName == null) SkyblockId("ENCHANTED_BOOK")
|
if (enchantName == null) SkyblockId("ENCHANTED_BOOK")
|
||||||
else SkyblockId("${enchantName.uppercase()};${enchantmentData.getInt(enchantName)}")
|
else SkyblockId("${enchantName.uppercase()};${enchantmentData.getInt(enchantName)}")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: PARTY_HAT_CRAB{,_ANIMATED,_SLOTH},POTION
|
// TODO: PARTY_HAT_CRAB{,_ANIMATED,_SLOTH},POTION
|
||||||
else -> {
|
else -> {
|
||||||
SkyblockId(id)
|
SkyblockId(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,8 @@
|
|||||||
"firmament.config.repo.disable-item-groups": "Disable Item Groups",
|
"firmament.config.repo.disable-item-groups": "Disable Item Groups",
|
||||||
"firmament.config.repo.reload": "Reload Item List",
|
"firmament.config.repo.reload": "Reload Item List",
|
||||||
"firmament.config.repo.redownload": "Redownload Item List",
|
"firmament.config.repo.redownload": "Redownload Item List",
|
||||||
|
"firmament.config.pets": "Pets",
|
||||||
|
"firmament.config.pets.highlight-pet": "Highlight active pet",
|
||||||
"firmament.ursa.debugrequest.start": "Ursa request launched",
|
"firmament.ursa.debugrequest.start": "Ursa request launched",
|
||||||
"firmament.ursa.debugrequest.result": "Ursa request succeeded: %s",
|
"firmament.ursa.debugrequest.result": "Ursa request succeeded: %s",
|
||||||
"firmament.sbinfo.nolocraw": "No locraw data available",
|
"firmament.sbinfo.nolocraw": "No locraw data available",
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 558 B |
Reference in New Issue
Block a user