From a36c8f1c0eae969dcee8cf690f12d9121350212d Mon Sep 17 00:00:00 2001 From: nea Date: Sun, 11 Jun 2023 02:43:14 +0200 Subject: Add collection info to skill page --- src/main/kotlin/moe/nea/firmament/Firmament.kt | 4 +- src/main/kotlin/moe/nea/firmament/apis/Profiles.kt | 57 +++++++++--- src/main/kotlin/moe/nea/firmament/commands/rome.kt | 7 +- .../kotlin/moe/nea/firmament/gui/WTitledItem.kt | 26 ++++++ .../nea/firmament/gui/profileviewer/PetsPage.kt | 13 +-- .../nea/firmament/gui/profileviewer/SkillPage.kt | 100 ++++++++++++++++++-- .../moe/nea/firmament/repo/HypixelStaticData.kt | 103 +++++++++++++++++++++ .../kotlin/moe/nea/firmament/repo/ItemCostData.kt | 86 ----------------- src/main/kotlin/moe/nea/firmament/util/ItemUtil.kt | 10 ++ src/main/kotlin/moe/nea/firmament/util/MC.kt | 1 + .../moe/nea/firmament/util/colorconversion.kt | 5 + 11 files changed, 292 insertions(+), 120 deletions(-) create mode 100644 src/main/kotlin/moe/nea/firmament/gui/WTitledItem.kt create mode 100644 src/main/kotlin/moe/nea/firmament/repo/HypixelStaticData.kt delete mode 100644 src/main/kotlin/moe/nea/firmament/repo/ItemCostData.kt (limited to 'src/main/kotlin/moe/nea/firmament') diff --git a/src/main/kotlin/moe/nea/firmament/Firmament.kt b/src/main/kotlin/moe/nea/firmament/Firmament.kt index f130742..2e1cd05 100644 --- a/src/main/kotlin/moe/nea/firmament/Firmament.kt +++ b/src/main/kotlin/moe/nea/firmament/Firmament.kt @@ -50,7 +50,7 @@ import net.minecraft.util.Identifier import moe.nea.firmament.commands.registerFirmamentCommand import moe.nea.firmament.dbus.FirmamentDbusObject import moe.nea.firmament.features.FeatureManager -import moe.nea.firmament.repo.ItemCostData +import moe.nea.firmament.repo.HypixelStaticData import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.util.SBData import moe.nea.firmament.util.data.IDataHolder @@ -119,7 +119,7 @@ object Firmament { RepoManager.initialize() SBData.init() FeatureManager.autoload() - ItemCostData.spawnPriceLoop() + HypixelStaticData.spawnDataCollectionLoop() ClientCommandRegistrationCallback.EVENT.register(this::registerCommands) ClientLifecycleEvents.CLIENT_STOPPING.register(ClientLifecycleEvents.ClientStopping { runBlocking { diff --git a/src/main/kotlin/moe/nea/firmament/apis/Profiles.kt b/src/main/kotlin/moe/nea/firmament/apis/Profiles.kt index 4d4f370..ae23349 100644 --- a/src/main/kotlin/moe/nea/firmament/apis/Profiles.kt +++ b/src/main/kotlin/moe/nea/firmament/apis/Profiles.kt @@ -19,6 +19,32 @@ import moe.nea.firmament.util.json.DashlessUUIDSerializer import moe.nea.firmament.util.json.InstantAsLongSerializer +@Serializable +data class CollectionSkillData( + val items: Map +) + +@Serializable +data class CollectionResponse( + val success: Boolean, + val collections: Map +) + +@Serializable +data class CollectionInfo( + val name: String, + val maxTiers: Int, + val tiers: List +) + +@Serializable +data class CollectionTier( + val tier: Int, + val amountRequired: Long, + val unlocks: List, +) + + @Serializable data class Profiles( val success: Boolean, @@ -35,18 +61,18 @@ data class Profile( val members: Map, ) -enum class Skill(val accessor: KProperty1, val color: DyeColor) { - FARMING(Member::experienceSkillFarming, DyeColor.YELLOW), - FORAGING(Member::experienceSkillForaging, DyeColor.BROWN), - MINING(Member::experienceSkillMining, DyeColor.LIGHT_GRAY), - ALCHEMY(Member::experienceSkillAlchemy, DyeColor.PURPLE), - TAMING(Member::experienceSkillTaming, DyeColor.GREEN), - FISHING(Member::experienceSkillFishing, DyeColor.BLUE), - RUNECRAFTING(Member::experienceSkillRunecrafting, DyeColor.PINK), - CARPENTRY(Member::experienceSkillCarpentry, DyeColor.ORANGE), - COMBAT(Member::experienceSkillCombat, DyeColor.RED), - SOCIAL(Member::experienceSkillSocial, DyeColor.WHITE), - ENCHANTING(Member::experienceSkillEnchanting, DyeColor.MAGENTA), +enum class Skill(val accessor: KProperty1, val color: DyeColor, val icon: SkyblockId) { + FARMING(Member::experienceSkillFarming, DyeColor.YELLOW, SkyblockId("ROOKIE_HOE")), + FORAGING(Member::experienceSkillForaging, DyeColor.BROWN, SkyblockId("TREECAPITATOR_AXE")), + MINING(Member::experienceSkillMining, DyeColor.LIGHT_GRAY, SkyblockId("DIAMOND_PICKAXE")), + ALCHEMY(Member::experienceSkillAlchemy, DyeColor.PURPLE, SkyblockId("BREWING_STAND")), + TAMING(Member::experienceSkillTaming, DyeColor.GREEN, SkyblockId("SUPER_EGG")), + FISHING(Member::experienceSkillFishing, DyeColor.BLUE, SkyblockId("FARMER_ROD")), + RUNECRAFTING(Member::experienceSkillRunecrafting, DyeColor.PINK, SkyblockId("MUSIC_RUNE;1")), + CARPENTRY(Member::experienceSkillCarpentry, DyeColor.ORANGE, SkyblockId("WORKBENCH")), + COMBAT(Member::experienceSkillCombat, DyeColor.RED, SkyblockId("UNDEAD_SWORD")), + SOCIAL(Member::experienceSkillSocial, DyeColor.WHITE, SkyblockId("EGG_HUNT")), + ENCHANTING(Member::experienceSkillEnchanting, DyeColor.MAGENTA, SkyblockId("ENCHANTMENT_TABLE")), ; fun getMaximumLevel(leveling: Leveling) = leveling.maximumLevels[name.lowercase()] ?: TODO("Repo error") @@ -58,6 +84,12 @@ enum class Skill(val accessor: KProperty1, val color: DyeColor) } } +@Serializable +@JvmInline +value class CollectionType(val string: String) { + val skyblockId get() = SkyblockId(string.replace(":", "-").replace("MUSHROOM_COLLECTION", "HUGE_MUSHROOM_2")) +} + @Serializable data class Member( val pets: List = listOf(), @@ -85,6 +117,7 @@ data class Member( val experienceSkillRunecrafting: Double = 0.0, @SerialName("experience_skill_carpentry") val experienceSkillCarpentry: Double = 0.0, + val collection: Map = mapOf() ) @Serializable diff --git a/src/main/kotlin/moe/nea/firmament/commands/rome.kt b/src/main/kotlin/moe/nea/firmament/commands/rome.kt index ff8c21e..2237abd 100644 --- a/src/main/kotlin/moe/nea/firmament/commands/rome.kt +++ b/src/main/kotlin/moe/nea/firmament/commands/rome.kt @@ -19,14 +19,13 @@ package moe.nea.firmament.commands import com.mojang.brigadier.CommandDispatcher -import com.mojang.brigadier.arguments.StringArgumentType.getString import com.mojang.brigadier.arguments.StringArgumentType.string import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource import net.minecraft.text.Text import moe.nea.firmament.features.world.FairySouls import moe.nea.firmament.gui.config.AllConfigsGui import moe.nea.firmament.gui.profileviewer.ProfileViewer -import moe.nea.firmament.repo.ItemCostData +import moe.nea.firmament.repo.HypixelStaticData import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.util.FirmFormatters import moe.nea.firmament.util.MC @@ -74,7 +73,7 @@ fun firmamentCommand() = literal("firmament") { thenExecute { val itemName = SkyblockId(get(item)) source.sendFeedback(Text.translatable("firmament.price", itemName.neuItem)) - val bazaarData = ItemCostData.bazaarData[itemName] + val bazaarData = HypixelStaticData.bazaarData[itemName] if (bazaarData != null) { source.sendFeedback(Text.translatable("firmament.price.bazaar")) source.sendFeedback( @@ -108,7 +107,7 @@ fun firmamentCommand() = literal("firmament") { ) ) } - val lowestBin = ItemCostData.lowestBin[itemName] + val lowestBin = HypixelStaticData.lowestBin[itemName] if (lowestBin != null) { source.sendFeedback( Text.translatable( diff --git a/src/main/kotlin/moe/nea/firmament/gui/WTitledItem.kt b/src/main/kotlin/moe/nea/firmament/gui/WTitledItem.kt new file mode 100644 index 0000000..ff9e894 --- /dev/null +++ b/src/main/kotlin/moe/nea/firmament/gui/WTitledItem.kt @@ -0,0 +1,26 @@ +package moe.nea.firmament.gui + +import io.github.cottonmc.cotton.gui.client.BackgroundPainter +import io.github.cottonmc.cotton.gui.widget.TooltipBuilder +import io.github.cottonmc.cotton.gui.widget.WItem +import net.minecraft.client.gui.DrawContext +import net.minecraft.client.item.TooltipContext +import net.minecraft.item.ItemStack +import net.minecraft.text.Text +import moe.nea.firmament.util.MC + +class WTitledItem(val stack: ItemStack, val countString: Text = Text.empty()) : WItem(stack) { + override fun paint(context: DrawContext, x: Int, y: Int, mouseX: Int, mouseY: Int) { + BackgroundPainter.SLOT.paintBackground(context, x, y, this) + super.paint(context, x, y, mouseX, mouseY) + context.matrices.push() + context.matrices.translate(0F, 0F, 200F) + context.drawText(MC.font, countString, x + 19 - 2 - MC.font.getWidth(countString), y + 6 + 3, 0xFFFFFF, true) + context.matrices.push() + } + + override fun addTooltip(tooltip: TooltipBuilder) { + tooltip.add(*stack.getTooltip(null, TooltipContext.BASIC).toTypedArray()) + } + +} diff --git a/src/main/kotlin/moe/nea/firmament/gui/profileviewer/PetsPage.kt b/src/main/kotlin/moe/nea/firmament/gui/profileviewer/PetsPage.kt index 62889bd..20e11e7 100644 --- a/src/main/kotlin/moe/nea/firmament/gui/profileviewer/PetsPage.kt +++ b/src/main/kotlin/moe/nea/firmament/gui/profileviewer/PetsPage.kt @@ -14,8 +14,10 @@ import net.minecraft.client.item.TooltipContext import net.minecraft.item.Items import net.minecraft.text.Text import moe.nea.firmament.gui.WTightScrollPanel +import moe.nea.firmament.gui.WTitledItem import moe.nea.firmament.rei.PetData import moe.nea.firmament.rei.SBItemStack +import moe.nea.firmament.repo.RepoManager object PetsPage : ProfilePage { override fun getElements(profileViewer: ProfileViewer): WWidget { @@ -26,16 +28,7 @@ object PetsPage : ProfilePage { it.setGaps(8, 8) for ((i, pet) in profileViewer.member.pets.withIndex()) { val stack = SBItemStack(pet.itemId, PetData(pet.tier, pet.type.name, pet.exp)).asItemStack() - it.add(object : WItem(stack) { - override fun paint(context: DrawContext?, x: Int, y: Int, mouseX: Int, mouseY: Int) { - BackgroundPainter.SLOT.paintBackground(context, x, y, this) - super.paint(context, x, y, mouseX, mouseY) - } - - override fun addTooltip(tooltip: TooltipBuilder) { - tooltip.add(*stack.getTooltip(null, TooltipContext.BASIC).toTypedArray()) - } - }, i % 5, i / 5, 1, 1) + it.add(WTitledItem(stack), i % 5, i / 5, 1, 1) } it.layout() })), 0, 1, 8, 8) diff --git a/src/main/kotlin/moe/nea/firmament/gui/profileviewer/SkillPage.kt b/src/main/kotlin/moe/nea/firmament/gui/profileviewer/SkillPage.kt index c750101..2de217e 100644 --- a/src/main/kotlin/moe/nea/firmament/gui/profileviewer/SkillPage.kt +++ b/src/main/kotlin/moe/nea/firmament/gui/profileviewer/SkillPage.kt @@ -1,20 +1,39 @@ package moe.nea.firmament.gui.profileviewer import io.github.cottonmc.cotton.gui.widget.TooltipBuilder +import io.github.cottonmc.cotton.gui.widget.WBox import io.github.cottonmc.cotton.gui.widget.WGridPanel +import io.github.cottonmc.cotton.gui.widget.WPanel +import io.github.cottonmc.cotton.gui.widget.WTabPanel import io.github.cottonmc.cotton.gui.widget.WText import io.github.cottonmc.cotton.gui.widget.WWidget +import io.github.cottonmc.cotton.gui.widget.data.Axis +import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment import io.github.cottonmc.cotton.gui.widget.data.Insets import io.github.cottonmc.cotton.gui.widget.icon.Icon import io.github.cottonmc.cotton.gui.widget.icon.ItemIcon import net.minecraft.item.ItemStack import net.minecraft.item.Items +import net.minecraft.text.Style import net.minecraft.text.Text +import net.minecraft.util.Formatting +import moe.nea.firmament.apis.CollectionInfo +import moe.nea.firmament.apis.CollectionType +import moe.nea.firmament.apis.Member import moe.nea.firmament.apis.Skill import moe.nea.firmament.gui.WBar +import moe.nea.firmament.gui.WFixedPanel +import moe.nea.firmament.gui.WTitledItem +import moe.nea.firmament.hud.horizontal +import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry +import moe.nea.firmament.rei.SBItemEntryDefinition +import moe.nea.firmament.repo.HypixelStaticData +import moe.nea.firmament.repo.ItemCache.asItemStack import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.util.FirmFormatters +import moe.nea.firmament.util.modifyLore import moe.nea.firmament.util.toShedaniel +import moe.nea.firmament.util.toTextColor object SkillPage : ProfilePage { @@ -37,14 +56,83 @@ object SkillPage : ProfilePage { } } + private fun collectionItem(type: CollectionType, info: CollectionInfo, skill: Skill, member: Member): WWidget { + val collectionCount = member.collection[type] ?: 0 + val unlockedTiers = info.tiers.count { it.amountRequired <= collectionCount } + return WTitledItem( + SBItemEntryDefinition.getEntry(type.skyblockId).asItemEntry().value.copy() + .also { + it.setCustomName( + Text.literal(info.name).fillStyle( + Style.EMPTY.withItalic(false).withBold(true) + .withColor(skill.color.toTextColor()) + ) + ) + it.modifyLore { old -> + listOf( + Text.literal("${info.name} Collection: $collectionCount / ${info.tiers.last().amountRequired}"), + Text.literal("Tiers unlocked: $unlockedTiers") + ).map { + it.fillStyle( + Style.EMPTY.withItalic(false).withColor(Formatting.GRAY) + ) + } + } + }, countString = Text.literal("$unlockedTiers").styled { + if (unlockedTiers == info.maxTiers) + it.withColor(Formatting.YELLOW) + else it + } + ) + } + + private fun collectionPanel(profileViewer: ProfileViewer): WTabPanel { + return WTabPanel().also { + val data = HypixelStaticData.collectionData + val panels = mutableListOf() + for ((skill, collections) in data.entries) { + val panel = WBox(Axis.HORIZONTAL).also { + it.horizontalAlignment = HorizontalAlignment.CENTER + it.add(WFixedPanel(WGridPanel().also { + it.insets = Insets.ROOT_PANEL + it.setGaps(2, 2) + var x = 0 + var y = 0 + for (item in collections.items) { + it.add(collectionItem(item.key, item.value, skill, profileViewer.member), x, y, 1, 1) + x++ + if (x == 5) { + x = 0 + y++ + } + } + })) + } + panels.add(panel) + it.add(panel) { + it.tooltip( + Text.translatable("firmament.pv.skills.${skill.name.lowercase()}") + .styled { it.withColor(skill.color.toTextColor()) }) + it.icon(ItemIcon(RepoManager.getNEUItem(skill.icon).asItemStack())) + } + } + it.layout() + val tabWidth = it.width + panels.forEach { it.setSize(tabWidth - Insets.ROOT_PANEL.horizontal, it.height) } + } + } + override fun getElements(profileViewer: ProfileViewer): WWidget { - return WGridPanel().also { + return WBox(Axis.HORIZONTAL).also { it.insets = Insets.ROOT_PANEL - it.add(WText(Text.literal(profileViewer.account.getDisplayName())), 0, 0, 6, 1) - for ((i, skill) in Skill.values().withIndex()) { - it.add(WText(Text.translatable("firmament.pv.skills.${skill.name.lowercase()}")), 0, i + 1, 4, 1) - it.add(skillBar(profileViewer, skill), 4, i + 1, 4, 1) - } + it.add(WGridPanel().also { + it.add(WText(Text.literal(profileViewer.account.getDisplayName())), 0, 0, 8, 1) + for ((i, skill) in Skill.values().withIndex()) { + it.add(WText(Text.translatable("firmament.pv.skills.${skill.name.lowercase()}")), 0, i + 1, 4, 1) + it.add(skillBar(profileViewer, skill), 4, i + 1, 4, 1) + } + }) + it.add(collectionPanel(profileViewer)) } } diff --git a/src/main/kotlin/moe/nea/firmament/repo/HypixelStaticData.kt b/src/main/kotlin/moe/nea/firmament/repo/HypixelStaticData.kt new file mode 100644 index 0000000..f2a2668 --- /dev/null +++ b/src/main/kotlin/moe/nea/firmament/repo/HypixelStaticData.kt @@ -0,0 +1,103 @@ +package moe.nea.firmament.repo + +import io.ktor.client.call.body +import io.ktor.client.request.get +import org.apache.logging.log4j.LogManager +import org.lwjgl.glfw.GLFW +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.launch +import kotlinx.coroutines.withTimeoutOrNull +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlin.time.Duration.Companion.minutes +import moe.nea.firmament.Firmament +import moe.nea.firmament.apis.CollectionResponse +import moe.nea.firmament.apis.CollectionSkillData +import moe.nea.firmament.apis.Skill +import moe.nea.firmament.keybindings.IKeyBinding +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.async.waitForInput + +object HypixelStaticData { + private val logger = LogManager.getLogger("Firmament.HypixelStaticData") + private val moulberryBaseUrl = "https://moulberry.codes" + private val hypixelApiBaseUrl = "https://api.hypixel.net" + var lowestBin: Map = mapOf() + private set + var bazaarData: Map = mapOf() + private set + var collectionData: Map = mapOf() + private set + + @Serializable + data class BazaarData( + @SerialName("product_id") + val productId: SkyblockId.BazaarStock, + @SerialName("quick_status") + val quickStatus: BazaarStatus, + ) + + @Serializable + data class BazaarStatus( + val sellPrice: Double, + val sellVolume: Long, + val sellMovingWeek: Long, + val sellOrders: Long, + val buyPrice: Double, + val buyVolume: Long, + val buyMovingWeek: Long, + val buyOrders: Long + ) + + @Serializable + private data class BazaarResponse( + val success: Boolean, + val products: Map = mapOf(), + ) + + fun getPriceOfItem(item: SkyblockId): Double? = bazaarData[item]?.quickStatus?.buyPrice ?: lowestBin[item] + + + fun spawnDataCollectionLoop() { + Firmament.coroutineScope.launch { updateCollectionData() } + Firmament.coroutineScope.launch { + while (true) { + logger.info("Updating NEU prices") + updatePrices() + withTimeoutOrNull(10.minutes) { waitForInput(IKeyBinding.ofKeyCode(GLFW.GLFW_KEY_U)) } + } + } + } + + private suspend fun updatePrices() { + awaitAll( + Firmament.coroutineScope.async { fetchBazaarPrices() }, + Firmament.coroutineScope.async { fetchPricesFromMoulberry() }, + ) + } + + private suspend fun fetchPricesFromMoulberry() { + lowestBin = Firmament.httpClient.get("$moulberryBaseUrl/lowestbin.json") + .body>() + } + + private suspend fun fetchBazaarPrices() { + val response = Firmament.httpClient.get("$hypixelApiBaseUrl/skyblock/bazaar").body() + if (!response.success) { + logger.warn("Retrieved unsuccessful bazaar data") + } + bazaarData = response.products.mapKeys { it.key.toRepoId() } + } + + private suspend fun updateCollectionData() { + val response = + Firmament.httpClient.get("$hypixelApiBaseUrl/resources/skyblock/collections").body() + if (!response.success) { + logger.warn("Retrieved unsuccessful collection data") + } + collectionData = response.collections + logger.info("Downloaded ${collectionData.values.sumOf { it.items.values.size }} collections") + } + +} diff --git a/src/main/kotlin/moe/nea/firmament/repo/ItemCostData.kt b/src/main/kotlin/moe/nea/firmament/repo/ItemCostData.kt deleted file mode 100644 index a1084b9..0000000 --- a/src/main/kotlin/moe/nea/firmament/repo/ItemCostData.kt +++ /dev/null @@ -1,86 +0,0 @@ -package moe.nea.firmament.repo - -import io.ktor.client.call.body -import io.ktor.client.request.get -import org.apache.logging.log4j.LogManager -import org.lwjgl.glfw.GLFW -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.launch -import kotlinx.coroutines.withTimeoutOrNull -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlin.time.Duration.Companion.minutes -import moe.nea.firmament.Firmament -import moe.nea.firmament.keybindings.IKeyBinding -import moe.nea.firmament.util.SkyblockId -import moe.nea.firmament.util.async.waitForInput - -object ItemCostData { - private val logger = LogManager.getLogger("Firmament.ItemCostData") - private val moulberryBaseUrl = "https://moulberry.codes" - private val hypixelApiBaseUrl = "https://api.hypixel.net" - var lowestBin: Map = mapOf() - private set - var bazaarData: Map = mapOf() - private set - - @Serializable - data class BazaarData( - @SerialName("product_id") - val productId: SkyblockId.BazaarStock, - @SerialName("quick_status") - val quickStatus: BazaarStatus, - ) - - @Serializable - data class BazaarStatus( - val sellPrice: Double, - val sellVolume: Long, - val sellMovingWeek: Long, - val sellOrders: Long, - val buyPrice: Double, - val buyVolume: Long, - val buyMovingWeek: Long, - val buyOrders: Long - ) - - @Serializable - private data class BazaarResponse( - val success: Boolean, - val products: Map = mapOf(), - ) - - fun getPriceOfItem(item: SkyblockId): Double? = bazaarData[item]?.quickStatus?.buyPrice ?: lowestBin[item] - - fun spawnPriceLoop() { - Firmament.coroutineScope.launch { - while (true) { - logger.info("Updating NEU prices") - updatePrices() - withTimeoutOrNull(10.minutes) { waitForInput(IKeyBinding.ofKeyCode(GLFW.GLFW_KEY_U)) } - } - } - } - - private suspend fun updatePrices() { - awaitAll( - Firmament.coroutineScope.async { fetchBazaarPrices() }, - Firmament.coroutineScope.async { fetchPricesFromMoulberry() }, - ) - } - - private suspend fun fetchPricesFromMoulberry() { - lowestBin = Firmament.httpClient.get("$moulberryBaseUrl/lowestbin.json") - .body>() - } - - private suspend fun fetchBazaarPrices() { - val response = Firmament.httpClient.get("$hypixelApiBaseUrl/skyblock/bazaar").body() - if (!response.success) { - logger.warn("Retrieved unsuccessful bazaar data") - } - bazaarData = response.products.mapKeys { it.key.toRepoId() } - } - -} diff --git a/src/main/kotlin/moe/nea/firmament/util/ItemUtil.kt b/src/main/kotlin/moe/nea/firmament/util/ItemUtil.kt index 25fb7d3..78627cd 100644 --- a/src/main/kotlin/moe/nea/firmament/util/ItemUtil.kt +++ b/src/main/kotlin/moe/nea/firmament/util/ItemUtil.kt @@ -33,6 +33,16 @@ fun ItemStack.appendLore(args: List) { } } +fun ItemStack.modifyLore(update: (List) -> List) { + val compoundTag = getOrCreateSubNbt("display") + val loreList = compoundTag.getOrCreateList("Lore", NbtString.STRING_TYPE) + val parsed = loreList.map { Text.Serializer.fromJson(it.asString())!! } + val updated = update(parsed) + loreList.clear() + loreList.addAll(updated.map { NbtString.of(Text.Serializer.toJson(it)) }) +} + + fun NbtCompound.getOrCreateList(label: String, tag: Byte): NbtList = getList(label, tag.toInt()).also { put(label, it) } diff --git a/src/main/kotlin/moe/nea/firmament/util/MC.kt b/src/main/kotlin/moe/nea/firmament/util/MC.kt index 53bad8b..e9ab6c9 100644 --- a/src/main/kotlin/moe/nea/firmament/util/MC.kt +++ b/src/main/kotlin/moe/nea/firmament/util/MC.kt @@ -24,6 +24,7 @@ import net.minecraft.client.gui.screen.ingame.HandledScreen import net.minecraft.util.math.BlockPos object MC { + inline val font get() = MinecraftClient.getInstance().textRenderer inline val soundManager get() = MinecraftClient.getInstance().soundManager inline val player get() = MinecraftClient.getInstance().player inline val world get() = MinecraftClient.getInstance().world diff --git a/src/main/kotlin/moe/nea/firmament/util/colorconversion.kt b/src/main/kotlin/moe/nea/firmament/util/colorconversion.kt index c19eefa..5da9f22 100644 --- a/src/main/kotlin/moe/nea/firmament/util/colorconversion.kt +++ b/src/main/kotlin/moe/nea/firmament/util/colorconversion.kt @@ -1,6 +1,11 @@ package moe.nea.firmament.util +import net.minecraft.text.TextColor import net.minecraft.util.DyeColor fun DyeColor.toShedaniel(): me.shedaniel.math.Color = me.shedaniel.math.Color.ofOpaque(this.signColor) + +fun DyeColor.toTextColor(): TextColor = + TextColor.fromRgb(this.signColor) + -- cgit