diff options
Diffstat (limited to 'src/main/kotlin/features/debug')
4 files changed, 125 insertions, 20 deletions
diff --git a/src/main/kotlin/features/debug/PowerUserTools.kt b/src/main/kotlin/features/debug/PowerUserTools.kt index 7c1df3f..1a7b2cf 100644 --- a/src/main/kotlin/features/debug/PowerUserTools.kt +++ b/src/main/kotlin/features/debug/PowerUserTools.kt @@ -59,6 +59,7 @@ object PowerUserTools : FirmamentFeature { val exportItemStackToRepo by keyBindingWithDefaultUnbound("export-item-stack") val exportUIRecipes by keyBindingWithDefaultUnbound("export-recipe") val exportNpcLocation by keyBindingWithDefaultUnbound("export-npc-location") + val highlightNonOverlayItems by toggle("highlight-non-overlay") { false } } override val config diff --git a/src/main/kotlin/features/debug/itemeditor/ItemExporter.kt b/src/main/kotlin/features/debug/itemeditor/ItemExporter.kt index d7d17aa..c521b5a 100644 --- a/src/main/kotlin/features/debug/itemeditor/ItemExporter.kt +++ b/src/main/kotlin/features/debug/itemeditor/ItemExporter.kt @@ -1,6 +1,5 @@ package moe.nea.firmament.features.debug.itemeditor -import com.mojang.brigadier.arguments.StringArgumentType import kotlinx.coroutines.launch import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonObject @@ -19,13 +18,14 @@ import net.minecraft.nbt.NbtString import net.minecraft.text.Text import moe.nea.firmament.Firmament import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.commands.RestArgumentType import moe.nea.firmament.commands.get -import moe.nea.firmament.commands.suggestsList import moe.nea.firmament.commands.thenArgument import moe.nea.firmament.commands.thenExecute import moe.nea.firmament.commands.thenLiteral import moe.nea.firmament.events.CommandEvent import moe.nea.firmament.events.HandledScreenKeyPressedEvent +import moe.nea.firmament.events.SlotRenderEvents import moe.nea.firmament.features.debug.DeveloperFeatures import moe.nea.firmament.features.debug.ExportedTestConstantMeta import moe.nea.firmament.features.debug.PowerUserTools @@ -40,6 +40,7 @@ import moe.nea.firmament.util.mc.SNbtFormatter.Companion.toPrettyString import moe.nea.firmament.util.mc.displayNameAccordingToNbt import moe.nea.firmament.util.mc.loreAccordingToNbt import moe.nea.firmament.util.mc.toNbtList +import moe.nea.firmament.util.render.drawGuiTexture import moe.nea.firmament.util.setSkyBlockId import moe.nea.firmament.util.skyBlockId import moe.nea.firmament.util.tr @@ -47,12 +48,29 @@ import moe.nea.firmament.util.tr object ItemExporter { fun exportItem(itemStack: ItemStack): Text { + nonOverlayCache.clear() val exporter = LegacyItemExporter.createExporter(itemStack) - val json = exporter.exportJson() - val jsonFormatted = Firmament.twoSpaceJson.encodeToString(json) + var json = exporter.exportJson() val fileName = json.jsonObject["internalname"]!!.jsonPrimitive.content val itemFile = RepoDownloadManager.repoSavedLocation.resolve("items").resolve("${fileName}.json") itemFile.createParentDirectories() + if (itemFile.exists()) { + val existing = try { + Firmament.json.decodeFromString<JsonObject>(itemFile.readText()) + } catch (ex: Exception) { + ex.printStackTrace() + JsonObject(mapOf()) + } + val mut = json.jsonObject.toMutableMap() + for (prop in existing) { + if (prop.key !in mut || mut[prop.key]!!.let { + (it is JsonPrimitive && (it.content.isEmpty() || it.content == "0")) || (it is JsonArray && it.isEmpty()) || (it is JsonObject && it.isEmpty()) + }) + mut[prop.key] = prop.value + } + json = JsonObject(mut) + } + val jsonFormatted = Firmament.twoSpaceJson.encodeToString(json) itemFile.writeText(jsonFormatted) val overlayFile = RepoDownloadManager.repoSavedLocation.resolve("itemsOverlay") .resolve(ExportedTestConstantMeta.current.dataVersion.toString()) @@ -100,25 +118,42 @@ object ItemExporter { fun onCommand(event: CommandEvent.SubCommand) { event.subcommand(DeveloperFeatures.DEVELOPER_SUBCOMMAND) { thenLiteral("reexportlore") { - thenArgument("itemid", StringArgumentType.string()) { itemid -> - suggestsList { RepoManager.neuRepo.items.items.keys } + thenArgument("itemid", RestArgumentType) { itemid -> + suggests { ctx, builder -> + val spaceIndex = builder.remaining.lastIndexOf(" ") + val (before, after) = + if (spaceIndex < 0) Pair("", builder.remaining) + else Pair( + builder.remaining.substring(0, spaceIndex + 1), + builder.remaining.substring(spaceIndex + 1) + ) + RepoManager.neuRepo.items.items.keys + .asSequence() + .filter { it.startsWith(after, ignoreCase = true) } + .forEach { + builder.suggest(before + it) + } + + builder.buildFuture() + } thenExecute { - val itemid = SkyblockId(get(itemid)) - if (pathFor(itemid).notExists()) { + for (itemid in get(itemid).split(" ").map { SkyblockId(it) }) { + if (pathFor(itemid).notExists()) { + MC.sendChat( + tr( + "firmament.repo.export.relore.fail", + "Could not find json file to relore for ${itemid}" + ) + ) + } + fixLoreNbtFor(itemid) MC.sendChat( tr( - "firmament.repo.export.relore.fail", - "Could not find json file to relore for ${itemid}" + "firmament.repo.export.relore", + "Updated lore / display name for $itemid" ) ) } - fixLoreNbtFor(itemid) - MC.sendChat( - tr( - "firmament.repo.export.relore", - "Updated lore / display name for $itemid" - ) - ) } } thenLiteral("all") { @@ -172,6 +207,27 @@ object ItemExporter { } } + val nonOverlayCache = mutableMapOf<SkyblockId, Boolean>() + + @Subscribe + fun onRender(event: SlotRenderEvents.Before) { + if (!PowerUserTools.TConfig.highlightNonOverlayItems) { + return + } + val stack = event.slot.stack ?: return + val isExported = nonOverlayCache.getOrPut(stack.skyBlockId ?: return) { + RepoDownloadManager.repoSavedLocation.resolve("itemsOverlay") + .resolve(ExportedTestConstantMeta.current.dataVersion.toString()) + .resolve("${stack.skyBlockId}.snbt") + .exists() + } + if (!isExported) + event.context.drawGuiTexture( + Firmament.identifier("selected_pet_background"), + event.slot.x, event.slot.y, 16, 16, + ) + } + fun exportStub(skyblockId: SkyblockId, title: String, extra: (ItemStack) -> Unit = {}) { exportItem(ItemStack(Items.PLAYER_HEAD).also { it.displayNameAccordingToNbt = Text.literal(title) diff --git a/src/main/kotlin/features/debug/itemeditor/LegacyItemData.kt b/src/main/kotlin/features/debug/itemeditor/LegacyItemData.kt index c0f48ca..bc8c618 100644 --- a/src/main/kotlin/features/debug/itemeditor/LegacyItemData.kt +++ b/src/main/kotlin/features/debug/itemeditor/LegacyItemData.kt @@ -9,6 +9,7 @@ import moe.nea.firmament.Firmament import moe.nea.firmament.repo.ExpensiveItemCacheApi import moe.nea.firmament.repo.ItemCache import moe.nea.firmament.util.MC +import moe.nea.firmament.util.StringUtil.camelWords /** * Load data based on [prismarine.js' 1.8 item data](https://github.com/PrismarineJS/minecraft-data/blob/master/data/pc/1.8/items.json) @@ -58,6 +59,7 @@ object LegacyItemData { val enchantmentLut = enchantmentData.associateBy { Identifier.ofVanilla(it.name) } val itemDat = getLegacyData<List<ItemData>>("items") + @OptIn(ExpensiveItemCacheApi::class) // This is fine, we get loaded in a thread. val itemLut = itemDat.flatMap { item -> item.allVariants().map { legacyItemType -> @@ -72,4 +74,16 @@ object LegacyItemData { } }.toMap() + @Serializable + data class LegacyEffect( + val id: Int, + val name: String, + val displayName: String, + val type: String + ) + + val effectList = getLegacyData<List<LegacyEffect>>("effects") + .associateBy { + it.name.camelWords().map { it.trim().lowercase() }.joinToString("_") + } } diff --git a/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt b/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt index 3cd1ce8..ad03b16 100644 --- a/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt +++ b/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt @@ -7,9 +7,11 @@ import kotlinx.serialization.json.put import kotlin.concurrent.thread import net.minecraft.component.DataComponentTypes import net.minecraft.item.ItemStack +import net.minecraft.nbt.NbtByte import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtElement import net.minecraft.nbt.NbtInt +import net.minecraft.nbt.NbtList import net.minecraft.nbt.NbtOps import net.minecraft.nbt.NbtString import net.minecraft.text.Text @@ -36,8 +38,9 @@ import moe.nea.firmament.util.unformattedString class LegacyItemExporter private constructor(var itemStack: ItemStack) { init { - require(!itemStack.isEmpty) + require(!itemStack.isEmpty) } + var lore = itemStack.loreAccordingToNbt var name = itemStack.displayNameAccordingToNbt val extraAttribs = itemStack.extraAttributes.copy() @@ -133,24 +136,55 @@ class LegacyItemExporter private constructor(var itemStack: ItemStack) { legacyNbt.put("HideFlags", NbtInt.of(254)) copyUnbreakable() copyItemModel() + copyPotion() copyExtraAttributes() copyLegacySkullNbt() copyDisplay() + copyColour() copyEnchantments() copyEnchantGlint() // TODO: copyDisplay } + private fun copyPotion() { + val effects = itemStack.get(DataComponentTypes.POTION_CONTENTS) ?: return + legacyNbt.put("CustomPotionEffects", NbtList().also { + effects.effects.forEach { effect -> + val effectId = effect.effectType.key.get().value.path + val duration = effect.duration + val legacyId = LegacyItemData.effectList[effectId]!! + + it.add(NbtCompound().apply { + put("Ambient", NbtByte.of(false)) + put("Duration", NbtInt.of(duration)) + put("Id", NbtByte.of(legacyId.id.toByte())) + put("Amplifier", NbtByte.of(effect.amplifier.toByte())) + }) + } + }) + } + + fun NbtCompound.getOrPutCompound(name: String): NbtCompound { + val compound = getCompoundOrEmpty(name) + put(name, compound) + return compound + } + + private fun copyColour() { + val leatherTint = itemStack.get(DataComponentTypes.DYED_COLOR) ?: return + legacyNbt.getOrPutCompound("display").put("color", NbtInt.of(leatherTint.rgb)) + } + private fun copyItemModel() { val itemModel = itemStack.get(DataComponentTypes.ITEM_MODEL) ?: return legacyNbt.put("ItemModel", NbtString.of(itemModel.toString())) } private fun copyDisplay() { - legacyNbt.put("display", NbtCompound().apply { + legacyNbt.getOrPutCompound("display").apply { put("Lore", lore.map { NbtString.of(it.getLegacyFormatString(trimmed = true)) }.toNbtList()) putString("Name", name.getLegacyFormatString(trimmed = true)) - }) + } } fun exportModernSnbt(): NbtElement { |