package net.torvald.terrarum.itemproperties import com.badlogic.gdx.utils.JsonValue import net.torvald.terrarum.gameitems.ItemID import net.torvald.terrarum.utils.forEachSiblings import net.torvald.terrarum.utils.forEachSiblingsIndexed /** * Created by minjaesong on 2022-06-24. */ class CraftingCodex { @Transient internal val props = HashMap>() // the key ItemID and value.product must be equal fun addFromJson(json: JsonValue, moduleName: String, fileName:String) { if (moduleName.filter { it.code in 33..127 } .length < 5) throw IllegalStateException("Invalid module name: ${moduleName}") json.forEachSiblings { itemName, details -> val workbenchStr = details["workbench"].asString() val recipes = ArrayList() details["ingredients"].forEachSiblingsIndexed { ingredientIndex, _, ingredientRecord -> var moq = -1L val qtys = ArrayList() val itemsStr = ArrayList() ingredientRecord.forEachIndexed { i, elem -> if (i == 0) { moq = elem.asLong() } else { if (i % 2 == 1) qtys.add(elem.asLong()) else itemsStr.add(elem.asString()) } } // sanity check if (moq !in 1..1000) throw IllegalStateException("Recipe #${ingredientIndex+1} for item '$itemName' has invalid moq of ${moq}") else if (qtys.size != itemsStr.size) throw IllegalStateException("Mismatched item name and count for recipe #${ingredientIndex+1} for item '$itemName'") val ingredients = ArrayList() itemsStr.forEachIndexed { i, itemStr -> ingredients.add(CraftingIngredients( if (itemStr.startsWith("$")) itemStr.substring(1) else itemStr , if (itemStr.startsWith("$")) CraftingItemKeyMode.TAG else CraftingItemKeyMode.VERBATIM , qtys[i] )) } recipes.add(CraftingRecipe(workbenchStr, ingredients.toTypedArray(), moq, itemName, "$moduleName/$fileName")) } // register to the main props if (props[itemName] == null) props[itemName] = ArrayList() props[itemName]!!.addAll(recipes) } } /** * Returns list of all possible recipes for the item; null if there is no recipe * * Even if the props for the specified item is happens to exist but has no element (usually caused by bad mod behaviour), * this function is guaranteed to return null. */ fun getRecipesFor(itemID: ItemID): List? = props[itemID]?.toList()?.let { return it.ifEmpty { null } } /** * @return list of itemIDs and corresponding recipes */ fun getRecipesUsingTheseItems(items: List): List { TODO() } /** * @return list of itemIDs and corresponding recipes */ fun getRecipesForIngredients(ingredients: List>): List { TODO() } data class CraftingRecipe(val workbench: String, val ingredients: Array, val moq: Long, val product: ItemID, val addedBy: String) data class CraftingIngredients(val key: String, val keyMode: CraftingItemKeyMode, val qty: Long) enum class CraftingItemKeyMode { VERBATIM, TAG } }