crafting: mutual exclusiveness for $WALL tag

This commit is contained in:
minjaesong
2023-09-17 15:16:04 +09:00
parent 0a62037896
commit af36cec60f
5 changed files with 37 additions and 34 deletions

View File

@@ -29,10 +29,13 @@ Each entry is interpreted as:
For example: 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, This line is interpreted as: this item requires 1 tagged-as-wood and tagged-as-wall ingredient and
and returns 2 of crafted items. 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"]``` ```[20, 1, "ITEM_PLATFORM_BUILDING_KIT"]```

View File

@@ -360,6 +360,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
} }
fun hasTag(s: String) = tags.contains(s) fun hasTag(s: String) = tags.contains(s)
fun hasAllTags(s: List<String>) = tags.containsAll(s)
companion object { companion object {

View File

@@ -47,7 +47,7 @@ class CraftingCodex {
itemsStr.forEachIndexed { i, itemStr -> itemsStr.forEachIndexed { i, itemStr ->
ingredients.add(CraftingIngredients( ingredients.add(CraftingIngredients(
if (itemStr.startsWith("$")) if (itemStr.startsWith("$"))
itemStr.substring(1) itemStr.substring(1).replace('$',',')
else else
itemStr itemStr
, ,

View File

@@ -64,7 +64,9 @@ class EntryPoint : ModuleEntryPoint() {
if (IS_DEVELOPMENT_BUILD) print(tile.id+" ") if (IS_DEVELOPMENT_BUILD) print(tile.id+" ")
if (BlockCodex[tile.id].isWallable) { 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 + " ") if (IS_DEVELOPMENT_BUILD) print("wall@" + tile.id + " ")
} }
} }

View File

@@ -10,6 +10,7 @@ import net.torvald.terrarum.UIItemInventoryCatBar.Companion.CAT_ALL
import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameitems.GameItem import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.ItemID import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameitems.isWall
import net.torvald.terrarum.itemproperties.CraftingCodex import net.torvald.terrarum.itemproperties.CraftingCodex
import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
@@ -217,8 +218,10 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
val itemID = gameItem.dynamicID val itemID = gameItem.dynamicID
// don't rely on highlightedness of the button to determine the item on the button is the selected // 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) // 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 val targetItemToAlter = recipe.ingredients.filter { (key, mode) -> // 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 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 { }.let {
if (it.size > 1) if (it.size > 1)
println("[UICrafting] Your recipe seems to have two similar ingredients defined\n" + 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() it.firstOrNull()
} }
targetItemToAlter?.let { targetItemToAlter?.let { (key, mode) ->
val oldItem = _getItemListIngredients().getInventory().first { itemPair -> val oldItem = _getItemListIngredients().getInventory().first { (itm, qty) ->
(it.keyMode == CraftingCodex.CraftingItemKeyMode.TAG && ItemCodex[itemPair.itm]!!.hasTag(it.key)) 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) changeIngredient(oldItem, itemID)
refreshCraftButtonStatus() refreshCraftButtonStatus()
@@ -259,20 +264,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
recipeClicked = recipe recipeClicked = recipe
// printdbg(this, "Recipe selected: $recipe") // printdbg(this, "Recipe selected: $recipe")
recipe.ingredients.forEach { ingredient -> recipe.ingredients.forEach { ingredient ->
val selectedItem: ItemID = if (ingredient.keyMode == CraftingCodex.CraftingItemKeyMode.TAG) { val selectedItem = getItemForIngredient(playerInventory, ingredient)
// 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
}
selectedItems.add(selectedItem) selectedItems.add(selectedItem)
ingredients.add(selectedItem, ingredient.qty) ingredients.add(selectedItem, ingredient.qty)
} }
@@ -536,22 +528,27 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
val craftingStationAvailable: Boolean, 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) * 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<String>): List<RecipeIngredientRecord> { fun recipeToIngredientRecord(inventory: FixtureInventory, recipe: CraftingCodex.CraftingRecipe, nearbyCraftingStations: List<String>): List<RecipeIngredientRecord> {
val hasStation = if (recipe.workbench.isBlank()) true else nearbyCraftingStations.contains(recipe.workbench) val hasStation = if (recipe.workbench.isBlank()) true else nearbyCraftingStations.contains(recipe.workbench)
return recipe.ingredients.map { ingredient -> return recipe.ingredients.map { ingredient ->
val selectedItem = if (ingredient.keyMode == CraftingCodex.CraftingItemKeyMode.TAG) { val selectedItem = getItemForIngredient(inventory, ingredient)
// 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 howManyPlayerHas = inventory.searchByID(selectedItem)?.qty ?: 0L val howManyPlayerHas = inventory.searchByID(selectedItem)?.qty ?: 0L
val howManyTheRecipeWants = ingredient.qty val howManyTheRecipeWants = ingredient.qty