diff options
Diffstat (limited to 'src/main/kotlin')
3 files changed, 258 insertions, 0 deletions
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 new file mode 100644 index 00000000..945449ba --- /dev/null +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumItemHighlighter.kt @@ -0,0 +1,121 @@ +/* + * 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.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 +import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent +import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent +import io.github.moulberry.notenoughupdates.util.ItemResolutionQuery +import io.github.moulberry.notenoughupdates.util.ItemUtils +import io.github.moulberry.notenoughupdates.util.LRUCache +import io.github.moulberry.notenoughupdates.util.MuseumUtil +import net.minecraft.client.gui.Gui +import net.minecraft.init.Items +import net.minecraft.inventory.ContainerChest +import net.minecraft.inventory.IInventory +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 + private val config get() = NotEnoughUpdates.INSTANCE.config.museum + + private fun getHighlightColor() = ChromaColour.specialToChromaRGB(config.museumItemColor) + + + private val findRawItemForName = LRUCache.memoize(::findRawItemForName0, 4 * 7 * 2) + + @SubscribeEvent + fun onRepositoryReload(event: RepositoryReloadEvent) { + findRawItemForName.clearCache() + } + + private fun findRawItemForName0(arg: Pair<String, Boolean>): ItemStack? { + val (name, armor) = arg + return MuseumUtil.findItemsByName(name, armor).firstOrNull()?.let { manager.createItem(it) } + } + + + @SubscribeEvent + fun onItemOverride(event: ReplaceItemEvent) { + if (!config.museumItemShow) return + if (!isMuseumInventory(event.inventory)) return + val original = event.original ?: return + if (!isCompletedRetrievedItem(original)) return + val armor = StringUtils.cleanColour(event.inventory.displayName.unformattedText).endsWith("Armor Sets") + val rawItem = findRawItemForName.apply(original.displayName to armor) ?: return + val hydratedItem = hydrateMuseumItem(rawItem, original) + event.replaceWith(hydratedItem) + } + + fun isCompletedRetrievedItem(itemStack: ItemStack): Boolean { + return itemStack.hasDisplayName() && itemStack.item == Items.dye && EnumDyeColor.byDyeDamage(itemStack.itemDamage) == EnumDyeColor.LIME + } + + fun isMuseumInventory(inventory: IInventory): Boolean { + return StringUtils.cleanColour(inventory.displayName.unformattedText).startsWith("Museum ➜") + } + + @SubscribeEvent + fun onBackgroundDrawn(event: GuiContainerBackgroundDrawnEvent) { + val egui = event.container ?: return + val chest = egui.inventorySlots as? ContainerChest ?: return + if (!config.museumItemShow) return + if (!isMuseumInventory(chest.lowerChestInventory)) return + val fixedHighlightColor = getHighlightColor() + for (slot in chest.inventorySlots) { + if (slot == null || slot.stack == null) continue + if (isHydratedMuseumItem(slot.stack) || isCompletedRetrievedItem(slot.stack)) { + val left = slot.xDisplayPosition + val top = slot.yDisplayPosition + Gui.drawRect( + left, top, + left + 16, top + 16, + fixedHighlightColor + ) + } + } + } + + fun hydrateMuseumItem(rawItem: ItemStack, original: ItemStack) = rawItem.copy().apply { + setStackDisplayName(original.displayName) + val originalLore = ItemUtils.getLore(original).toMutableList() + ItemUtils.setLore(this, originalLore) + val data = ItemUtils.getOrCreateTag(this) + val extraAttributes = data.getCompoundTag("ExtraAttributes") + extraAttributes.setByte("donated_museum", 1) + data.setTag("ExtraAttributes", extraAttributes) + data.setBoolean(MUSEUM_HYDRATED_ITEM_TAG, true) + } + + fun isHydratedMuseumItem(stack: ItemStack): Boolean { + return ItemUtils.getOrCreateTag(stack).getBoolean(MUSEUM_HYDRATED_ITEM_TAG) + } + + const val MUSEUM_HYDRATED_ITEM_TAG = "NEU_HYDRATED_MUSEUM_ITEM" + +} diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/KotlinStringUtils.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/KotlinStringUtils.kt new file mode 100644 index 00000000..dc1e800c --- /dev/null +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/KotlinStringUtils.kt @@ -0,0 +1,24 @@ +/* + * 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 + +import net.minecraft.util.StringUtils + +fun String.stripControlCodes(): String = StringUtils.stripControlCodes(this) diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/MuseumUtil.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/MuseumUtil.kt new file mode 100644 index 00000000..dd52d175 --- /dev/null +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/MuseumUtil.kt @@ -0,0 +1,113 @@ +/* + * 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 + +import io.github.moulberry.notenoughupdates.NEUManager +import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import net.minecraft.item.EnumDyeColor +import net.minecraft.item.ItemDye +import net.minecraft.item.ItemStack + +object MuseumUtil { + + data class MuseumItem( + /** + * A potentially non-exhaustive list of item ids that are required for this museum donation. + */ + val skyblockItemIds: List<String>, + val state: DonationState, + ) + + enum class DonationState { + /** + * Donated armor only shows one piece, so we use that for id resolution, which might result in incomplete + * results (hence the separate state). This still means that the entire set is donated, but it is guaranteed to + * be only a partial result. Other values of this enum do not guarantee a full result, but at least they do not + * guarantee a partial one. + */ + DONATED_PRESENT_PARTIAL, + DONATED_PRESENT, + DONATED_VACANT, + MISSING, + } + + fun findMuseumItem(stack: ItemStack, isOnArmorPage: Boolean): MuseumItem? { + val item = stack.item ?: return null + val items by lazy { findItemsByName(stack.displayName, isOnArmorPage)} + if (item is ItemDye) { + val dyeColor = EnumDyeColor.byDyeDamage(stack.itemDamage) + if (dyeColor == EnumDyeColor.LIME) { + // Item is donated, but not present in the museum + return MuseumItem(items, DonationState.DONATED_VACANT) + } else if (dyeColor == EnumDyeColor.GRAY) { + // Item is not donated + return MuseumItem(items, DonationState.MISSING) + } + // Otherwise unknown item, try to analyze as normal item. + } + val skyblockId = NotEnoughUpdates.INSTANCE.manager.createItemResolutionQuery().withItemStack(stack) + .resolveInternalName() + if (skyblockId != null) { + return MuseumItem( + listOf(skyblockId), + if (isOnArmorPage) DonationState.DONATED_PRESENT_PARTIAL else DonationState.DONATED_PRESENT + ) + } + return MuseumItem( + items, + DonationState.DONATED_PRESENT + ) + } + + fun findItemsByName(displayName: String, armor: Boolean): List<String> { + return (if (armor) + findMuseumArmorSetByName(displayName) + else + listOf(findMuseumItemByName(displayName))).filterNotNull() + + } + + fun findMuseumItemByName(displayName: String): String? = + ItemResolutionQuery.findInternalNameByDisplayName(displayName, true) + + + fun findMuseumArmorSetByName(displayName: String): List<String?> { + val armorSlots = arrayOf( + "HELMET", + "LEGGINGS", + "CHESTPLATE", + "BOOTS" + ) + val monochromeName = NEUManager.cleanForTitleMapSearch(displayName) + val results = ItemResolutionQuery.findInternalNameCandidatesForDisplayName(displayName) + .asSequence() + .filter { + val item = NotEnoughUpdates.INSTANCE.manager.createItem(it) + val name = NEUManager.cleanForTitleMapSearch(item.displayName) + monochromeName.replace("armor", "") in name + } + .toSet() + return armorSlots.map { armorSlot -> + results.singleOrNull { armorSlot in it } + } + } + + +} |