[WIP] Add really shitty pv. This is mostly so I have something to be bothered to improve
This commit is contained in:
108
src/main/kotlin/moe/nea/firmament/apis/Profiles.kt
Normal file
108
src/main/kotlin/moe/nea/firmament/apis/Profiles.kt
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
@file:UseSerializers(DashlessUUIDSerializer::class, InstantAsLongSerializer::class)
|
||||||
|
|
||||||
|
package moe.nea.firmament.apis
|
||||||
|
|
||||||
|
import io.github.moulberry.repo.constants.Leveling
|
||||||
|
import io.github.moulberry.repo.data.Rarity
|
||||||
|
import java.util.UUID
|
||||||
|
import kotlinx.datetime.Instant
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.UseSerializers
|
||||||
|
import kotlin.reflect.KProperty1
|
||||||
|
import moe.nea.firmament.util.json.DashlessUUIDSerializer
|
||||||
|
import moe.nea.firmament.util.json.InstantAsLongSerializer
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Profiles(
|
||||||
|
val success: Boolean,
|
||||||
|
val profiles: List<Profile>
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Profile(
|
||||||
|
@SerialName("profile_id")
|
||||||
|
val profileId: UUID,
|
||||||
|
@SerialName("cute_name")
|
||||||
|
val cuteName: String,
|
||||||
|
val selected: Boolean = false,
|
||||||
|
val members: Map<UUID, Member>,
|
||||||
|
)
|
||||||
|
|
||||||
|
enum class Skill(val accessor: KProperty1<Member, Double>) {
|
||||||
|
FARMING(Member::experienceSkillFarming),
|
||||||
|
FORAGING(Member::experienceSkillForaging),
|
||||||
|
MINING(Member::experienceSkillMining),
|
||||||
|
ALCHEMY(Member::experienceSkillAlchemy),
|
||||||
|
TAMING(Member::experienceSkillTaming),
|
||||||
|
FISHING(Member::experienceSkillFishing),
|
||||||
|
RUNECRAFTING(Member::experienceSkillRunecrafting),
|
||||||
|
CARPENTRY(Member::experienceSkillCarpentry),
|
||||||
|
COMBAT(Member::experienceSkillCombat),
|
||||||
|
SOCIAL(Member::experienceSkillSocial),
|
||||||
|
ENCHANTING(Member::experienceSkillEnchanting),
|
||||||
|
;
|
||||||
|
|
||||||
|
fun getMaximumLevel(leveling: Leveling) = leveling.maximumLevels[name.lowercase()] ?: TODO("Repo error")
|
||||||
|
|
||||||
|
fun getLadder(leveling: Leveling): List<Int> {
|
||||||
|
if (this == SOCIAL) return leveling.socialExperienceRequiredPerLevel
|
||||||
|
if (this == RUNECRAFTING) return leveling.runecraftingExperienceRequiredPerLevel
|
||||||
|
return leveling.skillExperienceRequiredPerLevel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Member(
|
||||||
|
val pets: List<Pet>,
|
||||||
|
@SerialName("coop_invitation")
|
||||||
|
val coopInvitation: CoopInvitation? = null,
|
||||||
|
@SerialName("experience_skill_farming")
|
||||||
|
val experienceSkillFarming: Double = 0.0,
|
||||||
|
@SerialName("experience_skill_alchemy")
|
||||||
|
val experienceSkillAlchemy: Double = 0.0,
|
||||||
|
@SerialName("experience_skill_combat")
|
||||||
|
val experienceSkillCombat: Double = 0.0,
|
||||||
|
@SerialName("experience_skill_taming")
|
||||||
|
val experienceSkillTaming: Double = 0.0,
|
||||||
|
@SerialName("experience_skill_social2")
|
||||||
|
val experienceSkillSocial: Double = 0.0,
|
||||||
|
@SerialName("experience_skill_enchanting")
|
||||||
|
val experienceSkillEnchanting: Double = 0.0,
|
||||||
|
@SerialName("experience_skill_fishing")
|
||||||
|
val experienceSkillFishing: Double = 0.0,
|
||||||
|
@SerialName("experience_skill_foraging")
|
||||||
|
val experienceSkillForaging: Double = 0.0,
|
||||||
|
@SerialName("experience_skill_mining")
|
||||||
|
val experienceSkillMining: Double = 0.0,
|
||||||
|
@SerialName("experience_skill_runecrafting")
|
||||||
|
val experienceSkillRunecrafting: Double = 0.0,
|
||||||
|
@SerialName("experience_skill_carpentry")
|
||||||
|
val experienceSkillCarpentry: Double = 0.0,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class CoopInvitation(
|
||||||
|
val timestamp: Instant,
|
||||||
|
@SerialName("invited_by")
|
||||||
|
val invitedBy: UUID? = null,
|
||||||
|
val confirmed: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
@JvmInline
|
||||||
|
@Serializable
|
||||||
|
value class PetType(val name: String)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Pet(
|
||||||
|
val uuid: UUID?,
|
||||||
|
val type: PetType,
|
||||||
|
val exp: Double,
|
||||||
|
val active: Boolean,
|
||||||
|
val tier: Rarity,
|
||||||
|
val candyUsed: Int,
|
||||||
|
val heldItem: String?,
|
||||||
|
val skin: String?,
|
||||||
|
|
||||||
|
)
|
||||||
@@ -21,14 +21,27 @@ package moe.nea.firmament.commands
|
|||||||
import com.mojang.brigadier.CommandDispatcher
|
import com.mojang.brigadier.CommandDispatcher
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType.getString
|
import com.mojang.brigadier.arguments.StringArgumentType.getString
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType.string
|
import com.mojang.brigadier.arguments.StringArgumentType.string
|
||||||
|
import io.github.cottonmc.cotton.gui.client.CottonClientScreen
|
||||||
|
import io.ktor.client.call.body
|
||||||
|
import io.ktor.client.request.get
|
||||||
|
import io.ktor.client.request.parameter
|
||||||
|
import io.ktor.http.URLProtocol
|
||||||
|
import io.ktor.http.path
|
||||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource
|
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
|
import moe.nea.firmament.Firmament
|
||||||
|
import moe.nea.firmament.apis.Profiles
|
||||||
import moe.nea.firmament.features.world.FairySouls
|
import moe.nea.firmament.features.world.FairySouls
|
||||||
import moe.nea.firmament.gui.config.AllConfigsGui
|
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.ItemCostData
|
||||||
import moe.nea.firmament.repo.RepoManager
|
import moe.nea.firmament.repo.RepoManager
|
||||||
|
import moe.nea.firmament.util.MC
|
||||||
import moe.nea.firmament.util.SBData
|
import moe.nea.firmament.util.SBData
|
||||||
|
import moe.nea.firmament.util.ScreenUtil
|
||||||
import moe.nea.firmament.util.SkyblockId
|
import moe.nea.firmament.util.SkyblockId
|
||||||
|
import moe.nea.firmament.util.unformattedString
|
||||||
|
|
||||||
|
|
||||||
fun firmamentCommand() = literal("firmament") {
|
fun firmamentCommand() = literal("firmament") {
|
||||||
@@ -51,6 +64,31 @@ fun firmamentCommand() = literal("firmament") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
thenLiteral("pv") {
|
||||||
|
thenExecute {
|
||||||
|
val me = MC.player!!.uuid
|
||||||
|
val name = MC.player!!.name.unformattedString
|
||||||
|
val names = mapOf(me to name)
|
||||||
|
source.sendFeedback(Text.translatable("firmament.pv.lookingup", name))
|
||||||
|
Firmament.coroutineScope.launch {
|
||||||
|
val profiles = Firmament.httpClient.get {
|
||||||
|
url {
|
||||||
|
protocol = URLProtocol.HTTPS
|
||||||
|
host = "api.hypixel.net"
|
||||||
|
path("skyblock", "profiles")
|
||||||
|
parameter("key", "06b68418-71eb-4c2a-bb8a-65ed8bd4d5aa")
|
||||||
|
parameter("uuid", me.toString())
|
||||||
|
}
|
||||||
|
}.body<Profiles>()
|
||||||
|
val profile = profiles.profiles.find { it.selected }
|
||||||
|
if (profile == null) {
|
||||||
|
source.sendFeedback(Text.translatable("firmament.pv.noprofile", name))
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
ScreenUtil.setScreenLater(CottonClientScreen(ProfileViewer(me, names, profile)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
thenLiteral("price") {
|
thenLiteral("price") {
|
||||||
thenArgument("item", string()) { item ->
|
thenArgument("item", string()) { item ->
|
||||||
suggestsList { RepoManager.neuRepo.items.items.keys }
|
suggestsList { RepoManager.neuRepo.items.items.keys }
|
||||||
@@ -60,11 +98,36 @@ fun firmamentCommand() = literal("firmament") {
|
|||||||
val bazaarData = ItemCostData.bazaarData[itemName]
|
val bazaarData = ItemCostData.bazaarData[itemName]
|
||||||
if (bazaarData != null) {
|
if (bazaarData != null) {
|
||||||
source.sendFeedback(Text.translatable("firmament.price.bazaar"))
|
source.sendFeedback(Text.translatable("firmament.price.bazaar"))
|
||||||
source.sendFeedback(Text.translatable("firmament.price.bazaar.productid", bazaarData.productId.bazaarId))
|
source.sendFeedback(
|
||||||
source.sendFeedback(Text.translatable("firmament.price.bazaar.buy.price", bazaarData.quickStatus.buyPrice))
|
Text.translatable(
|
||||||
source.sendFeedback(Text.translatable("firmament.price.bazaar.buy.order", bazaarData.quickStatus.buyOrders))
|
"firmament.price.bazaar.productid",
|
||||||
source.sendFeedback(Text.translatable("firmament.price.bazaar.sell.price", bazaarData.quickStatus.sellPrice))
|
bazaarData.productId.bazaarId
|
||||||
source.sendFeedback(Text.translatable("firmament.price.bazaar.sell.order", bazaarData.quickStatus.sellOrders))
|
)
|
||||||
|
)
|
||||||
|
source.sendFeedback(
|
||||||
|
Text.translatable(
|
||||||
|
"firmament.price.bazaar.buy.price",
|
||||||
|
bazaarData.quickStatus.buyPrice
|
||||||
|
)
|
||||||
|
)
|
||||||
|
source.sendFeedback(
|
||||||
|
Text.translatable(
|
||||||
|
"firmament.price.bazaar.buy.order",
|
||||||
|
bazaarData.quickStatus.buyOrders
|
||||||
|
)
|
||||||
|
)
|
||||||
|
source.sendFeedback(
|
||||||
|
Text.translatable(
|
||||||
|
"firmament.price.bazaar.sell.price",
|
||||||
|
bazaarData.quickStatus.sellPrice
|
||||||
|
)
|
||||||
|
)
|
||||||
|
source.sendFeedback(
|
||||||
|
Text.translatable(
|
||||||
|
"firmament.price.bazaar.sell.order",
|
||||||
|
bazaarData.quickStatus.sellOrders
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
val lowestBin = ItemCostData.lowestBin[itemName]
|
val lowestBin = ItemCostData.lowestBin[itemName]
|
||||||
if (lowestBin != null) {
|
if (lowestBin != null) {
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package moe.nea.firmament.gui.profileviewer
|
||||||
|
|
||||||
|
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.TooltipBuilder
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WGridPanel
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WTabPanel
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WText
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.data.Insets
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.icon.ItemIcon
|
||||||
|
import java.util.UUID
|
||||||
|
import net.minecraft.item.Items
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
import moe.nea.firmament.apis.Profile
|
||||||
|
import moe.nea.firmament.apis.Skill
|
||||||
|
import moe.nea.firmament.repo.RepoManager
|
||||||
|
|
||||||
|
class ProfileViewer(
|
||||||
|
val primaryPlayer: UUID,
|
||||||
|
val playerNames: Map<UUID, String>,
|
||||||
|
val profile: Profile,
|
||||||
|
) : LightweightGuiDescription() {
|
||||||
|
init {
|
||||||
|
val primaryMember = profile.members[primaryPlayer] ?: error("Primary player not in profile")
|
||||||
|
val panel = WTabPanel().also { rootPanel = it }
|
||||||
|
panel.backgroundPainter
|
||||||
|
panel.add(WGridPanel().also {
|
||||||
|
it.insets = Insets.ROOT_PANEL
|
||||||
|
it.add(WText(Text.literal(playerNames[primaryPlayer] ?: error("Primary player has no name"))), 0, 0, 6, 1)
|
||||||
|
for ((i, skill) in Skill.values().withIndex()) {
|
||||||
|
val leveling = RepoManager.neuRepo.constants.leveling
|
||||||
|
val exp = skill.accessor.get(primaryMember)
|
||||||
|
val maxLevel = skill.getMaximumLevel(leveling)
|
||||||
|
val level = skill.getLadder(leveling)
|
||||||
|
.runningFold(0.0) { a, b -> a + b }
|
||||||
|
.filter { it <= exp }.size
|
||||||
|
.coerceAtMost(maxLevel)
|
||||||
|
it.add(WText(Text.translatable("firmament.pv.skills.${skill.name.lowercase()}")), 0, i + 1, 5, 1)
|
||||||
|
it.add(object : WText(Text.literal("$level/$maxLevel")) {
|
||||||
|
override fun addTooltip(tooltip: TooltipBuilder) {
|
||||||
|
tooltip.add(Text.translatable("firmament.pv.skills.total", exp))
|
||||||
|
}
|
||||||
|
}, 5, i + 1, 2, 1)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
it.icon(ItemIcon(Items.IRON_SWORD))
|
||||||
|
it.title(Text.translatable("firmament.pv.skills"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@ package moe.nea.firmament.util.json
|
|||||||
|
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.Serializer
|
|
||||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||||
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
@@ -15,7 +14,11 @@ object DashlessUUIDSerializer : KSerializer<UUID> {
|
|||||||
PrimitiveSerialDescriptor("DashlessUUIDSerializer", PrimitiveKind.STRING)
|
PrimitiveSerialDescriptor("DashlessUUIDSerializer", PrimitiveKind.STRING)
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): UUID {
|
override fun deserialize(decoder: Decoder): UUID {
|
||||||
return parseDashlessUUID(decoder.decodeString())
|
val str = decoder.decodeString()
|
||||||
|
if ("-" in str) {
|
||||||
|
return UUID.fromString(str)
|
||||||
|
}
|
||||||
|
return parseDashlessUUID(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, value: UUID) {
|
override fun serialize(encoder: Encoder, value: UUID) {
|
||||||
|
|||||||
@@ -36,5 +36,19 @@
|
|||||||
"firmament.key.slotlocking": "Lock Slot / Slot Binding",
|
"firmament.key.slotlocking": "Lock Slot / Slot Binding",
|
||||||
"firmament.key.category": "Firmament",
|
"firmament.key.category": "Firmament",
|
||||||
"firmament.protectitem": "Firmament protected your item: ",
|
"firmament.protectitem": "Firmament protected your item: ",
|
||||||
"firmament.recipe.forge.time": "Forging Time: %s"
|
"firmament.recipe.forge.time": "Forging Time: %s",
|
||||||
|
"firmament.pv.skills": "Skills",
|
||||||
|
"firmament.pv.skills.farming": "Farming",
|
||||||
|
"firmament.pv.skills.foraging": "Foraging",
|
||||||
|
"firmament.pv.skills.mining": "Mining",
|
||||||
|
"firmament.pv.skills.alchemy": "Alchemy",
|
||||||
|
"firmament.pv.skills.taming": "Taming",
|
||||||
|
"firmament.pv.skills.fishing": "Fishing",
|
||||||
|
"firmament.pv.skills.runecrafting": "Runecrafting",
|
||||||
|
"firmament.pv.skills.carpentry": "Carpentry",
|
||||||
|
"firmament.pv.skills.combat": "Combat",
|
||||||
|
"firmament.pv.skills.social": "Social",
|
||||||
|
"firmament.pv.skills.enchanting": "Enchanting",
|
||||||
|
"firmament.pv.skills.total": "Total Exp: %.1f",
|
||||||
|
"firmament.pv.lookingup": "Looking up %s"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user