diff --git a/src/net/torvald/terrarum/TerrarumAppConfiguration.kt b/src/net/torvald/terrarum/TerrarumAppConfiguration.kt index 14b40f1a3..dd11b8303 100644 --- a/src/net/torvald/terrarum/TerrarumAppConfiguration.kt +++ b/src/net/torvald/terrarum/TerrarumAppConfiguration.kt @@ -73,8 +73,8 @@ basegame // Commit counts up to the Release 0.3.3: 3020 // val VERSION_SNAPSHOT = Snapshot(0) // for normal dev - val VERSION_SNAPSHOT = ForcedSnapshot("24w07c") // for snapshot release -// val VERSION_SNAPSHOT = null // for the release +// val VERSION_SNAPSHOT = ForcedSnapshot("24w07d") // for snapshot release + val VERSION_SNAPSHOT = null // for the release const val VERSION_TAG: String = "" diff --git a/src/net/torvald/terrarum/itemproperties/CraftingCodex.kt b/src/net/torvald/terrarum/itemproperties/CraftingCodex.kt index 3011038b1..f0f31bbdf 100644 --- a/src/net/torvald/terrarum/itemproperties/CraftingCodex.kt +++ b/src/net/torvald/terrarum/itemproperties/CraftingCodex.kt @@ -1,7 +1,13 @@ package net.torvald.terrarum.itemproperties import com.badlogic.gdx.utils.JsonValue +import net.torvald.terrarum.INGAME +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 @@ -10,6 +16,10 @@ import net.torvald.terrarum.utils.forEachSiblingsIndexed */ class CraftingCodex { + /** + * Key: final product of the given recipes. Equal to the recipe.product + * Value: the recipes + */ @Transient internal val props = HashMap>() // the key ItemID and value.product must be equal fun addRecipe(recipe: CraftingRecipe) { @@ -89,10 +99,23 @@ class CraftingCodex { } /** + * Returns list of items that uses the given `item`. + * * @return list of itemIDs and corresponding recipes */ - fun getRecipesUsingTheseItems(items: List): List { - TODO() + fun getCraftableRecipesUsingTheseItems(item: ItemID): List { + return props.values.flatten().filter { recipe -> + recipe.ingredients.any { ingredient -> + when (ingredient.keyMode) { + CraftingItemKeyMode.TAG -> if (item.isBlock() || item.isWall()) + Terrarum.blockCodex[item].hasTag(ingredient.key) + else + Terrarum.itemCodex[item]!!.hasTag(ingredient.key) + + CraftingItemKeyMode.VERBATIM -> (item == ingredient.key) + } + } + } } /** diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UICrafting.kt b/src/net/torvald/terrarum/modulebasegame/ui/UICrafting.kt index aceb0ce59..000117964 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UICrafting.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UICrafting.kt @@ -35,33 +35,60 @@ class UICrafting(val full: UIInventoryFull?) : UICanvas( override var width = Toolkit.drawWidth override var height = App.scr.height - private val playerThings = UITemplateHalfInventory(this, false).also { - it.itemListTouchDownFun = { gameItem, _, _, _, _ -> recipeClicked?.let { recipe -> gameItem?.let { gameItem -> + private val playerThings = UITemplateHalfInventory(this, false).also { pt -> + pt.itemListTouchDownFun = { gameItem, _, _, _, theButton -> if (gameItem != null) { + val recipe = recipeClicked 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 { (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" + - "affected ingredients: ${it.joinToString()}\n" + - "the recipe: ${recipe}") - it.firstOrNull() - } - 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) + // change ingredient used + if (recipe != null) { + // 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 { (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" + + "affected ingredients: ${it.joinToString()}\n" + + "the recipe: ${recipe}" + ) + it.firstOrNull() + } + + 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(recipe, oldItem, itemID) + refreshCraftButtonStatus() } - changeIngredient(recipe, oldItem, itemID) - refreshCraftButtonStatus() } - } } } + // show all the items that can be made using this ingredient + else { + itemListCraftable.rebuild(arrayOf(itemID)) + pt.itemList.clearForceHighlightList() + pt.itemList.addToForceHighlightList(listOf(itemID)) + + if (itemListCraftable.craftingRecipes.isEmpty()) { + pt.itemList.clearForceHighlightList() + itemListCraftable.rebuild(FILTER_CAT_ALL) + } + } + } + else { + pt.itemList.clearForceHighlightList() + recipeClicked = null + filterPlayerListUsing(recipeClicked) + highlightCraftingCandidateButton(null) + ingredients.clear() + itemListIngredients.rebuild(FILTER_CAT_ALL) + }} } private val itemListCraftable: UIItemCraftingCandidateGrid // might be changed to something else @@ -69,7 +96,6 @@ class UICrafting(val full: UIInventoryFull?) : UICanvas( private val buttonCraft: UIItemTextButton private val spinnerCraftCount: UIItemSpinner - private val craftables = FixtureInventory() // might be changed to something else private val ingredients = FixtureInventory() // this one is definitely not to be changed private val negotiator = object : InventoryTransactionNegotiator() { @@ -83,7 +109,7 @@ class UICrafting(val full: UIInventoryFull?) : UICanvas( } override fun getNegotiator() = negotiator - override fun getFixtureInventory(): FixtureInventory = craftables + override fun getFixtureInventory(): FixtureInventory = TODO() override fun getPlayerInventory(): FixtureInventory = INGAME.actorNowPlaying!!.inventory private val halfSlotOffset = (UIItemInventoryElemSimple.height + listGap) / 2 @@ -228,7 +254,7 @@ class UICrafting(val full: UIInventoryFull?) : UICanvas( _getItemListPlayer().removeFromForceHighlightList(oldSelectedItems) _getItemListPlayer().addToForceHighlightList(selectedItems) - _getItemListPlayer().itemPage = 0 + if (recipe != null) _getItemListPlayer().itemPage = 0 filterPlayerListUsing(recipeClicked) _getItemListIngredients().rebuild(FILTER_CAT_ALL) @@ -237,6 +263,10 @@ class UICrafting(val full: UIInventoryFull?) : UICanvas( oldSelectedItems.clear() oldSelectedItems.addAll(selectedItems) + if (recipe == null) { + playerThings.itemList.clearForceHighlightList() + } + refreshCraftButtonStatus() } } @@ -248,7 +278,7 @@ class UICrafting(val full: UIInventoryFull?) : UICanvas( itemListIngredients.numberMultiplier = it.toLong() itemListIngredients.rebuild(FILTER_CAT_ALL) itemListCraftable.numberMultiplier = it.toLong() - itemListCraftable.rebuild(FILTER_CAT_ALL) + itemListCraftable.rebuild() refreshCraftButtonStatus() } @@ -362,7 +392,7 @@ class UICrafting(val full: UIInventoryFull?) : UICanvas( filterPlayerListUsing(recipeClicked) highlightCraftingCandidateButton(null) ingredients.clear() - playerThings.removeFromForceHighlightList(oldSelectedItems) + playerThings.itemList.clearForceHighlightList() itemListIngredients.rebuild(FILTER_CAT_ALL) // reset scroll @@ -399,7 +429,7 @@ class UICrafting(val full: UIInventoryFull?) : UICanvas( private fun itemListUpdate() { // let itemlists be sorted - itemListCraftable.rebuild(FILTER_CAT_ALL) + itemListCraftable.rebuild() playerThings.rebuild(FILTER_CAT_ALL) encumbrancePerc = getPlayerInventory().let { it.capacity.toFloat() / it.maxCapacity diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UIItemCraftingCandidateGrid.kt b/src/net/torvald/terrarum/modulebasegame/ui/UIItemCraftingCandidateGrid.kt index 8df1b6063..14220a574 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UIItemCraftingCandidateGrid.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UIItemCraftingCandidateGrid.kt @@ -9,6 +9,7 @@ import net.torvald.terrarum.gameitems.ItemID import net.torvald.terrarum.itemproperties.CraftingCodex import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory import net.torvald.terrarum.modulebasegame.gameactors.InventoryPair +import net.torvald.terrarum.ui.UIItemCatBar.Companion.CAT_ALL /** * Created by minjaesong on 2022-06-28. @@ -95,34 +96,42 @@ class UIItemCraftingCandidateGrid( highlightRecipe(highlightedRecipe) } - private var currentFilter1 = arrayOf("") + private var currentFilter0 = arrayOf(CAT_ALL) + private var currentFilter1 = CAT_ALL + + fun rebuild() = rebuild(currentFilter0) override fun rebuild(filter: Array) { // printdbg(this, "Rebuilding crafting candidate with following filters: ${filter.joinToString()}") - currentFilter1 = filter + currentFilter1 = filter.first() + currentFilter0 = arrayOf(currentFilter1) // filtering policy: if the player have all the ingredient item (regardless of the amount!), make the recipe visible craftingRecipes.clear() - CraftingRecipeCodex.props.forEach { (_, recipes) -> - recipes.forEach { + + + + if (currentFilter1 == CAT_ALL) + CraftingRecipeCodex.props.forEach { (_, recipes) -> + recipes.forEach { + if (isCraftable((parentUI as UICrafting).getPlayerInventory(), it, (parentUI as UICrafting).nearbyCraftingStations)) { + craftingRecipes.add(it) + } + } + } + else + CraftingRecipeCodex.getCraftableRecipesUsingTheseItems(currentFilter1).forEach { if (isCraftable((parentUI as UICrafting).getPlayerInventory(), it, (parentUI as UICrafting).nearbyCraftingStations)) { craftingRecipes.add(it) } - else { -// printdbg(this, " Skipping $recipes: insufficient ingredients") - } } - } + + recipesSortList.clear() // kinda like the output list craftingRecipes.forEach { - if ( - filter.contains((ItemCodex[it.product]?.inventoryCategory ?: throw IllegalArgumentException("Unknown item: ${it.product}"))) || - filter[0] == UIItemCatBar.CAT_ALL - ) { - recipesSortList.add(it) - } + recipesSortList.add(it) } // map sortList to item list @@ -155,11 +164,11 @@ class UIItemCraftingCandidateGrid( } override fun rebuild(filterFun: (InventoryPair) -> Boolean) { - rebuild(currentFilter1) + rebuild(currentFilter0) } override fun rebuild(filterFun: (InventoryPair) -> Boolean, itemAppendix: ItemID) { - rebuild(currentFilter1) + rebuild(currentFilter0) } override fun scrolled(amountX: Float, amountY: Float): Boolean { diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UITemplateHalfInventory.kt b/src/net/torvald/terrarum/modulebasegame/ui/UITemplateHalfInventory.kt index cc9b123f3..8cba6b301 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UITemplateHalfInventory.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UITemplateHalfInventory.kt @@ -82,10 +82,6 @@ class UITemplateHalfInventory( itemList.rebuild(predicate, appendix) } - fun removeFromForceHighlightList(items: List) { - itemList.removeFromForceHighlightList(items) - } - fun setGetInventoryFun(getter: () -> ActorInventory) { itemList.getInventory = getter }