diff options
author | nea <nea@nea.moe> | 2023-06-11 02:43:14 +0200 |
---|---|---|
committer | nea <nea@nea.moe> | 2023-06-11 02:43:14 +0200 |
commit | a36c8f1c0eae969dcee8cf690f12d9121350212d (patch) | |
tree | ea93f19bf5f77f8b5e42a7b56162d9b6492b7fed | |
parent | 040f7c7275568d783bfa5e4ed20412f72d126549 (diff) | |
download | firmament-a36c8f1c0eae969dcee8cf690f12d9121350212d.tar.gz firmament-a36c8f1c0eae969dcee8cf690f12d9121350212d.tar.bz2 firmament-a36c8f1c0eae969dcee8cf690f12d9121350212d.zip |
Add collection info to skill page
-rw-r--r-- | TODO.txt | 1 | ||||
-rw-r--r-- | URGENT.txt | 3 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/firmament/Firmament.kt | 4 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/firmament/apis/Profiles.kt | 57 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/firmament/commands/rome.kt | 7 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/firmament/gui/WTitledItem.kt | 26 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/firmament/gui/profileviewer/PetsPage.kt | 13 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/firmament/gui/profileviewer/SkillPage.kt | 100 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/firmament/repo/HypixelStaticData.kt (renamed from src/main/kotlin/moe/nea/firmament/repo/ItemCostData.kt) | 23 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/firmament/util/ItemUtil.kt | 10 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/firmament/util/MC.kt | 1 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/firmament/util/colorconversion.kt | 5 |
12 files changed, 210 insertions, 40 deletions
@@ -19,6 +19,7 @@ - Dungeon Map Priority 2: +- missing talismans / pets in pv - item overlays - tree capitator - builders wand @@ -7,9 +7,6 @@ - More wider - Pet level stat - Item List: - - Fix crafting recipes for vanilla items - - Either remove vanilla items and replace them - - Or remove vanilla (crafting recipes) - Add other recipe types (prio -1) - Fix banner data fixer (prio -1) 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 @@ -20,6 +20,32 @@ import moe.nea.firmament.util.json.InstantAsLongSerializer @Serializable +data class CollectionSkillData( + val items: Map<CollectionType, CollectionInfo> +) + +@Serializable +data class CollectionResponse( + val success: Boolean, + val collections: Map<Skill, CollectionSkillData> +) + +@Serializable +data class CollectionInfo( + val name: String, + val maxTiers: Int, + val tiers: List<CollectionTier> +) + +@Serializable +data class CollectionTier( + val tier: Int, + val amountRequired: Long, + val unlocks: List<String>, +) + + +@Serializable data class Profiles( val success: Boolean, val profiles: List<Profile>? @@ -35,18 +61,18 @@ data class Profile( val members: Map<UUID, Member>, ) -enum class Skill(val accessor: KProperty1<Member, Double>, 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<Member, Double>, 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") @@ -59,6 +85,12 @@ enum class Skill(val accessor: KProperty1<Member, Double>, 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<Pet> = listOf(), @SerialName("coop_invitation") @@ -85,6 +117,7 @@ data class Member( val experienceSkillRunecrafting: Double = 0.0, @SerialName("experience_skill_carpentry") val experienceSkillCarpentry: Double = 0.0, + val collection: Map<CollectionType, Long> = 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<WPanel>() + 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/ItemCostData.kt b/src/main/kotlin/moe/nea/firmament/repo/HypixelStaticData.kt index a1084b9..f2a2668 100644 --- a/src/main/kotlin/moe/nea/firmament/repo/ItemCostData.kt +++ b/src/main/kotlin/moe/nea/firmament/repo/HypixelStaticData.kt @@ -12,18 +12,23 @@ 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 ItemCostData { - private val logger = LogManager.getLogger("Firmament.ItemCostData") +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<SkyblockId, Double> = mapOf() private set var bazaarData: Map<SkyblockId, BazaarData> = mapOf() private set + var collectionData: Map<Skill, CollectionSkillData> = mapOf() + private set @Serializable data class BazaarData( @@ -53,7 +58,9 @@ object ItemCostData { fun getPriceOfItem(item: SkyblockId): Double? = bazaarData[item]?.quickStatus?.buyPrice ?: lowestBin[item] - fun spawnPriceLoop() { + + fun spawnDataCollectionLoop() { + Firmament.coroutineScope.launch { updateCollectionData() } Firmament.coroutineScope.launch { while (true) { logger.info("Updating NEU prices") @@ -83,4 +90,14 @@ object ItemCostData { bazaarData = response.products.mapKeys { it.key.toRepoId() } } + private suspend fun updateCollectionData() { + val response = + Firmament.httpClient.get("$hypixelApiBaseUrl/resources/skyblock/collections").body<CollectionResponse>() + 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/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<Text>) { } } +fun ItemStack.modifyLore(update: (List<Text>) -> List<Text>) { + 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) + |