Add the equipment alteration feature to the AlteredCharacterSheet

This commit is contained in:
Thomas Andres Gomez 2025-05-07 19:38:44 +02:00
parent 8d7b63ab96
commit 2c04559bb7
4 changed files with 56 additions and 12 deletions

View file

@ -2,6 +2,8 @@ package com.pixelized.desktop.lwa.repository.alteration
import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
import com.pixelized.desktop.lwa.repository.inventory.InventoryRepository
import com.pixelized.desktop.lwa.repository.item.ItemRepository
import com.pixelized.shared.lwa.model.alteration.Alteration import com.pixelized.shared.lwa.model.alteration.Alteration
import com.pixelized.shared.lwa.model.alteration.FieldAlteration import com.pixelized.shared.lwa.model.alteration.FieldAlteration
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet
@ -19,6 +21,8 @@ import kotlinx.coroutines.flow.stateIn
class AlterationRepository( class AlterationRepository(
private val alterationStore: AlterationStore, private val alterationStore: AlterationStore,
private val inventoryRepository: InventoryRepository,
private val itemRepository: ItemRepository,
campaignRepository: CampaignRepository, campaignRepository: CampaignRepository,
characterRepository: CharacterSheetRepository, characterRepository: CharacterSheetRepository,
) { ) {
@ -28,17 +32,17 @@ class AlterationRepository(
/** /**
* This flow transform the campaign instance (player + npc) into a * This flow transform the campaign instance (player + npc) into a
* Map<CharacterSheetId, List<AlterationId>>. * Map<CharacterSheetId, List<AlterationId>> from the CharacterSheet Alteration
* It is used by an other flow to build the FieldAlteration cache. * It is used by an other flow to build the FieldAlteration cache.
*/ */
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
private val campaignCharactersFlow: Flow<Map<String, List<String>>> = private val campaignCharacterAlterationFlow: Flow<Map<String, List<String>>> =
campaignRepository.campaignFlow() campaignRepository.campaignFlow()
.flatMapLatest { campaign -> .flatMapLatest { campaign ->
val flows = campaign.instances.map { val characters = campaign.instances.map {
characterRepository.characterDetailFlow(characterSheetId = it) characterRepository.characterDetailFlow(characterSheetId = it)
} }
combine(flows) { sheets: Array<CharacterSheet?> -> combine(characters) { sheets: Array<CharacterSheet?> ->
sheets sheets
.asSequence() .asSequence()
.filterNotNull() .filterNotNull()
@ -46,17 +50,46 @@ class AlterationRepository(
} }
} }
/**
* This flow transform the campaign instance (player + npc) into a
* Map<CharacterSheetId, List<AlterationId>> from the character inventory items Alteration
* It is used by an other flow to build the FieldAlteration cache.
*/
@OptIn(ExperimentalCoroutinesApi::class)
private val campaignCharacterInventoryAlterationFlow: Flow<Map<String, List<String>>> =
campaignRepository.campaignFlow()
.flatMapLatest { campaign ->
val equippedItems = campaign.instances.map { characterSheetId ->
combine(
inventoryRepository.equippedItemsFlow(characterSheetId = characterSheetId),
itemRepository.itemFlow(),
) { equipments, items ->
characterSheetId to equipments.flatMap { equipment ->
items[equipment.itemId]?.alterations ?: emptyList()
}
}
}
combine(equippedItems) { equipments: Array<Pair<String, List<String>>> ->
equipments
.asSequence()
.associate { it.first to it.second }
}
}
private val activeAlterationMapFlow: StateFlow<Map<String, Map<String, List<FieldAlteration>>>> = private val activeAlterationMapFlow: StateFlow<Map<String, Map<String, List<FieldAlteration>>>> =
combine( combine(
alterationStore.alterationsFlow, alterationStore.alterationsFlow,
campaignCharactersFlow, campaignCharacterAlterationFlow,
) { alterations, characters -> campaignCharacterInventoryAlterationFlow,
characters.map { (characterSheetId, alterationIds) -> ) { alterations, characters, inventories ->
characterSheetId to transformToAlterationFieldMap( val characterSheetIds = characters.keys + inventories.keys
characterSheetIds.associateWith {
transformToAlterationFieldMap(
alterations = alterations, alterations = alterations,
actives = alterationIds, actives = characters.getOrElse(it) { emptyList() } +
inventories.getOrElse(it) { emptyList() }
) )
}.toMap() }
}.stateIn( }.stateIn(
scope = scope, scope = scope,
started = SharingStarted.Eagerly, started = SharingStarted.Eagerly,
@ -96,7 +129,7 @@ class AlterationRepository(
) )
} }
@kotlin.jvm.Throws @Throws
suspend fun deleteAlteration( suspend fun deleteAlteration(
alterationId: String, alterationId: String,
) { ) {

View file

@ -3,6 +3,7 @@ package com.pixelized.desktop.lwa.repository.inventory
import com.pixelized.shared.lwa.model.inventory.Inventory import com.pixelized.shared.lwa.model.inventory.Inventory
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
class InventoryRepository( class InventoryRepository(
@ -30,6 +31,14 @@ class InventoryRepository(
.map { it[characterSheetId] ?: Inventory.empty(characterSheetId) } .map { it[characterSheetId] ?: Inventory.empty(characterSheetId) }
} }
fun equippedItemsFlow(
characterSheetId: String,
): Flow<List<Inventory.Item>> {
return inventoryStore.inventories
.map { it[characterSheetId] ?: Inventory.empty(characterSheetId) }
.map { inventory -> inventory.items.filter { item -> item.equipped } }
}
@Throws @Throws
suspend fun updateInventory( suspend fun updateInventory(
inventory: Inventory, inventory: Inventory,

View file

@ -199,7 +199,7 @@ fun InventoryItem(
.size(size = 64) .size(size = 64)
.build(), .build(),
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
filterQuality = FilterQuality.Low, filterQuality = FilterQuality.Medium,
contentDescription = null, contentDescription = null,
) )
if (item.consumable) { if (item.consumable) {

View file

@ -21,6 +21,8 @@ import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.Characterist
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.REFLEX import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.REFLEX
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.STR import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.STR
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.THUMBNAIL import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.THUMBNAIL
import com.pixelized.shared.lwa.model.inventory.Inventory
import com.pixelized.shared.lwa.model.inventory.Inventory.Item
import com.pixelized.shared.lwa.parser.expression.Expression import com.pixelized.shared.lwa.parser.expression.Expression
import com.pixelized.shared.lwa.usecase.CharacterSheetUseCase import com.pixelized.shared.lwa.usecase.CharacterSheetUseCase
import com.pixelized.shared.lwa.usecase.ExpressionUseCase import com.pixelized.shared.lwa.usecase.ExpressionUseCase