feat: Add crafting recipe exporter

This commit is contained in:
Linnea Gräf
2025-06-22 20:25:46 +02:00
parent 05ca14b623
commit 89047619c6
3 changed files with 106 additions and 25 deletions

View File

@@ -57,6 +57,7 @@ object PowerUserTools : FirmamentFeature {
val copyItemStack by keyBindingWithDefaultUnbound("copy-item-stack")
val copyTitle by keyBindingWithDefaultUnbound("copy-title")
val exportItemStackToRepo by keyBindingWithDefaultUnbound("export-item-stack")
val exportUIRecipes by keyBindingWithDefaultUnbound("export-recipe")
}
override val config

View File

@@ -0,0 +1,57 @@
package moe.nea.firmament.features.debug.itemeditor
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.HandledScreenKeyPressedEvent
import moe.nea.firmament.features.debug.PowerUserTools
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.mc.ScreenUtil.getSlotByIndex
import moe.nea.firmament.util.skyBlockId
import moe.nea.firmament.util.tr
object ExportRecipe {
val xNames = "ABC"
val yNames = "123"
val slotIndices = (0..<9).map {
val x = it % 3
val y = it / 3
(xNames[x].toString() + yNames[y]) to x + y * 9 + 10
}
val resultSlot = 25
@Subscribe
fun onRecipeKeyBind(event: HandledScreenKeyPressedEvent) {
if (!event.matches(PowerUserTools.TConfig.exportUIRecipes)) {
return
}
if (!event.screen.title.string.endsWith(" Recipe")) {
MC.sendChat(tr("firmament.repo.export.recipe.fail", "No Recipe found"))
return
}
slotIndices.forEach { (_, index) ->
event.screen.getSlotByIndex(index, false)?.stack?.let(ItemExporter::ensureExported)
}
val inputs = slotIndices.associate { (name, index) ->
val id = event.screen.getSlotByIndex(index, false)?.stack?.takeIf { !it.isEmpty() }?.let {
"${it.skyBlockId?.neuItem}:${it.count}"
} ?: ""
name to JsonPrimitive(id)
}
val output = event.screen.getSlotByIndex(resultSlot, false)?.stack!!
val overrideOutputId = output.skyBlockId!!.neuItem
val count = output.count
val recipe = JsonObject(
inputs + mapOf(
"type" to JsonPrimitive("crafting"),
"count" to JsonPrimitive(count),
"overrideOutputId" to JsonPrimitive(overrideOutputId)
)
)
ItemExporter.appendRecipe(output.skyBlockId!!, recipe)
}
}

View File

@@ -1,53 +1,76 @@
package moe.nea.firmament.features.debug.itemeditor
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import kotlin.io.path.createParentDirectories
import kotlin.io.path.exists
import kotlin.io.path.readText
import kotlin.io.path.relativeTo
import kotlin.io.path.writeText
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtOps
import net.minecraft.text.Text
import moe.nea.firmament.Firmament
import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.HandledScreenKeyPressedEvent
import moe.nea.firmament.features.debug.ExportedTestConstantMeta
import moe.nea.firmament.features.debug.PowerUserTools
import moe.nea.firmament.repo.RepoDownloadManager
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.focusedItemStack
import moe.nea.firmament.util.mc.SNbtFormatter.Companion.toPrettyString
import moe.nea.firmament.util.skyBlockId
import moe.nea.firmament.util.tr
object ItemExporter {
fun exportItem(itemStack: ItemStack): Text {
val exporter = LegacyItemExporter.createExporter(itemStack)
val json = exporter.exportJson()
val jsonFormatted = Firmament.twoSpaceJson.encodeToString(json)
val fileName = json.jsonObject["internalname"]!!.jsonPrimitive.content
val itemFile = RepoDownloadManager.repoSavedLocation.resolve("items").resolve("${fileName}.json")
itemFile.createParentDirectories()
itemFile.writeText(jsonFormatted)
val overlayFile = RepoDownloadManager.repoSavedLocation.resolve("itemsOverlay")
.resolve(ExportedTestConstantMeta.current.dataVersion.toString())
.resolve("${fileName}.snbt")
overlayFile.createParentDirectories()
overlayFile.writeText(exporter.exportModernSnbt().toPrettyString())
return tr(
"firmament.repoexport.success",
"Exported item to ${itemFile.relativeTo(RepoDownloadManager.repoSavedLocation)}${
exporter.warnings.joinToString(
""
) { "\nWarning: $it" }
}"
)
}
fun pathFor(skyBlockId: SkyblockId) =
RepoManager.neuRepo.baseFolder.resolve("items/${skyBlockId.neuItem}.json")
fun ensureExported(itemStack: ItemStack) {
if (!pathFor(itemStack.skyBlockId ?: return).exists())
exportItem(itemStack)
}
fun appendRecipe(skyblockId: SkyblockId, recipe: JsonObject) {
val oldJson = Firmament.json.decodeFromString<JsonObject>(pathFor(skyblockId).readText())
val mutableJson = oldJson.toMutableMap()
val recipes = ((mutableJson["recipes"] as JsonArray?) ?: listOf()).toMutableList()
recipes.add(recipe)
mutableJson["recipes"] = JsonArray(recipes)
pathFor(skyblockId).writeText(Firmament.twoSpaceJson.encodeToString(JsonObject(mutableJson)))
}
@Subscribe
fun onKeyBind(event: HandledScreenKeyPressedEvent) {
if (event.matches(PowerUserTools.TConfig.exportItemStackToRepo)) {
val itemStack = event.screen.focusedItemStack ?: return
val exporter = LegacyItemExporter.createExporter(itemStack)
val json = exporter.exportJson()
val jsonFormatted = Firmament.twoSpaceJson.encodeToString(json)
val fileName = json.jsonObject["internalname"]!!.jsonPrimitive.content
val itemFile = RepoDownloadManager.repoSavedLocation.resolve("items").resolve("${fileName}.json")
itemFile.createParentDirectories()
itemFile.writeText(jsonFormatted)
val overlayFile = RepoDownloadManager.repoSavedLocation.resolve("itemsOverlay")
.resolve(ExportedTestConstantMeta.current.dataVersion.toString())
.resolve("${fileName}.snbt")
overlayFile.createParentDirectories()
overlayFile.writeText(exporter.exportModernSnbt().toPrettyString())
PowerUserTools.lastCopiedStack = Pair(
itemStack,
tr(
"firmament.repoexport.success",
"Exported item to ${itemFile.relativeTo(RepoDownloadManager.repoSavedLocation)}${
exporter.warnings.joinToString(
""
) { "\nWarning: $it" }
}"
)
)
PowerUserTools.lastCopiedStack = (itemStack to exportItem(itemStack))
}
}
}