From 1c6a3f3d6b271e3022dd48827518e49e9d2398d8 Mon Sep 17 00:00:00 2001 From: My-Name-Is-Jeff <37018278+My-Name-Is-Jeff@users.noreply.github.com> Date: Fri, 9 Feb 2024 00:34:47 -0500 Subject: [PATCH] feat: add MojangUtil.queueUsernameForUUID --- .../gg/skytils/skytilsmod/utils/MojangUtil.kt | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/main/kotlin/gg/skytils/skytilsmod/utils/MojangUtil.kt b/src/main/kotlin/gg/skytils/skytilsmod/utils/MojangUtil.kt index 7a7601652..379bc12c3 100644 --- a/src/main/kotlin/gg/skytils/skytilsmod/utils/MojangUtil.kt +++ b/src/main/kotlin/gg/skytils/skytilsmod/utils/MojangUtil.kt @@ -20,11 +20,15 @@ package gg.skytils.skytilsmod.utils import gg.essential.lib.caffeine.cache.Cache import gg.essential.lib.caffeine.cache.Caffeine +import gg.skytils.skytilsmod.Skytils import gg.skytils.skytilsmod.Skytils.Companion.client import io.ktor.client.call.* import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch import kotlinx.serialization.Serializable import net.minecraft.client.entity.EntityOtherPlayerMP import net.minecraftforge.common.MinecraftForge @@ -34,6 +38,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.util.* import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicInteger +import kotlin.collections.ArrayDeque import kotlin.concurrent.fixedRateTimer @@ -42,6 +47,9 @@ object MojangUtil { private val usernameToUuid: Cache private val requestCount = AtomicInteger() + private val usernameQueue = MutableSharedFlow>() + private val uuidFlow = MutableSharedFlow>() + init { Caffeine.newBuilder() .weakKeys() @@ -65,6 +73,13 @@ object MojangUtil { } } + suspend fun queueUsernameForUUID(name: String): UUID? { + val username = name.lowercase() + usernameQueue.emit(username to System.currentTimeMillis()) + + return uuidFlow.first { it.first == username }.second + } + suspend fun getUUIDFromUsername(name: String): UUID? { val username = name.lowercase() return usernameToUuid.getIfPresent(username) ?: run { @@ -84,6 +99,46 @@ object MojangUtil { } } + suspend fun getUUIDsFromUsernames(names: Collection): Map { + if (requestCount.incrementAndGet() % 6 == 0) { + client.get("https://api.minecraftservices.com/minecraft/profile/lookup/name/SlashSlayer?ts=${System.currentTimeMillis()}") + requestCount.getAndIncrement() + } + val usernames = names.mapTo(hashSetOf()) { it.lowercase() } + val map = HashMap() + map.putAll(usernameToUuid.getAllPresent(usernames)) + + usernames.removeAll(map.keys) + + usernames.windowed(10).forEach { + client.post("https://api.minecraftservices.com/minecraft/profile/lookup/bulk/byname") { + contentType(ContentType.Application.Json) + setBody(it) + }.let { + when (it.status) { + HttpStatusCode.OK -> { + val response = it.body>() + for (profile in response) { + val username = profile.name.lowercase() + val uuid = profile.id + map[username] = uuid + usernameToUuid[username] = uuid + uuidToUsername[uuid] = username + } + } + + else -> throw it.body() + } + } + } + + names.forEach { + map.getOrPut(it) { null } + } + + return map + } + suspend fun getUsernameFromUUID(uuid: UUID): String? { return uuidToUsername.getIfPresent(uuid) ?: run { makeMojangRequest("https://api.minecraftservices.com/minecraft/profile/lookup/${uuid}").let { @@ -107,6 +162,19 @@ object MojangUtil { fixedRateTimer("Mojang-Fake-Requests-Insert", startAt = Date((System.currentTimeMillis() / 60000) * 60000 + 48000), period = 60_000L) { requestCount.set(0) } + + Skytils.IO.launch { + val usernames = ArrayDeque>(10) + usernameQueue.collect { name -> + usernames.add(name) + if (usernames.size >= 10 || usernames.isNotEmpty() && System.currentTimeMillis() - usernames.first().second >= 3000L) { + getUUIDsFromUsernames(usernames.map { it.first }).forEach { + uuidFlow.emit(it.toPair()) + } + usernames.clear() + } + } + } } /**