diff options
Diffstat (limited to 'src/main/kotlin')
7 files changed, 406 insertions, 1 deletions
diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/EnforcedConfigValues.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/EnforcedConfigValues.kt new file mode 100644 index 00000000..7351a4a0 --- /dev/null +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/EnforcedConfigValues.kt @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2022 Linnea Gräf + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscfeatures + +import com.google.gson.JsonElement +import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe +import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent +import io.github.moulberry.notenoughupdates.util.NotificationHandler +import io.github.moulberry.notenoughupdates.util.Shimmy +import io.github.moulberry.notenoughupdates.util.Utils +import io.github.moulberry.notenoughupdates.util.kotlin.fromJson +import net.minecraft.client.Minecraft +import net.minecraftforge.client.event.GuiOpenEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.TickEvent + +@NEUAutoSubscribe +object EnforcedConfigValues { + + class EnforcedValue { + // lateinit var because we use gson (instead of kotlinx.serialization which can handle data classes) + lateinit var path: String + lateinit var value: JsonElement + } + + class EnforcedValueData { + var enforcedValues: List<EnforcedValue> = listOf() + var notificationPSA: List<String>? = null + var chatPSA: List<String>? = null + lateinit var affectedVersions: List<Int> + } + + + var enforcedValues: List<EnforcedValueData> = listOf() + + @SubscribeEvent + fun onRepoReload(event: RepositoryReloadEvent) { + val fixedValues = event.repositoryRoot.resolve("enforced_values") + enforcedValues = if (fixedValues.exists()) { + fixedValues.listFiles() + .filter { + it != null && it.isFile && it.canRead() + } + .map { + NotEnoughUpdates.INSTANCE.manager.gson.fromJson<EnforcedValueData>(it.readText()) + }.filter { + NotEnoughUpdates.VERSION_ID in it.affectedVersions + } + } else { + listOf() + } + if (!event.isFirstLoad) + sendPSAs() + } + + @SubscribeEvent + fun onGuiClose(event: GuiOpenEvent) { + enforceOntoConfig(NotEnoughUpdates.INSTANCE.config ?: return) + } + + var hasSentPSAsOnce = false + + @SubscribeEvent + fun onTick(tickEvent: TickEvent.ClientTickEvent) { + if (hasSentPSAsOnce || Minecraft.getMinecraft().thePlayer == null || !NotEnoughUpdates.INSTANCE.isOnSkyblock) return + hasSentPSAsOnce = true + sendPSAs() + enforceOntoConfig(NotEnoughUpdates.INSTANCE.config ?: return) + } + + fun sendPSAs() { + val notification = enforcedValues.flatMap { it.notificationPSA ?: emptyList() } + if (notification.isNotEmpty()) { + NotificationHandler.displayNotification(notification, true) + } + val chat = enforcedValues.flatMap { it.chatPSA ?: emptyList() } + if (chat.isNotEmpty()) { + for (line in chat) { + Utils.addChatMessage(line) + } + } + } + + + fun enforceOntoConfig(config: Any) { + for (enforcedValue in enforcedValues.flatMap { it.enforcedValues }) { + val shimmy = Shimmy.makeShimmy(config, enforcedValue.path.split(".")) + if (shimmy == null) { + println("Could not create shimmy for path ${enforcedValue.path}") + continue + } + val currentValue = shimmy.getJson() + if (currentValue != enforcedValue.value) { + println("Resetting ${enforcedValue.path} to ${enforcedValue.value} from $currentValue") + shimmy.setJson(enforcedValue.value) + } + } + } + + fun isBlockedFromEditing(optionPath: String): Boolean { + return enforcedValues.flatMap { it.enforcedValues }.any { it.path == optionPath } + } + + +} diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumCheapestItemOverlay.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumCheapestItemOverlay.kt index 7485f14d..ccaf5ad8 100644 --- a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumCheapestItemOverlay.kt +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumCheapestItemOverlay.kt @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures.inventory import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe import io.github.moulberry.notenoughupdates.core.util.ArrowPagesUtils import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer import io.github.moulberry.notenoughupdates.util.MuseumUtil @@ -39,7 +40,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import org.lwjgl.input.Mouse import org.lwjgl.opengl.GL11 - +@NEUAutoSubscribe object MuseumCheapestItemOverlay { data class MuseumItem( var name: String, diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumItemHighlighter.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumItemHighlighter.kt index b809ee9f..945449ba 100644 --- a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumItemHighlighter.kt +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumItemHighlighter.kt @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures.inventory import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe import io.github.moulberry.notenoughupdates.core.ChromaColour import io.github.moulberry.notenoughupdates.core.util.StringUtils import io.github.moulberry.notenoughupdates.events.GuiContainerBackgroundDrawnEvent @@ -37,6 +38,7 @@ import net.minecraft.item.EnumDyeColor import net.minecraft.item.ItemStack import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +@NEUAutoSubscribe object MuseumItemHighlighter { private val manager get() = NotEnoughUpdates.INSTANCE.manager diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/PetLeveling.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/PetLeveling.kt index 200aa3fa..99066e52 100644 --- a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/PetLeveling.kt +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/PetLeveling.kt @@ -23,7 +23,9 @@ import com.google.gson.JsonObject import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay.Rarity import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe +@NEUAutoSubscribe object PetLeveling { data class ExpLadder( diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/Shimmy.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/Shimmy.kt new file mode 100644 index 00000000..37cdd3ac --- /dev/null +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/Shimmy.kt @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 Linnea Gräf + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.util + +import com.google.gson.Gson +import com.google.gson.JsonElement +import java.lang.reflect.Field + +class Shimmy private constructor( + val source: Any, + val field: Field, +) { + companion object { + val gson = Gson() + private fun shimmy(source: Any?, fieldName: String): Any? { + if (source == null) return null + return try { + val declaredField = source.javaClass.getDeclaredField(fieldName) + declaredField.isAccessible = true + declaredField.get(source) + } catch (e: NoSuchFieldException) { + null + } + } + + @JvmStatic + fun makeShimmy(source: Any?, path: List<String>): Shimmy? { + if (path.isEmpty()) + return null + var source = source + for (part in path.dropLast(1)) { + source = shimmy(source, part) + } + if (source == null) return null + val lastName = path.last() + return try { + val field = source.javaClass.getDeclaredField(lastName) + field.isAccessible = true + Shimmy( + source, + field, + ) + } catch (e: NoSuchFieldException) { + null + } + } + + } + + val clazz: Class<*> = field.type + fun get(): Any? { + return field.get(source) + } + + fun set(value: Any?) { + field.set(source, value) + } + + fun getJson(): JsonElement { + return gson.toJsonTree(get()) + } + + fun setJson(element: JsonElement) { + set(gson.fromJson(element, clazz)) + } + + +} diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/hypixelapi/Collection.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/hypixelapi/Collection.kt new file mode 100644 index 00000000..b2c7fcec --- /dev/null +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/hypixelapi/Collection.kt @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.util.hypixelapi + +import com.google.gson.JsonArray +import com.google.gson.JsonObject +import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import java.math.BigInteger +import java.util.concurrent.CompletableFuture +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.component1 +import kotlin.collections.component2 +import kotlin.collections.filter +import kotlin.collections.flatMap +import kotlin.collections.groupBy +import kotlin.collections.mapNotNull +import kotlin.collections.mapValues +import kotlin.collections.maxOf +import kotlin.collections.sumOf +import kotlin.collections.toList +import kotlin.collections.toMap +import kotlin.collections.toSet + +data class ProfileCollectionInfo( + val collections: Map<String, CollectionInfo>, + val craftedGenerators: Map<String, Int>, +) { + data class CollectionInfo( + val collection: Collection, + val totalCollectionCount: BigInteger, + val personalCollectionCount: BigInteger, + val unlockedTiers: List<CollectionTier>, + ) + + class CollectionMetadata internal constructor() { + lateinit var collections: Map<String, CollectionCategory> + private set + val allCollections by lazy { collections.values.flatMap { it.items.toList() }.toMap() } + } + + class CollectionCategory internal constructor() { + lateinit var items: Map<String, Collection> + private set + } + + class Collection internal constructor() { + lateinit var name: String + private set + var maxTiers: Int = -1 + private set + lateinit var tiers: List<CollectionTier> + private set + + override fun toString(): String { + return "Collection(name=$name, maxTiers=$maxTiers, tiers=$tiers)" + } + } + + class CollectionTier internal constructor() { + var tier: Int = -1 + private set + var amountRequired: Int = -1 + private set + lateinit var unlocks: List<String> + private set + + override fun toString(): String { + return "CollectionTier(tier=$tier, amountRequired=$amountRequired, unlocks=$unlocks)" + } + } + + + companion object { + + + val generatorPattern = "^([^0-9]+)_([0-9]+)$".toRegex() + + val hypixelCollectionInfo: CompletableFuture<CollectionMetadata> by lazy { + NotEnoughUpdates.INSTANCE.manager.apiUtils + .newHypixelApiRequest("resources/skyblock/collections") + .requestJson() + .thenApply { + NotEnoughUpdates.INSTANCE.manager.gson.fromJson(it, CollectionMetadata::class.java) + } + } + + fun getCollectionData( + profileData: JsonObject, + mainPlayer: String, + collectionData: CollectionMetadata + ): ProfileCollectionInfo? { + val mainPlayerUUID = mainPlayer.replace("-", "") + val members = profileData["members"] as? JsonObject ?: return null + val mainPlayerData = + (members[mainPlayerUUID] as? JsonObject ?: return null) + val mainPlayerCollection = mainPlayerData["collection"] as? JsonObject ?: return null + val memberCollections = members.entrySet().mapNotNull { (uuid, data) -> + if (data !is JsonObject) return null + data["collection"] as? JsonObject + } + val generators = members.entrySet().mapNotNull { (uuid, data) -> + if (data !is JsonObject) return null + data["crafted_generators"] as? JsonArray + }.flatMap { it.toList() } + return ProfileCollectionInfo( + collectionData.allCollections.mapValues { (name, collection) -> + val totalCollection = memberCollections.sumOf { it[name]?.asBigInteger ?: BigInteger.ZERO } + val personalCollection = mainPlayerCollection[name]?.asBigInteger ?: BigInteger.ZERO + CollectionInfo( + collection, + totalCollection, + personalCollection, + collection.tiers.filter { BigInteger.valueOf(it.amountRequired.toLong()) <= totalCollection } + ) + }, + generators.toSet() + .mapNotNull { + val pattern = generatorPattern.matchEntire(it.asString) ?: return@mapNotNull null + pattern.groupValues[1] to pattern.groupValues[2].toInt() + } + .groupBy { it.first } + .mapValues { + it.value.maxOf { it.second } + } + .toMap() + ) + } + + /** + * This should be the json object returned by /skyblock/profiles at profiles.<somenumber>. (aka the root tag + * should contain profile_id, members, cute_name, etc.) + */ + @JvmStatic + fun getCollectionData(profileData: JsonObject, mainPlayer: String): CompletableFuture<ProfileCollectionInfo?> { + return hypixelCollectionInfo.thenApply { + getCollectionData(profileData, mainPlayer, it) + } + } + } + +} diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/kotlin/gson.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/kotlin/gson.kt new file mode 100644 index 00000000..00c3d729 --- /dev/null +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/kotlin/gson.kt @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.util.kotlin + +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import java.lang.reflect.Type + + +inline fun <reified T : Any> typeToken(): Type { + return (object : TypeToken<T>() {}).type +} + +inline fun <reified T : Any> Gson.fromJson(string: String): T { + return fromJson(string, typeToken<T>()) +} |