aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/firmament/apis
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-08-28 19:04:24 +0200
committerLinnea Gräf <nea@nea.moe>2024-08-28 19:04:24 +0200
commitd2f240ff0ca0d27f417f837e706c781a98c31311 (patch)
tree0db7aff6cc14deaf36eed83889d59fd6b3a6f599 /src/main/kotlin/moe/nea/firmament/apis
parenta6906308163aa3b2d18fa1dc1aa71ac9bbcc83ab (diff)
downloadfirmament-d2f240ff0ca0d27f417f837e706c781a98c31311.tar.gz
firmament-d2f240ff0ca0d27f417f837e706c781a98c31311.tar.bz2
firmament-d2f240ff0ca0d27f417f837e706c781a98c31311.zip
Refactor source layout
Introduce compat source sets and move all kotlin sources to the main directory [no changelog]
Diffstat (limited to 'src/main/kotlin/moe/nea/firmament/apis')
-rw-r--r--src/main/kotlin/moe/nea/firmament/apis/Profiles.kt194
-rw-r--r--src/main/kotlin/moe/nea/firmament/apis/Routes.kt95
-rw-r--r--src/main/kotlin/moe/nea/firmament/apis/UrsaManager.kt72
3 files changed, 0 insertions, 361 deletions
diff --git a/src/main/kotlin/moe/nea/firmament/apis/Profiles.kt b/src/main/kotlin/moe/nea/firmament/apis/Profiles.kt
deleted file mode 100644
index 789364a..0000000
--- a/src/main/kotlin/moe/nea/firmament/apis/Profiles.kt
+++ /dev/null
@@ -1,194 +0,0 @@
-
-
-@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 kotlinx.datetime.Instant
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.UseSerializers
-import moe.nea.firmament.repo.RepoManager
-import moe.nea.firmament.util.LegacyFormattingCode
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.assertNotNullOr
-import moe.nea.firmament.util.json.DashlessUUIDSerializer
-import moe.nea.firmament.util.json.InstantAsLongSerializer
-import net.minecraft.util.DyeColor
-import net.minecraft.util.Formatting
-import java.util.*
-import kotlin.reflect.KProperty1
-
-
-@Serializable
-data class CollectionSkillData(
- val items: Map<CollectionType, CollectionInfo>
-)
-
-@Serializable
-data class CollectionResponse(
- val success: Boolean,
- val collections: Map<String, 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>?
-)
-
-@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>, 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) = assertNotNullOr(leveling.maximumLevels[name.lowercase()]) { 50 }
-
- fun getLadder(leveling: Leveling): List<Int> {
- if (this == SOCIAL) return leveling.socialExperienceRequiredPerLevel
- if (this == RUNECRAFTING) return leveling.runecraftingExperienceRequiredPerLevel
- return leveling.skillExperienceRequiredPerLevel
- }
-}
-
-enum class CollectionCategory(val skill: Skill?, val color: DyeColor, val icon: SkyblockId) {
- FARMING(Skill.FARMING, DyeColor.YELLOW, SkyblockId("ROOKIE_HOE")),
- FORAGING(Skill.FORAGING, DyeColor.BROWN, SkyblockId("TREECAPITATOR_AXE")),
- MINING(Skill.MINING, DyeColor.LIGHT_GRAY, SkyblockId("DIAMOND_PICKAXE")),
- FISHING(Skill.FISHING, DyeColor.BLUE, SkyblockId("FARMER_ROD")),
- COMBAT(Skill.COMBAT, DyeColor.RED, SkyblockId("UNDEAD_SWORD")),
- RIFT(null, DyeColor.PURPLE, SkyblockId("SKYBLOCK_MOTE")),
-}
-
-@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")
- 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,
- val collection: Map<CollectionType, Long> = mapOf()
-)
-
-@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? = null,
- val type: PetType,
- val exp: Double = 0.0,
- val active: Boolean = false,
- val tier: Rarity,
- val candyUsed: Int = 0,
- val heldItem: String? = null,
- val skin: String? = null,
-) {
- val itemId get() = SkyblockId("${type.name};${tier.ordinal}")
-}
-
-@Serializable
-data class PlayerResponse(
- val success: Boolean,
- val player: PlayerData,
-)
-
-@Serializable
-data class PlayerData(
- val uuid: UUID,
- val firstLogin: Instant,
- val lastLogin: Instant? = null,
- @SerialName("playername")
- val playerName: String,
- val achievementsOneTime: List<String> = listOf(),
- @SerialName("newPackageRank")
- val packageRank: String? = null,
- val monthlyPackageRank: String? = null,
- val rankPlusColor: String = "GOLD"
-) {
- val rankPlusDyeColor = LegacyFormattingCode.values().find { it.name == rankPlusColor } ?: LegacyFormattingCode.GOLD
- val rankData get() = RepoManager.neuRepo.constants.misc.ranks[if (monthlyPackageRank == "NONE" || monthlyPackageRank == null) packageRank else monthlyPackageRank]
- fun getDisplayName(name: String = playerName) = rankData?.let {
- ("§${it.color}[${it.tag}${rankPlusDyeColor.modern}" +
- "${it.plus ?: ""}§${it.color}] $name")
- } ?: "${Formatting.GRAY}$name"
-
-
-}
-
-@Serializable
-data class AshconNameLookup(
- val username: String,
- val uuid: UUID,
-)
diff --git a/src/main/kotlin/moe/nea/firmament/apis/Routes.kt b/src/main/kotlin/moe/nea/firmament/apis/Routes.kt
deleted file mode 100644
index bf55a2d..0000000
--- a/src/main/kotlin/moe/nea/firmament/apis/Routes.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
-package moe.nea.firmament.apis
-
-import io.ktor.client.call.*
-import io.ktor.client.request.*
-import io.ktor.http.*
-import io.ktor.util.*
-import java.util.*
-import kotlinx.coroutines.Deferred
-import kotlinx.coroutines.async
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import kotlin.collections.MutableMap
-import kotlin.collections.listOf
-import kotlin.collections.mutableMapOf
-import kotlin.collections.set
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.util.MinecraftDispatcher
-
-object Routes {
- private val nameToUUID: MutableMap<String, Deferred<UUID?>> = CaseInsensitiveMap()
- private val profiles: MutableMap<UUID, Deferred<Profiles?>> = mutableMapOf()
- private val accounts: MutableMap<UUID, Deferred<PlayerData?>> = mutableMapOf()
- private val UUIDToName: MutableMap<UUID, Deferred<String?>> = mutableMapOf()
-
- suspend fun getPlayerNameForUUID(uuid: UUID): String? {
- return withContext(MinecraftDispatcher) {
- UUIDToName.computeIfAbsent(uuid) {
- async(Firmament.coroutineScope.coroutineContext) {
- val response = Firmament.httpClient.get("https://api.ashcon.app/mojang/v2/user/$uuid")
- if (!response.status.isSuccess()) return@async null
- val data = response.body<AshconNameLookup>()
- launch(MinecraftDispatcher) {
- nameToUUID[data.username] = async { data.uuid }
- }
- data.username
- }
- }
- }.await()
- }
-
- suspend fun getUUIDForPlayerName(name: String): UUID? {
- return withContext(MinecraftDispatcher) {
- nameToUUID.computeIfAbsent(name) {
- async(Firmament.coroutineScope.coroutineContext) {
- val response = Firmament.httpClient.get("https://api.ashcon.app/mojang/v2/user/$name")
- if (!response.status.isSuccess()) return@async null
- val data = response.body<AshconNameLookup>()
- launch(MinecraftDispatcher) {
- UUIDToName[data.uuid] = async { data.username }
- }
- data.uuid
- }
- }
- }.await()
- }
-
- suspend fun getAccountData(uuid: UUID): PlayerData? {
- return withContext(MinecraftDispatcher) {
- accounts.computeIfAbsent(uuid) {
- async(Firmament.coroutineScope.coroutineContext) {
- val response = UrsaManager.request(listOf("v1", "hypixel","player", uuid.toString()))
- if (!response.status.isSuccess()) {
- launch(MinecraftDispatcher) {
- @Suppress("DeferredResultUnused")
- accounts.remove(uuid)
- }
- return@async null
- }
- response.body<PlayerResponse>().player
- }
- }
- }.await()
- }
-
- suspend fun getProfiles(uuid: UUID): Profiles? {
- return withContext(MinecraftDispatcher) {
- profiles.computeIfAbsent(uuid) {
- async(Firmament.coroutineScope.coroutineContext) {
- val response = UrsaManager.request(listOf("v1", "hypixel","profiles", uuid.toString()))
- if (!response.status.isSuccess()) {
- launch(MinecraftDispatcher) {
- @Suppress("DeferredResultUnused")
- profiles.remove(uuid)
- }
- return@async null
- }
- response.body<Profiles>()
- }
- }
- }.await()
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/apis/UrsaManager.kt b/src/main/kotlin/moe/nea/firmament/apis/UrsaManager.kt
deleted file mode 100644
index 13f7aef..0000000
--- a/src/main/kotlin/moe/nea/firmament/apis/UrsaManager.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
-package moe.nea.firmament.apis
-
-import io.ktor.client.request.*
-import io.ktor.client.statement.*
-import io.ktor.http.*
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.sync.Mutex
-import kotlinx.coroutines.withContext
-import moe.nea.firmament.Firmament
-import net.minecraft.client.MinecraftClient
-import java.time.Duration
-import java.time.Instant
-import java.util.*
-
-object UrsaManager {
- private data class Token(
- val validUntil: Instant,
- val token: String,
- val obtainedFrom: String,
- ) {
- fun isValid(host: String) = Instant.now().plusSeconds(60) < validUntil && obtainedFrom == host
- }
-
- private var currentToken: Token? = null
- private val lock = Mutex()
- private fun getToken(host: String) = currentToken?.takeIf { it.isValid(host) }
-
- suspend fun request(path: List<String>): HttpResponse {
- var didLock = false
- try {
- val host = "ursa.notenoughupdates.org"
- var token = getToken(host)
- if (token == null) {
- lock.lock()
- didLock = true
- token = getToken(host)
- }
- val response = Firmament.httpClient.get {
- url {
- this.host = host
- appendPathSegments(path, encodeSlash = true)
- }
- if (token == null) {
- withContext(Dispatchers.IO) {
- val mc = MinecraftClient.getInstance()
- val serverId = UUID.randomUUID().toString()
- mc.sessionService.joinServer(mc.session.uuidOrNull, mc.session.accessToken, serverId)
- header("x-ursa-username", mc.session.username)
- header("x-ursa-serverid", serverId)
- }
- } else {
- header("x-ursa-token", token.token)
- }
- }
- val savedToken = response.headers["x-ursa-token"]
- if (savedToken != null) {
- val validUntil = response.headers["x-ursa-expires"]?.toLongOrNull()?.let { Instant.ofEpochMilli(it) }
- ?: (Instant.now() + Duration.ofMinutes(55))
- currentToken = Token(validUntil, savedToken, host)
- }
- if (response.status.value != 200) {
- Firmament.logger.error("Failed to contact ursa minor: ${response.bodyAsText()}")
- }
- return response
- } finally {
- if (didLock)
- lock.unlock()
- }
- }
-}