diff --git a/assets/mods/basegame/crafting/doc.md b/assets/mods/basegame/crafting/doc.md index 9c2dc53cb..0c52c5341 100644 --- a/assets/mods/basegame/crafting/doc.md +++ b/assets/mods/basegame/crafting/doc.md @@ -29,10 +29,13 @@ Each entry is interpreted as: For example: -```[2, 1, "$WOOD", 1, "$ROCK"]``` +```[2, 1, "$WOOD$WALL", 1, "$ROCK"]``` -This line is interpreted as: this item requires 1 tagged-as-wood ingredient and 1 tagged-as-rock ingredient, -and returns 2 of crafted items. +This line is interpreted as: this item requires 1 tagged-as-wood and tagged-as-wall ingredient and +1 tagged-as-rock ingredient, and returns 2 of crafted items. + +$WALL tag is treated specially as state of "having $WALL tag" and "not having $WALL tag" is mutually exclusive; +Ingredient Resolver will NOT look for walls if there is no $WALL tag ```[20, 1, "ITEM_PLATFORM_BUILDING_KIT"]``` diff --git a/src/net/torvald/terrarum/gameitems/GameItem.kt b/src/net/torvald/terrarum/gameitems/GameItem.kt index 8d788e0a5..b15221504 100644 --- a/src/net/torvald/terrarum/gameitems/GameItem.kt +++ b/src/net/torvald/terrarum/gameitems/GameItem.kt @@ -360,6 +360,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable, Cloneabl } fun hasTag(s: String) = tags.contains(s) + fun hasAllTags(s: List) = tags.containsAll(s) companion object { diff --git a/src/net/torvald/terrarum/itemproperties/CraftingCodex.kt b/src/net/torvald/terrarum/itemproperties/CraftingCodex.kt index 834e25567..51b12366a 100644 --- a/src/net/torvald/terrarum/itemproperties/CraftingCodex.kt +++ b/src/net/torvald/terrarum/itemproperties/CraftingCodex.kt @@ -47,7 +47,7 @@ class CraftingCodex { itemsStr.forEachIndexed { i, itemStr -> ingredients.add(CraftingIngredients( if (itemStr.startsWith("$")) - itemStr.substring(1) + itemStr.substring(1).replace('$',',') else itemStr , diff --git a/src/net/torvald/terrarum/modulebasegame/EntryPoint.kt b/src/net/torvald/terrarum/modulebasegame/EntryPoint.kt index 11b53519c..7a3eebe2a 100644 --- a/src/net/torvald/terrarum/modulebasegame/EntryPoint.kt +++ b/src/net/torvald/terrarum/modulebasegame/EntryPoint.kt @@ -64,7 +64,9 @@ class EntryPoint : ModuleEntryPoint() { if (IS_DEVELOPMENT_BUILD) print(tile.id+" ") if (BlockCodex[tile.id].isWallable) { - ItemCodex["wall@" + tile.id] = makeNewItemObj(tile, true) + ItemCodex["wall@" + tile.id] = makeNewItemObj(tile, true).also { + it.tags.add("WALL") + } if (IS_DEVELOPMENT_BUILD) print("wall@" + tile.id + " ") } } diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UICrafting.kt b/src/net/torvald/terrarum/modulebasegame/ui/UICrafting.kt index 6792c11a2..b0dcc85c9 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UICrafting.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UICrafting.kt @@ -10,6 +10,7 @@ import net.torvald.terrarum.UIItemInventoryCatBar.Companion.CAT_ALL import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.gameitems.GameItem import net.torvald.terrarum.gameitems.ItemID +import net.torvald.terrarum.gameitems.isWall import net.torvald.terrarum.itemproperties.CraftingCodex import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory @@ -217,8 +218,10 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory { val itemID = gameItem.dynamicID // don't rely on highlightedness of the button to determine the item on the button is the selected // ingredient (because I don't fully trust my code lol) - val targetItemToAlter = recipe.ingredients.filter { // altering recipe doesn't make sense if player selected a recipe that requires no tag-ingredients - (it.keyMode == CraftingCodex.CraftingItemKeyMode.TAG && gameItem.hasTag(it.key)) + val targetItemToAlter = recipe.ingredients.filter { (key, mode) -> // altering recipe doesn't make sense if player selected a recipe that requires no tag-ingredients + val tags = key.split(',') + val wantsWall = tags.contains("WALL") + (mode == CraftingCodex.CraftingItemKeyMode.TAG && gameItem.hasAllTags(tags) && (wantsWall == gameItem.originalID.isWall())) // true if (wants wall and is wall) or (wants no wall and is not wall) }.let { if (it.size > 1) println("[UICrafting] Your recipe seems to have two similar ingredients defined\n" + @@ -227,9 +230,11 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory { it.firstOrNull() } - targetItemToAlter?.let { - val oldItem = _getItemListIngredients().getInventory().first { itemPair -> - (it.keyMode == CraftingCodex.CraftingItemKeyMode.TAG && ItemCodex[itemPair.itm]!!.hasTag(it.key)) + targetItemToAlter?.let { (key, mode) -> + val oldItem = _getItemListIngredients().getInventory().first { (itm, qty) -> + val tags = key.split(',') + val wantsWall = tags.contains("WALL") + (mode == CraftingCodex.CraftingItemKeyMode.TAG && ItemCodex[itm]!!.hasAllTags(tags) && (wantsWall == itm.isWall())) // true if (wants wall and is wall) or (wants no wall and is not wall) } changeIngredient(oldItem, itemID) refreshCraftButtonStatus() @@ -259,20 +264,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory { recipeClicked = recipe // printdbg(this, "Recipe selected: $recipe") recipe.ingredients.forEach { ingredient -> - val selectedItem: ItemID = if (ingredient.keyMode == CraftingCodex.CraftingItemKeyMode.TAG) { - // If the player has the required item, use it; otherwise, will take an item from the ItemCodex - val selectedItem = playerInventory.filter { (itm, qty) -> - ItemCodex[itm]?.tags?.contains(ingredient.key) == true && qty >= ingredient.qty - }.maxByOrNull { it.qty }?.itm ?: ((ItemCodex.itemCodex.firstNotNullOfOrNull { if (it.value.hasTag(ingredient.key)) it.key else null }) ?: throw NullPointerException("Item with tag '${ingredient.key}' not found. Possible cause: game or a module not updated or installed")) - -// printdbg(this, "Adding ingredients by tag ${selectedItem} (${ingredient.qty})") - selectedItem - } - else { -// printdbg(this, "Adding ingredients by name ${ingredient.key} (${ingredient.qty})") - ingredient.key - } - + val selectedItem = getItemForIngredient(playerInventory, ingredient) selectedItems.add(selectedItem) ingredients.add(selectedItem, ingredient.qty) } @@ -536,22 +528,27 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory { val craftingStationAvailable: Boolean, ) + fun getItemForIngredient(inventory: FixtureInventory, ingredient: CraftingCodex.CraftingIngredients): ItemID { + return if (ingredient.keyMode == CraftingCodex.CraftingItemKeyMode.TAG) { + val tags = ingredient.key.split(',') + val wantsWall = tags.contains("WALL") + // If the player has the required item, use it; otherwise, will take an item from the ItemCodex + inventory.filter { (itm, qty) -> + ItemCodex[itm]?.hasAllTags(tags) == true && qty >= ingredient.qty && (wantsWall == itm.isWall()) // true if (wants wall and is wall) or (wants no wall and is not wall) + }.maxByOrNull { it.qty }?.itm ?: ((ItemCodex.itemCodex.firstNotNullOfOrNull { if (it.value.hasTag(ingredient.key)) it.key else null }) ?: throw NullPointerException("Item with tag '${ingredient.key}' not found. Possible cause: game or a module not updated or installed")) + } + else { + ingredient.key + } + } + /** * For each ingredient of the recipe, returns list of (ingredient, how many the player has the ingredient, how many the recipe wants) */ fun recipeToIngredientRecord(inventory: FixtureInventory, recipe: CraftingCodex.CraftingRecipe, nearbyCraftingStations: List): List { val hasStation = if (recipe.workbench.isBlank()) true else nearbyCraftingStations.contains(recipe.workbench) return recipe.ingredients.map { ingredient -> - val selectedItem = if (ingredient.keyMode == CraftingCodex.CraftingItemKeyMode.TAG) { - // If the player has the required item, use it; otherwise, will take an item from the ItemCodex - inventory.filter { (itm, qty) -> - ItemCodex[itm]?.tags?.contains(ingredient.key) == true && qty >= ingredient.qty - }.maxByOrNull { it.qty }?.itm ?: ((ItemCodex.itemCodex.firstNotNullOfOrNull { if (it.value.hasTag(ingredient.key)) it.key else null }) ?: throw NullPointerException("Item with tag '${ingredient.key}' not found. Possible cause: game or a module not updated or installed")) - } - else { - ingredient.key - } - + val selectedItem = getItemForIngredient(inventory, ingredient) val howManyPlayerHas = inventory.searchByID(selectedItem)?.qty ?: 0L val howManyTheRecipeWants = ingredient.qty