using 'smelting dictionary' for smelter recipes

This commit is contained in:
minjaesong
2024-03-10 00:46:46 +09:00
parent c6999e0794
commit 247cf9bd33
14 changed files with 681 additions and 111 deletions

View File

@@ -1,13 +1,11 @@
package net.torvald.terrarum.itemproperties
import com.badlogic.gdx.utils.JsonValue
import net.torvald.terrarum.INGAME
import net.torvald.terrarum.ItemCodex
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameitems.isBlock
import net.torvald.terrarum.gameitems.isWall
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
import net.torvald.terrarum.utils.forEachSiblings
import net.torvald.terrarum.utils.forEachSiblingsIndexed
@@ -22,6 +20,8 @@ class CraftingCodex {
*/
@Transient internal val props = HashMap<ItemID, ArrayList<CraftingRecipe>>() // the key ItemID and value.product must be equal
@Transient internal val smeltingProps = HashMap<String, SmeltingRecipe>()
fun addRecipe(recipe: CraftingRecipe) {
val product = recipe.product
if (props.containsKey(product)) {
@@ -88,6 +88,27 @@ class CraftingCodex {
}
}
fun addSmeltingFromJson(json: JsonValue, moduleName: String, fileName:String) {
if (moduleName.filter { it.code in 33..127 } .length < 5)
throw IllegalStateException("Invalid module name: ${moduleName}")
json.forEachSiblings { key0, details ->
val key = key0.split('+').map { it.trim() }.sorted().joinToString("+")
val difficulty = details["difficulty"].asFloat()
val recipes = ArrayList<SmeltingRecipe>()
val moq = details["product"][0].asLong()
val product = details["product"][1].asString()
// sanity check
if (moq !in 1..1000) {
throw IllegalStateException("Smelting Recipe for item '$product' has invalid moq of ${moq}")
}
// register to the main props
smeltingProps[key] = SmeltingRecipe(difficulty, key.split('+').toTypedArray(), moq, product, "$moduleName/$fileName")
}
}
/**
* Returns list of all possible recipes for the item; null if there is no recipe
*
@@ -98,6 +119,55 @@ class CraftingCodex {
return it.ifEmpty { null }
}
private fun getCombinations0(data: List<List<String>>): List<List<String>> {
if (data.isEmpty()) {
return listOf(emptyList())
}
val first = data.first()
val rest = data.subList(1, data.size)
val combinations = mutableListOf<List<String>>()
for (sublist in getCombinations0(rest)) {
for (item in first) {
combinations.add(listOf(item) + sublist)
}
}
return combinations
}
private fun getCombinations(data: List<List<String>>): List<String> {
val r = mutableListOf<String>()
val l = getCombinations0(data)
l.forEach {
r.add(it.sorted().joinToString("+"))
}
return r
}
/**
* @return Null if:
* - at least one of the vararg contains null
* - a smelting product of given items does not exist
* - Otherwise, a smelting product of the given items are returned
*/
fun getSmeltingProductOf(vararg item: ItemID?): SmeltingRecipe? {
if (item.contains(null)) return null
val keysPossible0: List<List<String>> =
(item.map { listOf(it!!) + (ItemCodex[it]?.tags?.toList()?.map { "\$" + it } ?: emptyList()) })
val keysPossible = getCombinations(keysPossible0)
// iterate through all the combinations of keys
var found: SmeltingRecipe? = null
var i = 0
while (found == null && i < keysPossible.size) {
found = smeltingProps[keysPossible[i]]
i += 1
}
return found
}
/**
* Returns list of items that uses the given `item`.
*
@@ -118,6 +188,7 @@ class CraftingCodex {
}
}
/**
* @return list of itemIDs and corresponding recipes
*/
@@ -128,6 +199,7 @@ class CraftingCodex {
data class SmeltingRecipe(val difficulty: Float, val ingredients: Array<ItemID>, val moq: Long, val item: ItemID, val addedBy: String)
data class CraftingRecipe(val workbench: String, val ingredients: Array<CraftingIngredients>, val moq: Long, val product: ItemID, val addedBy: String)
data class CraftingIngredients(val key: String, val keyMode: CraftingItemKeyMode, val qty: Long) {
override fun toString() = "$qty ${if (keyMode == CraftingItemKeyMode.TAG) "\$$key" else "$key"}"