Add collection info to skill page
This commit is contained in:
1
TODO.txt
1
TODO.txt
@@ -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)
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<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,
|
||||
@@ -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")
|
||||
@@ -58,6 +84,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(),
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
26
src/main/kotlin/moe/nea/firmament/gui/WTitledItem.kt
Normal file
26
src/main/kotlin/moe/nea/firmament/gui/WTitledItem.kt
Normal file
@@ -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())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getElements(profileViewer: ProfileViewer): WWidget {
|
||||
return WGridPanel().also {
|
||||
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.add(WText(Text.literal(profileViewer.account.getDisplayName())), 0, 0, 6, 1)
|
||||
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 WBox(Axis.HORIZONTAL).also {
|
||||
it.insets = Insets.ROOT_PANEL
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user