diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml
index b44213f..d634db1 100644
--- a/composeApp/src/commonMain/composeResources/values/strings.xml
+++ b/composeApp/src/commonMain/composeResources/values/strings.xml
@@ -184,8 +184,9 @@
Supprimer la feuille de personnage
Êtes-vous sûr de vouloir supprimer "%1$s" ?
- Ajouter un objet
Filtrer l'inventaire
+ Ajouter un objet
+ Utiliser
Ajouter à la bourse
Retirer de la bourse
Filtrer les objets
@@ -193,6 +194,9 @@
Ajouter à l'inventaire
Quantité
Modifier
+ Jetter
+ Equiper
+ Utiliser
Cet objet n'a pas de description.
Les caractéristiques constituent les aptitudes innées d’un personnage comme son intelligence, sa force, son charisme, etc. Elles ne sont pas acquises, mais peuvent être parfois augmentées par un entraînement ou une utilisation réussie. Les caractéristiques des humains normaux varient de 2 (niveau extrêmement bas) à 20 (maximum du potentiel humain), avec une moyenne de 10 ou 11. Plus une caractéristique est élevée plus le personnage est puissant dans cette aptitude.\nÀ la création de votre personnage, répartissez les valeurs suivantes dans les différentes caractéristiques : 15, 15, 13, 11, 10, 9 et 7.
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClient.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClient.kt
index 254ddf2..dff8ec1 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClient.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClient.kt
@@ -115,13 +115,35 @@ interface LwaClient {
create: Boolean,
): APIResponse
+ suspend fun deleteInventory(
+ characterSheetId: String,
+ ): APIResponse
+
suspend fun createInventoryItem(
characterSheetId: String,
itemId: String,
): APIResponse
- suspend fun deleteInventory(
+ suspend fun changeInventoryItemCount(
characterSheetId: String,
+ inventoryId: String,
+ count: Float,
+ ): APIResponse
+
+ suspend fun equipInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
+ equip: Boolean,
+ ): APIResponse
+
+ suspend fun consumeInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
+ ): APIResponse
+
+ suspend fun deleteInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
): APIResponse
// Tags
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClientImpl.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClientImpl.kt
index 48af180..032edbc 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClientImpl.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClientImpl.kt
@@ -192,18 +192,52 @@ class LwaClientImpl(
}
.body>()
+ @Throws
+ override suspend fun deleteInventory(characterSheetId: String): APIResponse = client
+ .delete("$root/inventory/delete?characterSheetId=$characterSheetId")
+ .body()
+
@Throws
override suspend fun createInventoryItem(
characterSheetId: String,
itemId: String,
): APIResponse = client
- .put("$root/inventory/create?characterSheetId=$characterSheetId&itemId=$itemId")
+ .put("$root/inventory/item/create?characterSheetId=$characterSheetId&itemId=$itemId")
.body>()
@Throws
- override suspend fun deleteInventory(characterSheetId: String): APIResponse = client
- .delete("$root/inventory/delete?characterSheetId=$characterSheetId")
- .body()
+ override suspend fun changeInventoryItemCount(
+ characterSheetId: String,
+ inventoryId: String,
+ count: Float,
+ ): APIResponse = client
+ .put("$root/inventory/item/count?characterSheetId=$characterSheetId&inventoryId=$inventoryId&count=$count")
+ .body>()
+
+ @Throws
+ override suspend fun equipInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
+ equip: Boolean,
+ ): APIResponse = client
+ .put("$root/inventory/item/equip?characterSheetId=$characterSheetId&inventoryId=$inventoryId&equip=$equip")
+ .body>()
+
+ @Throws
+ override suspend fun consumeInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
+ ): APIResponse = client
+ .put("$root/inventory/item/consume?characterSheetId=$characterSheetId&inventoryId=$inventoryId")
+ .body>()
+
+ @Throws
+ override suspend fun deleteInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
+ ): APIResponse = client
+ .delete("$root/inventory/item/delete?characterSheetId=$characterSheetId&inventoryId=$inventoryId")
+ .body>()
@Throws
override suspend fun getAlterationTags(): APIResponse> = client
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/inventory/InventoryRepository.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/inventory/InventoryRepository.kt
index 277d3d1..665c9cf 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/inventory/InventoryRepository.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/inventory/InventoryRepository.kt
@@ -53,11 +53,52 @@ class InventoryRepository(
}
@Throws
- suspend fun deleteItem(
+ suspend fun changeInventoryItemCount(
characterSheetId: String,
+ inventoryId: String,
+ count: Float,
) {
- inventoryStore.deleteInventory(
+ inventoryStore.changeInventoryItemCount(
characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ count = count,
+ )
+ }
+
+ @Throws
+ suspend fun consumeInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
+ ) {
+ inventoryStore.consumeInventoryItem(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ )
+ }
+
+ @Throws
+ suspend fun equipInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
+ ) {
+ val inventory = inventory(characterSheetId = characterSheetId)
+ val inventoryItem = inventory.items.firstOrNull { it.inventoryId == inventoryId }
+
+ inventoryStore.equipInventoryItem(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ equip = inventoryItem?.equipped?.not() ?: true,
+ )
+ }
+
+ @Throws
+ suspend fun deleteInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
+ ) {
+ inventoryStore.deleteInventoryItem(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
)
}
}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/inventory/InventoryStore.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/inventory/InventoryStore.kt
index 5a86be5..2d5dc2f 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/inventory/InventoryStore.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/inventory/InventoryStore.kt
@@ -73,6 +73,16 @@ class InventoryStore(
}
}
+ @Throws
+ suspend fun deleteInventory(
+ characterSheetId: String,
+ ) {
+ val request = client.deleteInventory(characterSheetId = characterSheetId)
+ if (request.success.not()) {
+ LwaClient.error(error = request)
+ }
+ }
+
@Throws
suspend fun createInventoryItem(
characterSheetId: String,
@@ -89,10 +99,60 @@ class InventoryStore(
}
@Throws
- suspend fun deleteInventory(
+ suspend fun changeInventoryItemCount(
characterSheetId: String,
+ inventoryId: String,
+ count: Float,
) {
- val request = client.deleteInventory(characterSheetId = characterSheetId)
+ val request = client.changeInventoryItemCount(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ count = count,
+ )
+ if (request.success.not()) {
+ LwaClient.error(error = request)
+ }
+ }
+
+ @Throws
+ suspend fun consumeInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
+ ) {
+ val request = client.consumeInventoryItem(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ )
+ if (request.success.not()) {
+ LwaClient.error(error = request)
+ }
+ }
+
+ @Throws
+ suspend fun equipInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
+ equip: Boolean,
+ ) {
+ val request = client.equipInventoryItem(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ equip = equip,
+ )
+ if (request.success.not()) {
+ LwaClient.error(error = request)
+ }
+ }
+
+ @Throws
+ suspend fun deleteInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
+ ) {
+ val request = client.deleteInventoryItem(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ )
if (request.success.not()) {
LwaClient.error(error = request)
}
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/item/ItemDetailDialog.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/item/ItemDetailDialog.kt
index 5cf0f31..fb369bd 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/item/ItemDetailDialog.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/item/ItemDetailDialog.kt
@@ -1,6 +1,9 @@
package com.pixelized.desktop.lwa.ui.composable.character.item
import androidx.compose.animation.AnimatedContent
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.animation.togetherWith
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -42,7 +45,10 @@ import com.pixelized.desktop.lwa.ui.theme.lwa
import com.pixelized.desktop.lwa.utils.rememberSaturationFilter
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.character__inventory__inventory__dialog__action
+import lwacharactersheet.composeapp.generated.resources.character__inventory__inventory__dialog__consume_action
import lwacharactersheet.composeapp.generated.resources.character__inventory__inventory__dialog__count_action
+import lwacharactersheet.composeapp.generated.resources.character__inventory__inventory__dialog__equip_action
+import lwacharactersheet.composeapp.generated.resources.character__inventory__inventory__dialog__throw_action
import lwacharactersheet.composeapp.generated.resources.ic_close_24dp
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
@@ -59,12 +65,14 @@ data class ItemDetailDialogUio(
val count: Float,
// options
val countable: LwaTextFieldUio?,
+ val consumable: Boolean,
+ val equipable: Boolean,
)
@Stable
object ItemDetailDialogDefault {
@Stable
- val paddings = PaddingValues(all = 16.dp)
+ val paddings = PaddingValues(top = 16.dp, start = 16.dp, end = 16.dp, bottom = 8.dp)
@Stable
val spacings = 8.dp
@@ -78,6 +86,9 @@ fun ItemDetailDialog(
onDismissRequest: () -> Unit,
onConfirm: (ItemDetailDialogUio) -> Unit,
onAddItem: (ItemDetailDialogUio) -> Unit,
+ onEquip: (ItemDetailDialogUio) -> Unit,
+ onConsume: (ItemDetailDialogUio) -> Unit,
+ onThrow: (ItemDetailDialogUio) -> Unit,
) {
LwaDialog(
state = dialog,
@@ -85,7 +96,8 @@ fun ItemDetailDialog(
onConfirm = { dialog.value?.let(onConfirm) ?: onDismissRequest },
) { state ->
val layoutDirection = LocalLayoutDirection.current
- val end = remember(layoutDirection, paddings) { paddings.calculateEndPadding(layoutDirection) }
+ val end =
+ remember(layoutDirection, paddings) { paddings.calculateEndPadding(layoutDirection) }
val top = remember(paddings) { paddings.calculateTopPadding() }
takeIf { state.image?.isNotEmpty() == true }?.let {
@@ -140,6 +152,7 @@ fun ItemDetailDialog(
AnimatedContent(
targetState = state.inventoryId,
+ transitionSpec = { fadeIn() togetherWith fadeOut() },
) {
when (it) {
null -> Row(
@@ -158,14 +171,12 @@ fun ItemDetailDialog(
else -> Column(
verticalArrangement = Arrangement.spacedBy(space = spacings)
) {
- if (state.countable != null) {
- Row(
- modifier = Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.spacedBy(
- space = spacings,
- Alignment.End,
- )
- ) {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.spacedBy(space = spacings),
+ verticalAlignment = Alignment.Bottom,
+ ) {
+ if (state.countable != null) {
LwaTextField(
modifier = Modifier.width(width = 128.dp),
colors = LwaTextFieldColors(
@@ -188,6 +199,34 @@ fun ItemDetailDialog(
)
}
}
+ Spacer(
+ modifier = Modifier.weight(weight = 1f),
+ )
+ TextButton(
+ onClick = { onThrow(state) },
+ ) {
+ Text(
+ text = stringResource(Res.string.character__inventory__inventory__dialog__throw_action),
+ )
+ }
+ if (state.equipable) {
+ TextButton(
+ onClick = { onEquip(state) },
+ ) {
+ Text(
+ text = stringResource(Res.string.character__inventory__inventory__dialog__equip_action),
+ )
+ }
+ }
+ if (state.consumable) {
+ TextButton(
+ onClick = { onConsume(state) },
+ ) {
+ Text(
+ text = stringResource(Res.string.character__inventory__inventory__dialog__consume_action),
+ )
+ }
+ }
}
}
}
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/item/ItemDetailDialogFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/item/ItemDetailDialogFactory.kt
index f0382f1..efde7eb 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/item/ItemDetailDialogFactory.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/item/ItemDetailDialogFactory.kt
@@ -37,6 +37,8 @@ class ItemDetailDialogFactory {
countable = takeIf { item.options.stackable }
?.let { createFieldFlow(value = format.format(count)) }
?.createTextField(label = getString(Res.string.character__inventory__inventory__dialog__count)),
+ consumable = item.options.consumable,
+ equipable = item.options.equipable,
)
}
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/item/ItemDetailDialogViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/item/ItemDetailDialogViewModel.kt
index dc2ab62..a9fae35 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/item/ItemDetailDialogViewModel.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/item/ItemDetailDialogViewModel.kt
@@ -83,49 +83,99 @@ class ItemDetailDialogViewModel(
suspend fun onAddInventoryItem(
characterSheetId: String,
itemId: String,
- ) {
+ ) : Boolean {
try {
// create the inventory item on the server, get the newly create id from that.
val inventoryId = inventoryRepository.createInventoryItem(
characterSheetId = characterSheetId,
itemId = itemId,
)
+ return true
// update the dialog with the id only if this dialog still correspond to this item. (should always be the case but hey).
- if (selectedItemId.value?.let { it.itemId == itemId && it.characterSheetId == characterSheetId } == true) {
- selectedItemId.update {
- it?.copy(inventoryId = inventoryId)
- }
- }
+// if (selectedItemId.value?.let { it.itemId == itemId && it.characterSheetId == characterSheetId } == true) {
+// selectedItemId.update {
+// it?.copy(inventoryId = inventoryId)
+// }
+// }
} catch (exception: Exception) {
val message = ErrorSnackUio.from(exception)
_error.emit(message)
+ return false
+ }
+ }
+
+ suspend fun throwInventoryItem(
+ characterSheetId: String,
+ inventoryId: String?,
+ ): Boolean {
+ if (inventoryId == null) return false
+ try {
+ inventoryRepository.deleteInventoryItem(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ )
+ return true
+ } catch (exception: Exception) {
+ val message = ErrorSnackUio.from(exception)
+ _error.emit(message)
+ return false
+ }
+ }
+
+ suspend fun consumeInventoryItem(
+ characterSheetId: String,
+ inventoryId: String?,
+ ): Boolean {
+ if (inventoryId == null) return false
+ try {
+ inventoryRepository.consumeInventoryItem(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ )
+ return true
+ } catch (exception: Exception) {
+ val message = ErrorSnackUio.from(exception)
+ _error.emit(message)
+ return false
+ }
+ }
+
+ suspend fun equipInventoryItem(
+ characterSheetId: String,
+ inventoryId: String?,
+ ) : Boolean {
+ if (inventoryId == null) return false
+ try {
+ inventoryRepository.equipInventoryItem(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ )
+ return true
+ } catch (exception: Exception) {
+ val message = ErrorSnackUio.from(exception)
+ _error.emit(message)
+ return false
}
}
suspend fun changeInventoryItemQuantity(
- dialog: ItemDetailDialogUio
- ) : Boolean {
+ dialog: ItemDetailDialogUio,
+ ): Boolean {
if (dialog.countable?.isError?.value == true) return false
val characterSheetId = dialog.characterSheetId
val inventoryId = dialog.inventoryId ?: return false
val quantity = dialog.countable?.valueFlow?.value ?: return false
- val count = factory.parse(quantity = quantity) ?: return false
-
- val inventory = inventoryRepository.inventory(characterSheetId = characterSheetId)
+ val count = factory.parse(quantity = quantity)
+ ?: quantity.toFloatOrNull()
+ ?: return false
try {
- inventoryRepository.updateInventory(
- inventory = inventory.copy(
- items = inventory.items.toMutableList().also { items ->
- val index = items.indexOfFirst { item -> item.inventoryId == inventoryId }
- items[index] = items[index].copy(
- count = count,
- )
- }
- ),
- create = false,
+ inventoryRepository.changeInventoryItemCount(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ count = count
)
return true
} catch (exception: Exception) {
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/CharacterDetailInventory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/CharacterDetailInventory.kt
index a6e28fa..c2bc1e1 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/CharacterDetailInventory.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/CharacterDetailInventory.kt
@@ -29,7 +29,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
-import coil3.compose.rememberDrawScopeSizeResolver
import com.pixelized.desktop.lwa.LocalBlurController
import com.pixelized.desktop.lwa.ui.composable.character.inventory.InventoryDialog
import com.pixelized.desktop.lwa.ui.composable.character.inventory.InventoryDialogViewModel
@@ -118,6 +117,14 @@ fun CharacterDetailInventory(
inventoryDialogViewModel.showInventoryDialog(
characterSheetId = it,
)
+ },
+ onConsume = {
+ scope.launch {
+ itemDetailDialogViewModel.consumeInventoryItem(
+ characterSheetId = it.characterSheetId,
+ inventoryId = it.inventoryId,
+ )
+ }
}
)
}
@@ -165,10 +172,14 @@ fun CharacterDetailInventory(
},
onAddItem = { dialog ->
scope.launch {
- itemDetailDialogViewModel.onAddInventoryItem(
+ val result = itemDetailDialogViewModel.onAddInventoryItem(
characterSheetId = dialog.characterSheetId,
itemId = dialog.itemId,
)
+ if (result) {
+ blur.hide()
+ itemDetailDialogViewModel.hideItemDialog()
+ }
}
},
onConfirm = { dialog ->
@@ -181,12 +192,51 @@ fun CharacterDetailInventory(
itemDetailDialogViewModel.hideItemDialog()
}
}
+ },
+ onEquip = { dialog ->
+ scope.launch {
+ val result = itemDetailDialogViewModel.equipInventoryItem(
+ characterSheetId = dialog.characterSheetId,
+ inventoryId = dialog.inventoryId,
+ )
+ if (result) {
+ blur.hide()
+ itemDetailDialogViewModel.hideItemDialog()
+ }
+ }
+ },
+ onConsume = { dialog ->
+ scope.launch {
+ val result = itemDetailDialogViewModel.consumeInventoryItem(
+ characterSheetId = dialog.characterSheetId,
+ inventoryId = dialog.inventoryId,
+ )
+ if (result) {
+ blur.hide()
+ itemDetailDialogViewModel.hideItemDialog()
+ }
+ }
+ },
+ onThrow = { dialog ->
+ scope.launch {
+ val result = itemDetailDialogViewModel.throwInventoryItem(
+ characterSheetId = dialog.characterSheetId,
+ inventoryId = dialog.inventoryId,
+ )
+ if (result) {
+ blur.hide()
+ itemDetailDialogViewModel.hideItemDialog()
+ }
+ }
}
)
ErrorSnackHandler(
error = purseViewModel.error,
)
+ ErrorSnackHandler(
+ error = itemDetailDialogViewModel.error,
+ )
}
@Composable
@@ -197,6 +247,7 @@ private fun CharacterDetailInventoryContent(
inventory: CharacterDetailInventoryUio,
onPurse: (String) -> Unit,
onItem: (InventoryItemUio) -> Unit,
+ onConsume: (InventoryItemUio) -> Unit,
onAddItem: (String) -> Unit,
) {
Box(
@@ -257,6 +308,7 @@ private fun CharacterDetailInventoryContent(
modifier = Modifier.animateItem(),
item = it,
onClick = { onItem(it) },
+ onConsume = { onConsume(it) },
)
}
}
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/CharacterDetailInventoryFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/CharacterDetailInventoryFactory.kt
index dff60d6..52c0663 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/CharacterDetailInventoryFactory.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/CharacterDetailInventoryFactory.kt
@@ -86,6 +86,7 @@ class CharacterDetailInventoryFactory(
label = item.metadata.label,
count = it.count,
equipped = it.equipped,
+ consumable = item.options.consumable,
tooltips = takeIf { item.metadata.description.isNotEmpty() }?.let {
InventoryItemUio.Tooltips(
label = item.metadata.label,
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/item/InventoryItem.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/item/InventoryItem.kt
index 828302a..e9c54d2 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/item/InventoryItem.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/item/InventoryItem.kt
@@ -19,6 +19,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
+import androidx.compose.material.TextButton
import androidx.compose.material.minimumInteractiveComponentSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
@@ -38,6 +39,9 @@ import com.pixelized.desktop.lwa.ui.composable.tooltip.TooltipLayout2
import com.pixelized.desktop.lwa.ui.theme.lwa
import com.pixelized.desktop.lwa.utils.extention.ribbon
import com.pixelized.desktop.lwa.utils.rememberSaturationFilter
+import lwacharactersheet.composeapp.generated.resources.Res
+import lwacharactersheet.composeapp.generated.resources.character__inventory__use__action
+import org.jetbrains.compose.resources.stringResource
@Stable
data class InventoryItemUio(
@@ -47,6 +51,7 @@ data class InventoryItemUio(
val label: String,
val count: Float,
val equipped: Boolean,
+ val consumable: Boolean,
val tooltips: Tooltips?,
) {
@Stable
@@ -60,7 +65,7 @@ data class InventoryItemUio(
@Stable
object GMCharacterPreviewDefault {
@Stable
- val paddings = PaddingValues(horizontal = 16.dp, vertical = 4.dp)
+ val paddings = PaddingValues(horizontal = 16.dp)
@Stable
val spacing: Dp = 4.dp
@@ -74,6 +79,7 @@ fun InventoryItem(
spacing: Dp = GMCharacterPreviewDefault.spacing,
item: InventoryItemUio,
onClick: () -> Unit,
+ onConsume: () -> Unit,
) {
TooltipLayout2(
modifier = modifier,
@@ -134,30 +140,41 @@ fun InventoryItem(
.fillMaxWidth()
.padding(paddingValues = padding)
.then(other = modifier),
- horizontalArrangement = Arrangement.spacedBy(space = spacing),
+ horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
- Text(
- modifier = Modifier.alignByBaseline(),
- style = MaterialTheme.lwa.typography.base.body1,
- fontWeight = FontWeight.Bold,
- overflow = TextOverflow.Ellipsis,
- maxLines = 1,
- text = item.label,
- )
- AnimatedContent(
- modifier = Modifier.alignByBaseline(),
- targetState = item.count,
- transitionSpec = { fadeIn() togetherWith fadeOut() },
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(space = spacing),
) {
- when (it) {
- 0f, 1f -> Unit
- else -> Text(
- style = MaterialTheme.lwa.typography.base.caption,
- overflow = TextOverflow.Ellipsis,
- maxLines = 1,
- text = "x${it}",
- )
+ Text(
+ modifier = Modifier.alignByBaseline(),
+ style = MaterialTheme.lwa.typography.base.body1,
+ fontWeight = FontWeight.Bold,
+ overflow = TextOverflow.Ellipsis,
+ maxLines = 1,
+ text = item.label,
+ )
+ AnimatedContent(
+ modifier = Modifier.alignByBaseline(),
+ targetState = item.count,
+ transitionSpec = { fadeIn() togetherWith fadeOut() },
+ ) {
+ when (it) {
+ 0f, 1f -> Unit
+ else -> Text(
+ style = MaterialTheme.lwa.typography.base.caption,
+ overflow = TextOverflow.Ellipsis,
+ maxLines = 1,
+ text = "x${it}",
+ )
+ }
+ }
+ }
+ if (item.consumable) {
+ TextButton(
+ onClick = onConsume,
+ ) {
+ Text(text = stringResource(Res.string.character__inventory__use__action))
}
}
}
diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/model/inventory/InventoryService.kt b/server/src/main/kotlin/com/pixelized/server/lwa/model/inventory/InventoryService.kt
index 789bf8b..7ebb404 100644
--- a/server/src/main/kotlin/com/pixelized/server/lwa/model/inventory/InventoryService.kt
+++ b/server/src/main/kotlin/com/pixelized/server/lwa/model/inventory/InventoryService.kt
@@ -1,5 +1,7 @@
package com.pixelized.server.lwa.model.inventory
+import com.pixelized.server.lwa.model.item.ItemStore
+import com.pixelized.server.lwa.server.exception.BusinessException
import com.pixelized.shared.lwa.model.inventory.Inventory
import com.pixelized.shared.lwa.model.inventory.InventoryJson
import com.pixelized.shared.lwa.model.inventory.factory.InventoryJsonFactory
@@ -9,9 +11,11 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
+import java.util.UUID
class InventoryService(
private val inventoryStore: InventoryStore,
+ private val itemStore: ItemStore,
private val factory: InventoryJsonFactory,
) {
private val scope = CoroutineScope(Dispatchers.IO + Job())
@@ -51,13 +55,185 @@ class InventoryService(
}
@Throws
- fun createItem(
+ fun createInventoryItem(
characterSheetId: String,
itemId: String,
- ) : String {
- return inventoryStore.createItem(
- characterSheetId = characterSheetId,
+ ): String {
+ // get the inventory of the character, if none create one.
+ val inventory = inventoryStore.inventoryFlow().value[characterSheetId]
+ ?: Inventory.empty(characterSheetId = characterSheetId)
+ // create an inventoryId.
+ val inventoryId = inventory.items.createInventoryId()
+ // create an inventory Item.
+ val item = Inventory.Item(
+ inventoryId = inventoryId,
itemId = itemId,
+ count = 1f,
+ equipped = false,
+ )
+ // update the inventory with the updated item.
+ val updatedInventory = inventory.copy(
+ items = inventory.items.toMutableList().also {
+ it.add(item)
+ }
+ )
+ // save the inventory
+ inventoryStore.save(
+ inventory = updatedInventory,
+ create = false,
+ )
+ return inventoryId
+ }
+
+ @Throws
+ fun changeInventoryItemCount(
+ characterSheetId: String,
+ inventoryId: String,
+ count: Float,
+ ) {
+ if (count < 0) {
+ throw BusinessException(
+ message = "InventoryItem (id:$inventoryId) quantity cannot go below 0.",
+ )
+ }
+ // get the inventory of the character, if none create one.
+ val inventory = inventoryStore.inventoryFlow().value[characterSheetId]
+ ?: Inventory.empty(characterSheetId = characterSheetId)
+ // Guard case.
+ val inventoryItemIndex = inventory.items.indexOfFirst { it.inventoryId == inventoryId }
+ if (inventoryItemIndex < 0) {
+ throw BusinessException(
+ message = "InventoryItem (id:$inventoryId) not found in Inventory(characterSheetId:$characterSheetId).",
+ )
+ }
+ // update the inventory with the updated item.
+ val updatedInventory = inventory.copy(
+ items = inventory.items.toMutableList().also { items ->
+ if (count == 0f) {
+ items.removeAt(inventoryItemIndex)
+ } else {
+ items[inventoryItemIndex] = items[inventoryItemIndex].copy(count = count)
+ }
+ }
+ )
+ // save the inventory
+ inventoryStore.save(
+ inventory = updatedInventory,
+ create = false,
)
}
+
+ @Throws
+ fun consumeInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
+ ) {
+ // get the inventory of the character, if none create one.
+ val inventory = inventoryStore.inventoryFlow().value[characterSheetId]
+ ?: Inventory.empty(characterSheetId = characterSheetId)
+ // Guard case.
+ val inventoryItemIndex = inventory.items.indexOfFirst { it.inventoryId == inventoryId }
+ if (inventoryItemIndex < 0) {
+ throw BusinessException(
+ message = "InventoryItem (id:$inventoryId) not found in Inventory(characterSheetId:$characterSheetId).",
+ )
+ }
+ // other Guard case.
+ val itemId = inventory.items[inventoryItemIndex].itemId
+ val item = itemStore.item(itemId = itemId)
+ ?: throw BusinessException(message = "Item (id:$itemId) not found.")
+ if (item.options.consumable.not()) {
+ throw BusinessException(message = "Item (id:$itemId) is not consumable.")
+ }
+ // update the inventory with the updated item.
+ val updatedInventory = inventory.copy(
+ items = inventory.items.toMutableList().also { items ->
+ val inventoryItem = inventory.items[inventoryItemIndex]
+ if (inventoryItem.count - 1f <= 0f) {
+ items.removeAt(inventoryItemIndex)
+ } else {
+ items[inventoryItemIndex] = inventoryItem.copy(count = inventoryItem.count - 1f)
+ }
+ }
+ )
+ // save the inventory
+ inventoryStore.save(
+ inventory = updatedInventory,
+ create = false,
+ )
+ }
+
+ @Throws
+ fun equipInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
+ equip: Boolean,
+ ) {
+ // get the inventory of the character, if none create one.
+ val inventory = inventoryStore.inventoryFlow().value[characterSheetId]
+ ?: Inventory.empty(characterSheetId = characterSheetId)
+ // Guard case.
+ val inventoryItemIndex = inventory.items.indexOfFirst { it.inventoryId == inventoryId }
+ if (inventoryItemIndex < 0) {
+ throw BusinessException(
+ message = "InventoryItem (id:$inventoryId) not found in Inventory(characterSheetId:$characterSheetId).",
+ )
+ }
+ // other Guard case.
+ val itemId = inventory.items[inventoryItemIndex].itemId
+ val item = itemStore.item(itemId = itemId)
+ ?: throw BusinessException(message = "Item (id:$itemId) not found.")
+ if (item.options.equipable.not()) {
+ throw BusinessException(message = "Item (id:$itemId) is not equipable.")
+ }
+ // update the inventory with the updated item.
+ val updatedInventory = inventory.copy(
+ items = inventory.items.toMutableList().also { items ->
+ items[inventoryItemIndex] = inventory.items[inventoryItemIndex].copy(
+ equipped = equip
+ )
+ }
+ )
+ // save the inventory
+ inventoryStore.save(
+ inventory = updatedInventory,
+ create = false,
+ )
+ }
+
+ @Throws
+ fun deleteInventoryItem(
+ characterSheetId: String,
+ inventoryId: String,
+ ) {
+ // get the inventory of the character, if none create one.
+ val inventory = inventoryStore.inventoryFlow().value[characterSheetId]
+ ?: Inventory.empty(characterSheetId = characterSheetId)
+ // Guard case.
+ val inventoryItemIndex = inventory.items.indexOfFirst { it.inventoryId == inventoryId }
+ if (inventoryItemIndex < 0) {
+ throw BusinessException(
+ message = "InventoryItem (id:$inventoryId) not found in Inventory(characterSheetId:$characterSheetId)",
+ )
+ }
+ // update the inventory with the updated item.
+ val updatedInventory = inventory.copy(
+ items = inventory.items.toMutableList().also { items ->
+ items.removeAt(inventoryItemIndex)
+ }
+ )
+ // save the inventory
+ inventoryStore.save(
+ inventory = updatedInventory,
+ create = false,
+ )
+ }
+
+ private fun List.createInventoryId(): String {
+ var inventoryId: String
+ do {
+ inventoryId = UUID.randomUUID().toString()
+ } while (any { inventoryId == it.inventoryId })
+ return inventoryId
+ }
}
diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/model/inventory/InventoryStore.kt b/server/src/main/kotlin/com/pixelized/server/lwa/model/inventory/InventoryStore.kt
index 6378c18..1bb13a5 100644
--- a/server/src/main/kotlin/com/pixelized/server/lwa/model/inventory/InventoryStore.kt
+++ b/server/src/main/kotlin/com/pixelized/server/lwa/model/inventory/InventoryStore.kt
@@ -153,49 +153,7 @@ class InventoryStore(
}
}
- @Throws
- fun createItem(
- characterSheetId: String,
- itemId: String,
- ): String {
- val (updatedInventory, inventoryId) = inventoryFlow.value.toMutableMap().let { characters ->
- // get the inventory of the character, if none create one.
- val inventory = characters[characterSheetId]
- ?: Inventory.empty(characterSheetId = characterSheetId)
- // create an inventoryId.
- val inventoryId = inventory.items.createInventoryId()
- // create an inventory Item.
- val item = Inventory.Item(
- inventoryId = inventoryId,
- itemId = itemId,
- count = 1f,
- equipped = false,
- )
- // update the inventory with the updated item.
- inventory.copy(
- items = inventory.items.toMutableList().also {
- it.add(item)
- }
- ) to inventoryId
- }
- // save the inventory
- save(
- inventory = updatedInventory,
- create = false,
- )
- // return the inventory ID.
- return inventoryId
- }
-
private fun inventoryFile(id: String): File {
return File("${pathProvider.inventoryPath()}${id}.json")
}
-
- private fun List.createInventoryId(): String {
- var inventoryId: String
- do {
- inventoryId = UUID.randomUUID().toString()
- } while (any { inventoryId == it.inventoryId })
- return inventoryId
- }
}
diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/model/item/ItemStore.kt b/server/src/main/kotlin/com/pixelized/server/lwa/model/item/ItemStore.kt
index af04b54..0915684 100644
--- a/server/src/main/kotlin/com/pixelized/server/lwa/model/item/ItemStore.kt
+++ b/server/src/main/kotlin/com/pixelized/server/lwa/model/item/ItemStore.kt
@@ -37,6 +37,10 @@ class ItemStore(
}
}
+ fun item(itemId: String?): Item? {
+ return itemFlow.value.firstOrNull { it.id == itemId }
+ }
+
fun itemsFlow(): StateFlow> = itemFlow
private fun updateItemsFlow() {
diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/Server.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/Server.kt
index 8fb3a98..5582ca7 100644
--- a/server/src/main/kotlin/com/pixelized/server/lwa/server/Server.kt
+++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/Server.kt
@@ -19,8 +19,12 @@ import com.pixelized.server.lwa.server.rest.character.putCharacterAlteration
import com.pixelized.server.lwa.server.rest.character.putCharacterDamage
import com.pixelized.server.lwa.server.rest.character.putCharacterDiminished
import com.pixelized.server.lwa.server.rest.character.putCharacterFatigue
-import com.pixelized.server.lwa.server.rest.inventory.createInventory
+import com.pixelized.server.lwa.server.rest.inventory.changeInventoryItemCount
+import com.pixelized.server.lwa.server.rest.inventory.consumeInventoryItem
+import com.pixelized.server.lwa.server.rest.inventory.createInventoryItem
+import com.pixelized.server.lwa.server.rest.inventory.equipInventoryItem
import com.pixelized.server.lwa.server.rest.inventory.deleteInventory
+import com.pixelized.server.lwa.server.rest.inventory.deleteInventoryItem
import com.pixelized.server.lwa.server.rest.inventory.getInventory
import com.pixelized.server.lwa.server.rest.inventory.putInventory
import com.pixelized.server.lwa.server.rest.item.deleteItem
@@ -218,7 +222,7 @@ class LocalServer {
body = engine.deleteAlteration()
)
}
- route(path = "item") {
+ route(path = "/item") {
get(
path = "/all",
body = engine.getItems(),
@@ -236,7 +240,7 @@ class LocalServer {
body = engine.deleteItem(),
)
}
- route(path = "tag") {
+ route(path = "/tag") {
get(
path = "/character",
body = engine.getCharacterTags(),
@@ -250,7 +254,7 @@ class LocalServer {
body = engine.getItemTags(),
)
}
- route(path = "inventory") {
+ route(path = "/inventory") {
get(
path = "/detail",
body = engine.getInventory(),
@@ -259,14 +263,34 @@ class LocalServer {
path = "/update",
body = engine.putInventory()
)
- put(
- path = "/create",
- body = engine.createInventory()
- )
delete(
path = "/delete",
body = engine.deleteInventory()
)
+ route(
+ path = "/item"
+ ) {
+ put(
+ path = "/create",
+ body = engine.createInventoryItem()
+ )
+ put(
+ path = "/count",
+ body = engine.changeInventoryItemCount()
+ )
+ put(
+ path = "/consume",
+ body = engine.consumeInventoryItem()
+ )
+ put(
+ path = "/equip",
+ body = engine.equipInventoryItem()
+ )
+ delete(
+ path = "/delete",
+ body = engine.deleteInventoryItem()
+ )
+ }
}
}
}
diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/DELETE_InventoryItem.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/DELETE_InventoryItem.kt
new file mode 100644
index 0000000..4567f18
--- /dev/null
+++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/DELETE_InventoryItem.kt
@@ -0,0 +1,40 @@
+package com.pixelized.server.lwa.server.rest.inventory
+
+import com.pixelized.server.lwa.server.Engine
+import com.pixelized.server.lwa.utils.extentions.characterSheetId
+import com.pixelized.server.lwa.utils.extentions.exception
+import com.pixelized.server.lwa.utils.extentions.inventoryId
+import com.pixelized.server.lwa.utils.extentions.itemId
+import com.pixelized.shared.lwa.protocol.rest.APIResponse
+import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation
+import io.ktor.server.response.respond
+import io.ktor.server.routing.RoutingContext
+
+fun Engine.deleteInventoryItem(): suspend RoutingContext.() -> Unit {
+ return {
+ try {
+ // get the query parameter
+ val characterSheetId = call.queryParameters.characterSheetId
+ val inventoryId = call.queryParameters.inventoryId
+ // add the item to the inventory.
+ inventoryService.deleteInventoryItem(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ )
+ // API & WebSocket responses.
+ call.respond(
+ message = APIResponse.success(),
+ )
+ webSocket.emit(
+ value = ApiSynchronisation.InventoryUpdate(
+ timestamp = System.currentTimeMillis(),
+ characterSheetId = characterSheetId,
+ ),
+ )
+ } catch (exception: Exception) {
+ call.exception(
+ exception = exception,
+ )
+ }
+ }
+}
diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/PUT_ChangeInventoryItemCount.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/PUT_ChangeInventoryItemCount.kt
new file mode 100644
index 0000000..0e3c9e4
--- /dev/null
+++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/PUT_ChangeInventoryItemCount.kt
@@ -0,0 +1,42 @@
+package com.pixelized.server.lwa.server.rest.inventory
+
+import com.pixelized.server.lwa.server.Engine
+import com.pixelized.server.lwa.utils.extentions.characterSheetId
+import com.pixelized.server.lwa.utils.extentions.count
+import com.pixelized.server.lwa.utils.extentions.exception
+import com.pixelized.server.lwa.utils.extentions.inventoryId
+import com.pixelized.shared.lwa.protocol.rest.APIResponse
+import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation
+import io.ktor.server.response.respond
+import io.ktor.server.routing.RoutingContext
+
+fun Engine.changeInventoryItemCount(): suspend RoutingContext.() -> Unit {
+ return {
+ try {
+ // get the query parameter
+ val characterSheetId = call.queryParameters.characterSheetId
+ val inventoryId = call.queryParameters.inventoryId
+ val count = call.queryParameters.count
+ // add the item to the inventory.
+ inventoryService.changeInventoryItemCount(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ count = count,
+ )
+ // API & WebSocket responses.
+ call.respond(
+ message = APIResponse.success(),
+ )
+ webSocket.emit(
+ value = ApiSynchronisation.InventoryUpdate(
+ timestamp = System.currentTimeMillis(),
+ characterSheetId = characterSheetId,
+ ),
+ )
+ } catch (exception: Exception) {
+ call.exception(
+ exception = exception,
+ )
+ }
+ }
+}
diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/PUT_ConsumeInventoryItem.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/PUT_ConsumeInventoryItem.kt
new file mode 100644
index 0000000..322c553
--- /dev/null
+++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/PUT_ConsumeInventoryItem.kt
@@ -0,0 +1,39 @@
+package com.pixelized.server.lwa.server.rest.inventory
+
+import com.pixelized.server.lwa.server.Engine
+import com.pixelized.server.lwa.utils.extentions.characterSheetId
+import com.pixelized.server.lwa.utils.extentions.exception
+import com.pixelized.server.lwa.utils.extentions.inventoryId
+import com.pixelized.shared.lwa.protocol.rest.APIResponse
+import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation
+import io.ktor.server.response.respond
+import io.ktor.server.routing.RoutingContext
+
+fun Engine.consumeInventoryItem(): suspend RoutingContext.() -> Unit {
+ return {
+ try {
+ // get the query parameter
+ val characterSheetId = call.queryParameters.characterSheetId
+ val inventoryId = call.queryParameters.inventoryId
+ // add the item to the inventory.
+ inventoryService.consumeInventoryItem(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ )
+ // API & WebSocket responses.
+ call.respond(
+ message = APIResponse.success(),
+ )
+ webSocket.emit(
+ value = ApiSynchronisation.InventoryUpdate(
+ timestamp = System.currentTimeMillis(),
+ characterSheetId = characterSheetId,
+ ),
+ )
+ } catch (exception: Exception) {
+ call.exception(
+ exception = exception,
+ )
+ }
+ }
+}
diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/PUT_EquipInventoryItem.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/PUT_EquipInventoryItem.kt
new file mode 100644
index 0000000..e7aecbc
--- /dev/null
+++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/PUT_EquipInventoryItem.kt
@@ -0,0 +1,43 @@
+package com.pixelized.server.lwa.server.rest.inventory
+
+import com.pixelized.server.lwa.server.Engine
+import com.pixelized.server.lwa.utils.extentions.characterSheetId
+import com.pixelized.server.lwa.utils.extentions.equip
+import com.pixelized.server.lwa.utils.extentions.exception
+import com.pixelized.server.lwa.utils.extentions.inventoryId
+import com.pixelized.shared.lwa.protocol.rest.APIResponse
+import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation
+import io.ktor.server.response.respond
+import io.ktor.server.routing.RoutingContext
+
+fun Engine.equipInventoryItem(): suspend RoutingContext.() -> Unit {
+ return {
+ try {
+ // get the query parameter
+ val characterSheetId = call.queryParameters.characterSheetId
+ val inventoryId = call.queryParameters.inventoryId
+ val equip = call.queryParameters.equip
+
+ // add the item to the inventory.
+ inventoryService.equipInventoryItem(
+ characterSheetId = characterSheetId,
+ inventoryId = inventoryId,
+ equip = equip,
+ )
+ // API & WebSocket responses.
+ call.respond(
+ message = APIResponse.success(),
+ )
+ webSocket.emit(
+ value = ApiSynchronisation.InventoryUpdate(
+ timestamp = System.currentTimeMillis(),
+ characterSheetId = characterSheetId,
+ ),
+ )
+ } catch (exception: Exception) {
+ call.exception(
+ exception = exception,
+ )
+ }
+ }
+}
diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/CREATE_Inventory.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/PUT_InventoryItem.kt
similarity index 91%
rename from server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/CREATE_Inventory.kt
rename to server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/PUT_InventoryItem.kt
index 186be00..4a67738 100644
--- a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/CREATE_Inventory.kt
+++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/inventory/PUT_InventoryItem.kt
@@ -9,14 +9,14 @@ import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
-fun Engine.createInventory(): suspend RoutingContext.() -> Unit {
+fun Engine.createInventoryItem(): suspend RoutingContext.() -> Unit {
return {
try {
// get the query parameter
val characterSheetId = call.queryParameters.characterSheetId
val itemId = call.queryParameters.itemId
// add the item to the inventory.
- val inventoryId = inventoryService.createItem(
+ val inventoryId = inventoryService.createInventoryItem(
characterSheetId = characterSheetId,
itemId = itemId,
)
diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/utils/extentions/ParametersExt.kt b/server/src/main/kotlin/com/pixelized/server/lwa/utils/extentions/ParametersExt.kt
index 3c71759..0475558 100644
--- a/server/src/main/kotlin/com/pixelized/server/lwa/utils/extentions/ParametersExt.kt
+++ b/server/src/main/kotlin/com/pixelized/server/lwa/utils/extentions/ParametersExt.kt
@@ -10,6 +10,7 @@ inline fun Parameters.param(
): T {
return when (T::class) {
String::class -> this[name] as? T
+ Float::class -> this[name]?.toFloatOrNull() as? T
Boolean::class -> this[name]?.toBooleanStrictOrNull() as? T
else -> null
} ?: throw MissingParameterException(
@@ -30,12 +31,24 @@ val Parameters.alterationId: String
code = APIResponse.ErrorCode.AlterationId,
)
+val Parameters.inventoryId: String
+ get() = param(
+ name = "inventoryId",
+ code = APIResponse.ErrorCode.InventoryId,
+ )
+
val Parameters.itemId: String
get() = param(
name = "itemId",
code = APIResponse.ErrorCode.ItemId,
)
+val Parameters.count: Float
+ get() = param(
+ name = "count",
+ code = APIResponse.ErrorCode.Count,
+ )
+
val Parameters.create: Boolean
get() = param(
name = "create",
@@ -46,4 +59,10 @@ val Parameters.active: Boolean
get() = param(
name = "active",
code = APIResponse.ErrorCode.Active,
+ )
+
+val Parameters.equip: Boolean
+ get() = param(
+ name = "equip",
+ code = APIResponse.ErrorCode.Equip,
)
\ No newline at end of file
diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/rest/APIResponse.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/rest/APIResponse.kt
index 52b62ce..b058d0d 100644
--- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/rest/APIResponse.kt
+++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/rest/APIResponse.kt
@@ -15,13 +15,16 @@ data class APIResponse(
AlterationId,
AlterationName,
ItemId,
+ InventoryId,
ItemName,
CharacterSheetId,
Create,
Active,
+ Equip,
Damage,
Fatigue,
Diminished,
+ Count,
}
companion object {