diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/campaign/CampaignStore.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/campaign/CampaignStore.kt index 66368e6..2438984 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/campaign/CampaignStore.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/campaign/CampaignStore.kt @@ -6,11 +6,9 @@ import com.pixelized.shared.lwa.model.campaign.Campaign import com.pixelized.shared.lwa.model.campaign.character import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory import com.pixelized.shared.lwa.model.campaign.npc -import com.pixelized.shared.lwa.protocol.websocket.CampaignMessage +import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent import com.pixelized.shared.lwa.protocol.websocket.GameMasterEvent -import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation import com.pixelized.shared.lwa.protocol.websocket.SocketMessage -import com.pixelized.shared.lwa.usecase.CampaignUseCase import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -113,25 +111,25 @@ class CampaignStore( campaign(update = true) } - is CampaignMessage -> { + is CampaignEvent -> { val instanceId = Campaign.CharacterInstance.Id( prefix = message.prefix, characterSheetId = message.characterSheetId, instanceId = message.instanceId, ) when (message) { - is CampaignMessage.UpdateCharacteristic -> updateCharacteristic( + is CampaignEvent.UpdateCharacteristic -> updateCharacteristic( characterInstanceId = instanceId, characteristic = factory.convertFromJson(json = message.characteristic), value = message.newValue, ) - is CampaignMessage.UpdateDiminished -> updateDiminished( + is CampaignEvent.UpdateDiminished -> updateDiminished( characterInstanceId = instanceId, diminished = message.diminished, ) - is CampaignMessage.ToggleActiveAlteration -> updateAlterations( + is CampaignEvent.ToggleActiveAlteration -> updateAlterations( characterInstanceId = instanceId, alterationId = message.alterationId, ) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt index 86ede52..04f8084 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt @@ -3,10 +3,9 @@ package com.pixelized.desktop.lwa.repository.characterSheet import com.pixelized.desktop.lwa.network.LwaClient import com.pixelized.desktop.lwa.repository.network.NetworkRepository import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet -import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJsonFactory +import com.pixelized.shared.lwa.model.characterSheet.factory.CharacterSheetJsonFactory import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetPreview import com.pixelized.shared.lwa.protocol.websocket.SocketMessage -import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation import com.pixelized.shared.lwa.protocol.websocket.UpdateSkillUsageMessage import com.pixelized.shared.lwa.usecase.CharacterSheetUseCase import kotlinx.coroutines.CoroutineScope diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/roll_history/RollHistoryRepository.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/roll_history/RollHistoryRepository.kt index 5892b70..f526cda 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/roll_history/RollHistoryRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/roll_history/RollHistoryRepository.kt @@ -1,14 +1,12 @@ package com.pixelized.desktop.lwa.repository.roll_history import com.pixelized.desktop.lwa.repository.network.NetworkRepository -import com.pixelized.shared.lwa.protocol.websocket.RollMessage +import com.pixelized.shared.lwa.protocol.websocket.RollEvent import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterIsInstance -import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.shareIn class RollHistoryRepository( @@ -16,8 +14,8 @@ class RollHistoryRepository( ) { private val scope = CoroutineScope(Dispatchers.IO) - val rolls: SharedFlow = network.data - .filterIsInstance(RollMessage::class) + val rolls: SharedFlow = network.data + .filterIsInstance(RollEvent::class) .shareIn( scope = scope, started = SharingStarted.Eagerly, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/characteristic/CharacterDetailCharacteristicDialogViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/characteristic/CharacterDetailCharacteristicDialogViewModel.kt index 611c61c..c344fc2 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/characteristic/CharacterDetailCharacteristicDialogViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/characteristic/CharacterDetailCharacteristicDialogViewModel.kt @@ -15,7 +15,7 @@ import com.pixelized.shared.lwa.model.campaign.damage import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory import com.pixelized.shared.lwa.model.campaign.power import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet -import com.pixelized.shared.lwa.protocol.websocket.CampaignMessage +import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent class CharacterDetailCharacteristicDialogViewModel( private val characterSheetRepository: CharacterSheetRepository, @@ -84,7 +84,7 @@ class CharacterDetailCharacteristicDialogViewModel( ) // share the data through the websocket. network.share( - message = CampaignMessage.UpdateCharacteristic( + message = CampaignEvent.UpdateCharacteristic( timestamp = System.currentTimeMillis(), prefix = characterInstanceId.prefix, characterSheetId = characterInstanceId.characterSheetId, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/portrait/PortraitOverlayViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/portrait/PortraitOverlayViewModel.kt index db1dca8..ac39ef3 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/portrait/PortraitOverlayViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/portrait/PortraitOverlayViewModel.kt @@ -5,7 +5,6 @@ import androidx.lifecycle.viewModelScope import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository import com.pixelized.desktop.lwa.repository.network.NetworkRepository import com.pixelized.desktop.lwa.repository.settings.SettingsRepository -import com.pixelized.shared.lwa.protocol.websocket.GameEvent import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.distinctUntilChanged diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/roll/RollViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/roll/RollViewModel.kt index 00398c5..2ccb86f 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/roll/RollViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/roll/RollViewModel.kt @@ -13,7 +13,7 @@ import com.pixelized.desktop.lwa.ui.overlay.roll.DifficultyUio.Difficulty import com.pixelized.desktop.lwa.ui.overlay.roll.RollAction.RollActionUio import com.pixelized.shared.lwa.model.AlteredCharacterSheet import com.pixelized.shared.lwa.model.AlteredCharacterSheetFactory -import com.pixelized.shared.lwa.protocol.websocket.RollMessage +import com.pixelized.shared.lwa.protocol.websocket.RollEvent import com.pixelized.shared.lwa.usecase.ExpressionUseCase import com.pixelized.shared.lwa.usecase.SkillStepUseCase import kotlinx.coroutines.Job @@ -278,7 +278,7 @@ class RollViewModel( ) { val rollAction = rollAction ?: return - val payload = RollMessage( + val payload = RollEvent( timestamp = System.currentTimeMillis(), uuid = UUID.randomUUID().toString(), prefix = rollAction.characterInstanceId.prefix, @@ -297,11 +297,11 @@ class RollViewModel( rollSuccessLimit = rollStep?.success?.last, critical = rollStep?.let { when (roll) { - in it.criticalSuccess -> RollMessage.Critical.CRITICAL_SUCCESS - in it.specialSuccess -> RollMessage.Critical.SPECIAL_SUCCESS - in it.success -> RollMessage.Critical.SUCCESS - in it.failure -> RollMessage.Critical.FAILURE - in it.criticalFailure -> RollMessage.Critical.CRITICAL_FAILURE + in it.criticalSuccess -> RollEvent.Critical.CRITICAL_SUCCESS + in it.specialSuccess -> RollEvent.Critical.SPECIAL_SUCCESS + in it.success -> RollEvent.Critical.SUCCESS + in it.failure -> RollEvent.Critical.FAILURE + in it.criticalFailure -> RollEvent.Critical.CRITICAL_FAILURE else -> null } }, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDiminishedViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDiminishedViewModel.kt index 44de234..0c27aa3 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDiminishedViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDiminishedViewModel.kt @@ -9,7 +9,7 @@ import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository import com.pixelized.desktop.lwa.repository.network.NetworkRepository import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.DiminishedStatDialogUio import com.pixelized.shared.lwa.model.campaign.Campaign -import com.pixelized.shared.lwa.protocol.websocket.CampaignMessage +import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent import lwacharactersheet.composeapp.generated.resources.Res import lwacharactersheet.composeapp.generated.resources.character_sheet__diminished__label import org.jetbrains.compose.resources.getString @@ -56,7 +56,7 @@ class CharacterDiminishedViewModel( ) { val diminished = dialog.value().text.toIntOrNull() ?: 0 networkRepository.share( - message = CampaignMessage.UpdateDiminished( + message = CampaignEvent.UpdateDiminished( timestamp = System.currentTimeMillis(), prefix = dialog.characterInstanceId.prefix, characterSheetId = dialog.characterInstanceId.characterSheetId, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/TextMessageFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/TextMessageFactory.kt index a8afd14..2db1f4f 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/TextMessageFactory.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/TextMessageFactory.kt @@ -8,11 +8,9 @@ import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.RollTextMessag import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.TextMessage import com.pixelized.shared.lwa.model.campaign.CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Damage import com.pixelized.shared.lwa.model.campaign.CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Power -import com.pixelized.shared.lwa.protocol.websocket.CampaignMessage -import com.pixelized.shared.lwa.protocol.websocket.GameEvent +import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent import com.pixelized.shared.lwa.protocol.websocket.GameMasterEvent -import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation -import com.pixelized.shared.lwa.protocol.websocket.RollMessage +import com.pixelized.shared.lwa.protocol.websocket.RollEvent import com.pixelized.shared.lwa.protocol.websocket.SocketMessage import com.pixelized.shared.lwa.protocol.websocket.UpdateSkillUsageMessage import lwacharactersheet.composeapp.generated.resources.Res @@ -37,7 +35,7 @@ class TextMessageFactory( val id = formatId.format(time) return when (message) { - is RollMessage -> { + is RollEvent -> { val sheetPreview = characterSheetRepository .characterPreview(characterId = message.characterSheetId) ?: return null @@ -54,18 +52,18 @@ class TextMessageFactory( rollSuccessLimit = takeIf { isGm }?.let { message.rollSuccessLimit }, resultLabel = message.resultLabel, resultType = when (message.critical) { - RollMessage.Critical.CRITICAL_SUCCESS -> RollTextMessageUio.Critical.CRITICAL_SUCCESS - RollMessage.Critical.SPECIAL_SUCCESS -> RollTextMessageUio.Critical.SPECIAL_SUCCESS - RollMessage.Critical.SUCCESS -> RollTextMessageUio.Critical.SUCCESS - RollMessage.Critical.FAILURE -> RollTextMessageUio.Critical.FAILURE - RollMessage.Critical.CRITICAL_FAILURE -> RollTextMessageUio.Critical.CRITICAL_FAILURE + RollEvent.Critical.CRITICAL_SUCCESS -> RollTextMessageUio.Critical.CRITICAL_SUCCESS + RollEvent.Critical.SPECIAL_SUCCESS -> RollTextMessageUio.Critical.SPECIAL_SUCCESS + RollEvent.Critical.SUCCESS -> RollTextMessageUio.Critical.SUCCESS + RollEvent.Critical.FAILURE -> RollTextMessageUio.Critical.FAILURE + RollEvent.Critical.CRITICAL_FAILURE -> RollTextMessageUio.Critical.CRITICAL_FAILURE null -> null } ) } - is CampaignMessage -> when (message) { - is CampaignMessage.UpdateDiminished -> { + is CampaignEvent -> when (message) { + is CampaignEvent.UpdateDiminished -> { val sheetPreview = characterSheetRepository .characterPreview(characterId = message.characterSheetId) ?: return null @@ -78,7 +76,7 @@ class TextMessageFactory( ) } - is CampaignMessage.UpdateCharacteristic -> { + is CampaignEvent.UpdateCharacteristic -> { val sheet = characterSheetRepository.characterDetail( characterSheetId = message.characterSheetId, ) ?: return null @@ -100,7 +98,7 @@ class TextMessageFactory( ) } - is CampaignMessage.ToggleActiveAlteration -> null // TODO + is CampaignEvent.ToggleActiveAlteration -> null // TODO } is RestSynchronisation.Campaign -> null diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/CharacterSheetViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/CharacterSheetViewModel.kt index f50abc4..65f7ccf 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/CharacterSheetViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/CharacterSheetViewModel.kt @@ -14,7 +14,7 @@ import com.pixelized.desktop.lwa.repository.network.NetworkRepository import com.pixelized.desktop.lwa.ui.navigation.screen.destination.CharacterSheetDestination import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.CharacterSheetDeleteConfirmationDialogUio import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.DiminishedStatDialogUio -import com.pixelized.shared.lwa.protocol.websocket.CampaignMessage +import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent import com.pixelized.shared.lwa.protocol.websocket.UpdateSkillUsageMessage import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow @@ -144,7 +144,7 @@ class CharacterSheetViewModel( suspend fun changeDiminished(dialog: DiminishedStatDialogUio) { val diminished = dialog.value().text.toIntOrNull() ?: 0 network.share( - message = CampaignMessage.UpdateDiminished( + message = CampaignEvent.UpdateDiminished( timestamp = System.currentTimeMillis(), prefix = dialog.characterInstanceId.prefix, characterSheetId = dialog.characterInstanceId.characterSheetId, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterActionUseCase.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterActionUseCase.kt index 5b52393..6f05e7e 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterActionUseCase.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterActionUseCase.kt @@ -3,7 +3,6 @@ package com.pixelized.desktop.lwa.ui.screen.gamemaster import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository import com.pixelized.desktop.lwa.repository.network.NetworkRepository import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacterUio.Action -import com.pixelized.shared.lwa.protocol.websocket.GameEvent class GameMasterActionUseCase( private val campaignRepository: CampaignRepository, diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/model/alteration/AlterationService.kt b/server/src/main/kotlin/com/pixelized/server/lwa/model/alteration/AlterationService.kt index ce6f3a5..f0fda7a 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/model/alteration/AlterationService.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/model/alteration/AlterationService.kt @@ -1,13 +1,33 @@ package com.pixelized.server.lwa.model.alteration import com.pixelized.shared.lwa.model.alteration.AlterationJson +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn class AlterationService( store: AlterationStore, ) { + private val scope = CoroutineScope(Dispatchers.IO + Job()) + private val alterationsFlow = store.alterationsFlow() + private val alterationHashFlow = alterationsFlow + .map { data -> data.associateBy { it.id } } + .stateIn( + scope = scope, + started = SharingStarted.Eagerly, + initialValue = emptyMap() + ) + fun alterations(): List { return alterationsFlow.value } + + fun alteration(alterationId: String): AlterationJson? { + return alterationHashFlow.value[alterationId] + } } diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/model/campaign/CampaignService.kt b/server/src/main/kotlin/com/pixelized/server/lwa/model/campaign/CampaignService.kt index f81ebae..d57577d 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/model/campaign/CampaignService.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/model/campaign/CampaignService.kt @@ -2,10 +2,7 @@ package com.pixelized.server.lwa.model.campaign import com.pixelized.shared.lwa.model.campaign.Campaign import com.pixelized.shared.lwa.model.campaign.CampaignJson -import com.pixelized.shared.lwa.model.campaign.character import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory -import com.pixelized.shared.lwa.model.campaign.npc -import com.pixelized.shared.lwa.usecase.CampaignUseCase import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -17,7 +14,6 @@ import kotlinx.coroutines.flow.stateIn class CampaignService( private val store: CampaignStore, private val factory: CampaignJsonFactory, - private val useCase: CampaignUseCase, ) { private val scope = CoroutineScope(Dispatchers.IO + Job()) @@ -41,36 +37,14 @@ class CampaignService( return campaignJsonFlow.value } - suspend fun addCharacter( - characterInstanceId: Campaign.CharacterInstance.Id, + fun addCharacter( + characterSheetId: String, ): Boolean { - // fetch all the current campaign character - val characters = campaign.characters.toMutableMap() - // check if the character is in the campaign. - if (characters.containsKey(characterInstanceId)) return false - // update the corresponding character - characters[characterInstanceId] = campaign.character(id = characterInstanceId) - // save the campaign to the disk + update the flow. - return try { - store.save( - campaign = campaign.copy(characters = characters) - ) - true - } catch (exception: Exception) { - false - } - } - - suspend fun removeCharacter( - characterInstanceId: Campaign.CharacterInstance.Id, - ): Boolean { - // fetch all the current campaign character - val characters = campaign.characters.toMutableMap() - // check if the character is in the campaign. - if (characters.containsKey(characterInstanceId).not()) return false - // update the corresponding character - characters.remove(characterInstanceId) - // save the campaign to the disk + update the flow. + // check if the character is already in the campaign. + if (campaign.characters.contains(characterSheetId)) return false + // update the corresponding instance + val characters = campaign.characters.toMutableSet().also { it.add(characterSheetId) } + // save the campaign to the disk (update the flow). return try { store.save( campaign = campaign.copy(characters = characters) @@ -82,18 +56,34 @@ class CampaignService( } suspend fun addNpc( - npcInstanceId: Campaign.CharacterInstance.Id, + characterSheetId: String, + ): Boolean { + // check if the character is already in the campaign. + if (campaign.npcs.contains(characterSheetId)) return false + // update the corresponding instance + val characters = campaign.npcs.toMutableSet().also { it.add(characterSheetId) } + // save the campaign to the disk (update the flow). + return try { + store.save( + campaign = campaign.copy(npcs = characters) + ) + true + } catch (exception: Exception) { + false + } + } + + suspend fun removeCharacter( + characterSheetId: String, ): Boolean { - // fetch all the current campaign character - val npcs = campaign.npcs.toMutableMap() // check if the character is in the campaign. - if (npcs.containsKey(npcInstanceId)) return false - // update the corresponding character - npcs[npcInstanceId] = campaign.npc(id = npcInstanceId) + if (campaign.characters.contains(characterSheetId).not()) return false + // update the corresponding instance + val characters = campaign.characters.toMutableSet().also { it.remove(characterSheetId) } // save the campaign to the disk + update the flow. return try { store.save( - campaign = campaign.copy(npcs = npcs) + campaign = campaign.copy(characters = characters) ) true } catch (exception: Exception) { @@ -102,18 +92,16 @@ class CampaignService( } suspend fun removeNpc( - npcInstanceId: Campaign.CharacterInstance.Id, + characterSheetId: String, ): Boolean { - // fetch all the current campaign character - val npcs = campaign.npcs.toMutableMap() // check if the character is in the campaign. - if (npcs.containsKey(npcInstanceId).not()) return false - // update the corresponding character - npcs.remove(npcInstanceId) + if (campaign.npcs.contains(characterSheetId).not()) return false + // update the corresponding instance + val characters = campaign.npcs.toMutableSet().also { it.remove(characterSheetId) } // save the campaign to the disk + update the flow. return try { store.save( - campaign = campaign.copy(npcs = npcs) + campaign = campaign.copy(npcs = characters) ) true } catch (exception: Exception) { @@ -124,35 +112,7 @@ class CampaignService( suspend fun removeInstance( characterSheetId: String, ): Boolean { - // fetch all the current campaign character - val characterIds = campaign.characters - .filterKeys { it.characterSheetId == characterSheetId } - .keys - val npcIds = campaign.npcs - .filterKeys { it.characterSheetId == characterSheetId } - .keys - - // check if the character is in the campaign. - if (characterIds.isEmpty() && npcIds.isEmpty()) return false - - // update the corresponding character - val characters = campaign.characters.toMutableMap() - val npcs = campaign.npcs.toMutableMap() - characterIds.forEach(characters::remove) - npcIds.forEach(npcs::remove) - - // save the campaign to the disk + update the flow. - return try { - store.save( - campaign = campaign.copy( - characters = characters, - npcs = npcs, - ) - ) - true - } catch (exception: Exception) { - false - } + return removeCharacter(characterSheetId) || removeNpc(characterSheetId) } suspend fun setScene( @@ -171,127 +131,127 @@ class CampaignService( // Data manipulation through WebSocket. - suspend fun updateCharacteristic( - characterInstanceId: Campaign.CharacterInstance.Id, - characteristic: Campaign.CharacterInstance.Characteristic, - value: Int, - ) { - when (characterInstanceId.prefix) { - Campaign.CharacterInstance.Id.PLAYER -> { - // fetch all the current campaign character - val characters = campaign.characters.toMutableMap() - // update the corresponding character using the use case. - characters[characterInstanceId] = useCase.updateCharacteristic( - instance = campaign.character(id = characterInstanceId), - characteristic = characteristic, - value = value, - ) - // save the campaign to the disk + update the flow. - store.save( - campaign = campaign.copy(characters = characters) - ) - } - - Campaign.CharacterInstance.Id.NPC -> { - // fetch all the current campaign character - val npcs = campaign.npcs.toMutableMap() - // update the corresponding character using the use case. - npcs[characterInstanceId] = useCase.updateCharacteristic( - instance = campaign.npc(id = characterInstanceId), - characteristic = characteristic, - value = value, - ) - // save the campaign to the disk + update the flow. - store.save( - campaign = campaign.copy(npcs = npcs) - ) - } - } - } - - suspend fun updateDiminished( - characterInstanceId: Campaign.CharacterInstance.Id, - diminished: Int, - ) { - when (characterInstanceId.prefix) { - Campaign.CharacterInstance.Id.PLAYER -> { - // fetch all the current campaign character - val characters = campaign.characters.toMutableMap() - // update the corresponding character using the use case. - characters[characterInstanceId] = useCase.updateDiminished( - instance = campaign.character(id = characterInstanceId), - diminished = diminished, - ) - // save the campaign to the disk + update the flow. - store.save( - campaign = campaign.copy(characters = characters) - ) - } - - Campaign.CharacterInstance.Id.NPC -> { - // fetch all the current campaign character - val npcs = campaign.npcs.toMutableMap() - // update the corresponding character using the use case. - npcs[characterInstanceId] = useCase.updateDiminished( - instance = campaign.npc(id = characterInstanceId), - diminished = diminished, - ) - // save the campaign to the disk + update the flow. - store.save( - campaign = campaign.copy(npcs = npcs) - ) - } - } - } - - suspend fun toggleAlteration( - characterInstanceId: Campaign.CharacterInstance.Id, - alterationId: String, - ) { - when (characterInstanceId.prefix) { - Campaign.CharacterInstance.Id.PLAYER -> { - // fetch all the current campaign character - val characters = campaign.characters.toMutableMap() - // update the corresponding character alterations - characters[characterInstanceId]?.let { character -> - characters[characterInstanceId] = character.copy( - alterations = character.alterations.toMutableList().also { alterations -> - if (alterations.contains(alterationId)) { - alterations.remove(alterationId) - } else { - alterations.add(alterationId) - } - }, - ) - } - // save the campaign to the disk + update the flow. - store.save( - campaign = campaign.copy(characters = characters) - ) - } - - Campaign.CharacterInstance.Id.NPC -> { - // fetch all the current campaign character - val characters = campaign.npcs.toMutableMap() - // update the corresponding character alterations - characters[characterInstanceId]?.let { character -> - characters[characterInstanceId] = character.copy( - alterations = character.alterations.toMutableList().also { alterations -> - if (alterations.contains(alterationId)) { - alterations.remove(alterationId) - } else { - alterations.add(alterationId) - } - }, - ) - } - // save the campaign to the disk + update the flow. - store.save( - campaign = campaign.copy(npcs = characters) - ) - } - } - } +// suspend fun updateCharacteristic( +// characterInstanceId: Campaign.CharacterInstance.Id, +// characteristic: Campaign.CharacterInstance.Characteristic, +// value: Int, +// ) { +// when (characterInstanceId.prefix) { +// Campaign.CharacterInstance.Id.PLAYER -> { +// // fetch all the current campaign character +// val characters = campaign.characters.toMutableMap() +// // update the corresponding character using the use case. +// characters[characterInstanceId] = useCase.updateCharacteristic( +// instance = campaign.character(id = characterInstanceId), +// characteristic = characteristic, +// value = value, +// ) +// // save the campaign to the disk + update the flow. +// store.save( +// campaign = campaign.copy(characters = characters) +// ) +// } +// +// Campaign.CharacterInstance.Id.NPC -> { +// // fetch all the current campaign character +// val npcs = campaign.npcs.toMutableMap() +// // update the corresponding character using the use case. +// npcs[characterInstanceId] = useCase.updateCharacteristic( +// instance = campaign.npc(id = characterInstanceId), +// characteristic = characteristic, +// value = value, +// ) +// // save the campaign to the disk + update the flow. +// store.save( +// campaign = campaign.copy(npcs = npcs) +// ) +// } +// } +// } +// +// suspend fun updateDiminished( +// characterInstanceId: Campaign.CharacterInstance.Id, +// diminished: Int, +// ) { +// when (characterInstanceId.prefix) { +// Campaign.CharacterInstance.Id.PLAYER -> { +// // fetch all the current campaign character +// val characters = campaign.characters.toMutableMap() +// // update the corresponding character using the use case. +// characters[characterInstanceId] = useCase.updateDiminished( +// instance = campaign.character(id = characterInstanceId), +// diminished = diminished, +// ) +// // save the campaign to the disk + update the flow. +// store.save( +// campaign = campaign.copy(characters = characters) +// ) +// } +// +// Campaign.CharacterInstance.Id.NPC -> { +// // fetch all the current campaign character +// val npcs = campaign.npcs.toMutableMap() +// // update the corresponding character using the use case. +// npcs[characterInstanceId] = useCase.updateDiminished( +// instance = campaign.npc(id = characterInstanceId), +// diminished = diminished, +// ) +// // save the campaign to the disk + update the flow. +// store.save( +// campaign = campaign.copy(npcs = npcs) +// ) +// } +// } +// } +// +// suspend fun toggleAlteration( +// characterInstanceId: Campaign.CharacterInstance.Id, +// alterationId: String, +// ) { +// when (characterInstanceId.prefix) { +// Campaign.CharacterInstance.Id.PLAYER -> { +// // fetch all the current campaign character +// val characters = campaign.characters.toMutableMap() +// // update the corresponding character alterations +// characters[characterInstanceId]?.let { character -> +// characters[characterInstanceId] = character.copy( +// alterations = character.alterations.toMutableList().also { alterations -> +// if (alterations.contains(alterationId)) { +// alterations.remove(alterationId) +// } else { +// alterations.add(alterationId) +// } +// }, +// ) +// } +// // save the campaign to the disk + update the flow. +// store.save( +// campaign = campaign.copy(characters = characters) +// ) +// } +// +// Campaign.CharacterInstance.Id.NPC -> { +// // fetch all the current campaign character +// val characters = campaign.npcs.toMutableMap() +// // update the corresponding character alterations +// characters[characterInstanceId]?.let { character -> +// characters[characterInstanceId] = character.copy( +// alterations = character.alterations.toMutableList().also { alterations -> +// if (alterations.contains(alterationId)) { +// alterations.remove(alterationId) +// } else { +// alterations.add(alterationId) +// } +// }, +// ) +// } +// // save the campaign to the disk + update the flow. +// store.save( +// campaign = campaign.copy(npcs = characters) +// ) +// } +// } +// } suspend fun updateToggleParty() { store.save( diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/model/campaign/CampaignStore.kt b/server/src/main/kotlin/com/pixelized/server/lwa/model/campaign/CampaignStore.kt index 6f3ef36..e81062f 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/model/campaign/CampaignStore.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/model/campaign/CampaignStore.kt @@ -18,7 +18,7 @@ class CampaignStore( private val factory: CampaignJsonFactory, private val json: Json, ) { - private val campaignFlow = MutableStateFlow(value = Campaign.EMPTY) + private val campaignFlow = MutableStateFlow(value = Campaign.empty()) init { // create the directory if needed. @@ -38,7 +38,7 @@ class CampaignStore( loadCampaign() } catch (exception: Exception) { println(exception) // TODO proper exception handling - Campaign.EMPTY + Campaign.empty() } } @@ -55,7 +55,7 @@ class CampaignStore( } // Guard, if the file is empty we load a default campaign. - if (json.isBlank()) return Campaign.EMPTY + if (json.isBlank()) return Campaign.empty() val campaign = try { val data = this.json.decodeFromString(json) @@ -74,7 +74,7 @@ class CampaignStore( fun save(campaign: Campaign) { // convert the data to json format val json = try { - factory.convertToJson(data = campaign).let(json::encodeToString) + factory.convertToJson(campaign = campaign).let(json::encodeToString) } catch (exception: Exception) { throw JsonConversionException(root = exception) } diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/model/character/CharacterSheetService.kt b/server/src/main/kotlin/com/pixelized/server/lwa/model/character/CharacterSheetService.kt index 3756d0c..6463ea8 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/model/character/CharacterSheetService.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/model/character/CharacterSheetService.kt @@ -1,9 +1,8 @@ package com.pixelized.server.lwa.model.character import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJson -import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJsonFactory +import com.pixelized.shared.lwa.model.characterSheet.factory.CharacterSheetJsonFactory import com.pixelized.shared.lwa.protocol.rest.CharacterPreviewJson -import com.pixelized.shared.lwa.usecase.CharacterSheetUseCase import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -14,7 +13,6 @@ import kotlinx.coroutines.flow.stateIn class CharacterSheetService( private val store: CharacterSheetStore, private val factory: CharacterSheetJsonFactory, - private val useCase: CharacterSheetUseCase, ) { private val scope = CoroutineScope(Dispatchers.IO + Job()) private val sheets get() = sheetsFlow.value @@ -30,12 +28,14 @@ class CharacterSheetService( return sheets.map { factory.convertToPreviewJson(sheet = it.value) } } - fun characterSheet(id: String): CharacterSheetJson? { - return sheets[id]?.let(factory::convertToJson) + fun characterSheet(characterSheetId: String): CharacterSheetJson? { + return sheets[characterSheetId]?.let(factory::convertToJson) } suspend fun updateCharacterSheet(character: CharacterSheetJson) { - return store.save(sheet = factory.convertFromJson(character)) + return store.save( + sheet = factory.convertFromJson(character) + ) } fun deleteCharacterSheet(characterSheetId: String): Boolean { @@ -44,30 +44,62 @@ class CharacterSheetService( // Data manipulation through WebSocket. - fun updateCharacterLevel( - characterId: String, - level: Int, + fun updateAlteration( + characterSheetId: String, + alterationId: String, + active: Boolean, ) { - sheets[characterId]?.let { character -> - val update = useCase.updateLevel( - character = character, - level = level, - ) + sheets[characterSheetId]?.let { character -> + val contain = character.alterations.contains(alterationId) + if (active && contain.not()) { + val alterations = character.alterations.toMutableList().also { + it.add(alterationId) + } + store.save( + sheet = character.copy( + alterations = alterations, + ) + ) + } + if (active.not() && contain) { + val alterations = character.alterations.toMutableList().also { + it.remove(alterationId) + } + store.save( + sheet = character.copy( + alterations = alterations, + ) + ) + } + } + } + + fun updateDamage( + characterSheetId: String, + damage: Int, + ) { + sheets[characterSheetId]?.let { character -> + val update = character.copy(damage = damage) store.save(sheet = update) } } - fun updateCharacterSkillLevel( - characterId: String, - skillId: String, - level: Int, + fun updateDiminished( + characterSheetId: String, + diminished: Int, ) { - sheets[characterId]?.let { character -> - val update = useCase.updateSkillLevel( - character = character, - skillId = skillId, - level = level, - ) + sheets[characterSheetId]?.let { character -> + val update = character.copy(diminished = diminished) + store.save(sheet = update) + } + } + + fun updateFatigue( + characterSheetId: String, + fatigue: Int, + ) { + sheets[characterSheetId]?.let { character -> + val update = character.copy(fatigue = fatigue) store.save(sheet = update) } } @@ -78,10 +110,16 @@ class CharacterSheetService( used: Boolean, ) { sheets[characterSheetId]?.let { character -> - val update = useCase.updateSkillUsage( - character = character, - skillId = skillId, - used = used, + val update = character.copy( + commonSkills = character.commonSkills.map { skill -> + skill.takeIf { skill.id == skillId }?.copy(used = used) ?: skill + }, + specialSkills = character.specialSkills.map { skill -> + skill.takeIf { skill.id == skillId }?.copy(used = used) ?: skill + }, + magicSkills = character.magicSkills.map { skill -> + skill.takeIf { skill.id == skillId }?.copy(used = used) ?: skill + }, ) store.save(sheet = update) } diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/model/character/CharacterSheetStore.kt b/server/src/main/kotlin/com/pixelized/server/lwa/model/character/CharacterSheetStore.kt index 20df234..0b611e7 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/model/character/CharacterSheetStore.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/model/character/CharacterSheetStore.kt @@ -2,7 +2,7 @@ package com.pixelized.server.lwa.model.character import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJson -import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJsonFactory +import com.pixelized.shared.lwa.model.characterSheet.factory.CharacterSheetJsonFactory import com.pixelized.shared.lwa.utils.PathProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/Engine.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/Engine.kt index 900e4b4..58be8dd 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/server/Engine.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/Engine.kt @@ -3,16 +3,13 @@ package com.pixelized.server.lwa.server import com.pixelized.server.lwa.model.alteration.AlterationService import com.pixelized.server.lwa.model.campaign.CampaignService import com.pixelized.server.lwa.model.character.CharacterSheetService -import com.pixelized.shared.lwa.model.campaign.Campaign import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory -import com.pixelized.shared.lwa.protocol.websocket.CampaignMessage -import com.pixelized.shared.lwa.protocol.websocket.CampaignMessage.ToggleActiveAlteration -import com.pixelized.shared.lwa.protocol.websocket.GameEvent +import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation +import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent +import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent import com.pixelized.shared.lwa.protocol.websocket.GameMasterEvent -import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation -import com.pixelized.shared.lwa.protocol.websocket.RollMessage +import com.pixelized.shared.lwa.protocol.websocket.RollEvent import com.pixelized.shared.lwa.protocol.websocket.SocketMessage -import com.pixelized.shared.lwa.protocol.websocket.UpdateSkillUsageMessage import kotlinx.coroutines.flow.MutableSharedFlow class Engine( @@ -26,55 +23,52 @@ class Engine( suspend fun handle(message: SocketMessage) { when (message) { - is RollMessage -> Unit // Nothing to do here. - - is CampaignMessage -> { - val instanceId = Campaign.CharacterInstance.Id( - prefix = message.prefix, - characterSheetId = message.characterSheetId, - instanceId = message.instanceId, - ) - when (message) { - is CampaignMessage.UpdateCharacteristic -> campaignService.updateCharacteristic( - characterInstanceId = instanceId, - characteristic = campaignJsonFactory.convertFromJson(json = message.characteristic), - value = message.newValue, - ) - - is CampaignMessage.UpdateDiminished -> campaignService.updateDiminished( - characterInstanceId = instanceId, - diminished = message.diminished, - ) - - is ToggleActiveAlteration -> campaignService.toggleAlteration( - characterInstanceId = instanceId, - alterationId = message.alterationId, - ) - } - } - - is UpdateSkillUsageMessage -> characterService.updateCharacterSkillUsage( - characterSheetId = message.characterSheetId, - skillId = message.skillId, - used = message.used, - ) - - is RestSynchronisation.Campaign -> Unit // Handle in the Rest - - is RestSynchronisation.CharacterSheetUpdate -> Unit // Handle in the Rest - - is RestSynchronisation.CharacterSheetDelete -> Unit // Handle in the Rest - - is ToggleActiveAlteration -> Unit // Handle in the Rest + is RollEvent -> Unit // Nothing to do here. is GameMasterEvent -> when (message) { is GameMasterEvent.TogglePlayer -> campaignService.updateToggleParty() is GameMasterEvent.ToggleNpc -> campaignService.updateToggleNpc() + is GameMasterEvent.DisplayPortrait -> Unit // Nothing to do here. } - is GameEvent -> when (message) { - is GameEvent.DisplayPortrait -> Unit // Nothing to do here. + is CharacterSheetEvent -> when (message) { + is CharacterSheetEvent.UpdateAlteration -> characterService.updateAlteration( + characterSheetId = message.characterSheetId, + alterationId = message.alterationId, + active = message.active, + ) + + is CharacterSheetEvent.UpdateDamage -> characterService.updateDamage( + characterSheetId = message.characterSheetId, + damage = message.damage, + ) + + is CharacterSheetEvent.UpdateDiminished -> characterService.updateDiminished( + characterSheetId = message.characterSheetId, + diminished = message.diminished, + ) + + is CharacterSheetEvent.UpdateFatigue -> characterService.updateFatigue( + characterSheetId = message.characterSheetId, + fatigue = message.fatigue, + ) + + is CharacterSheetEvent.UpdateSkillUsageEvent -> characterService.updateCharacterSkillUsage( + characterSheetId = message.characterSheetId, + skillId = message.skillId, + used = message.used, + ) } + + is CampaignEvent -> when (message) { + is CampaignEvent.CharacterAdded -> Unit // TODO + is CampaignEvent.CharacterRemoved -> Unit // TODO + is CampaignEvent.NpcAdded -> Unit // TODO + is CampaignEvent.NpcRemoved -> Unit // TODO + is CampaignEvent.UpdateScene -> Unit // TODO + } + + is ApiSynchronisation -> Unit // Nothing to do there. } } } \ No newline at end of file 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 264e138..8a3d1b5 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 @@ -1,18 +1,22 @@ package com.pixelized.server.lwa.server +import com.pixelized.server.lwa.server.rest.alteration.getAlteration import com.pixelized.server.lwa.server.rest.alteration.getAlterations -import com.pixelized.server.lwa.server.rest.campaign.deleteCampaignNpc +import com.pixelized.server.lwa.server.rest.campaign.removeCampaignNpc import com.pixelized.server.lwa.server.rest.campaign.getCampaign import com.pixelized.server.lwa.server.rest.campaign.putCampaignCharacter import com.pixelized.server.lwa.server.rest.campaign.putCampaignNpc import com.pixelized.server.lwa.server.rest.campaign.putCampaignScene -import com.pixelized.server.lwa.server.rest.campaign.putToggleAlteration import com.pixelized.server.lwa.server.rest.campaign.removeCampaignCharacter import com.pixelized.server.lwa.server.rest.character.deleteCharacter import com.pixelized.server.lwa.server.rest.character.getCharacter import com.pixelized.server.lwa.server.rest.character.getCharacters import com.pixelized.server.lwa.server.rest.character.putCharacter +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.shared.lwa.SERVER_PORT import com.pixelized.shared.lwa.protocol.websocket.SocketMessage import com.pixelized.shared.lwa.sharedModuleDependencies @@ -111,40 +115,66 @@ class LocalServer { } } ) - get( - path = "/alterations", - body = engine.getAlterations(), - ) - get( - path = "/characters", - body = engine.getCharacters(), - ) - route(path = "/character") { + route( + path = "/alteration", + ) { + get( + path = "/all", + body = engine.getAlterations(), + ) + get( + path = "/detail", + body = engine.getAlteration(), + ) + } + route( + path = "/character", + ) { + get( + path = "/all", + body = engine.getCharacters(), + ) get( path = "/detail", body = engine.getCharacter(), ) - put( - path = "/update", - body = engine.putCharacter(), - ) delete( path = "/delete", body = engine.deleteCharacter(), ) + route( + path = "/update", + ) { + put( + path = "/sheet", + body = engine.putCharacter(), + ) + put( + path = "/damage", + body = engine.putCharacterDamage(), + ) + put( + path = "/fatigue", + body = engine.putCharacterFatigue(), + ) + put( + path = "/diminished", + body = engine.putCharacterDiminished(), + ) + put( + path = "/alteration", + body = engine.putCharacterAlteration(), + ) + } } route(path = "/campaign") { get( path = "", body = engine.getCampaign(), ) - put( - path = "/toggleAlteration", - body = engine.putToggleAlteration(), - ) route(path = "/character") { put( - path = "/update", + path = "/add", body = engine.putCampaignCharacter(), ) delete( @@ -154,12 +184,12 @@ class LocalServer { } route(path = "/npc") { put( - path = "/update", + path = "/add", body = engine.putCampaignNpc(), ) delete( path = "/delete", - body = engine.deleteCampaignNpc(), + body = engine.removeCampaignNpc(), ) } put( diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/alteration/GET_Alteration.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/alteration/GET_Alteration.kt new file mode 100644 index 0000000..0414d46 --- /dev/null +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/alteration/GET_Alteration.kt @@ -0,0 +1,29 @@ +package com.pixelized.server.lwa.server.rest.alteration + +import com.pixelized.server.lwa.server.Engine +import com.pixelized.server.lwa.utils.extentions.alterationId +import io.ktor.http.HttpStatusCode +import io.ktor.server.response.respond +import io.ktor.server.response.respondText + +fun Engine.getAlteration(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { + return { + try { + // get the query parameter + val alterationId = call.queryParameters.alterationId + // get the alteration of the given id. + val alteration = alterationService + .alteration(alterationId = alterationId) + ?: error("Alteration with id:$alterationId not found.") + // send it back to the user. + call.respond( + message = alteration, + ) + } catch (exception: Exception) { + call.respondText( + text = exception.localizedMessage, + status = HttpStatusCode.UnprocessableEntity, + ) + } + } +} \ No newline at end of file diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/alteration/GET_Alterations.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/alteration/GET_Alterations.kt index 885d4e3..43316d2 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/alteration/GET_Alterations.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/alteration/GET_Alterations.kt @@ -5,6 +5,8 @@ import io.ktor.server.response.respond fun Engine.getAlterations(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { return { - call.respond(alterationService.alterations()) + call.respond( + message = alterationService.alterations(), + ) } } \ No newline at end of file diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/DELETE_Campaign_character.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/DELETE_Campaign_Character.kt similarity index 59% rename from server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/DELETE_Campaign_character.kt rename to server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/DELETE_Campaign_Character.kt index a6d17d1..42bf910 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/DELETE_Campaign_character.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/DELETE_Campaign_Character.kt @@ -1,8 +1,8 @@ package com.pixelized.server.lwa.server.rest.campaign import com.pixelized.server.lwa.server.Engine -import com.pixelized.server.lwa.utils.extentions.characterInstanceId -import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation +import com.pixelized.server.lwa.utils.extentions.characterSheetId +import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent import io.ktor.http.HttpStatusCode import io.ktor.server.response.respondText @@ -10,21 +10,24 @@ fun Engine.removeCampaignCharacter(): suspend io.ktor.server.routing.RoutingCont return { try { // get the query parameter - val characterInstanceId = call.queryParameters.characterInstanceId + val characterSheetId = call.queryParameters.characterSheetId // remove the character form the party - val updated = campaignService.removeCharacter(characterInstanceId = characterInstanceId) + val updated = campaignService.removeCharacter( + characterSheetId = characterSheetId, + ) // error case - if (!updated) { - error("Unexpected error when removing character (id:$characterInstanceId) from party.") + if (updated.not()) { + error("Unexpected error when removing character (characterSheetId:$characterSheetId) from party.") } // API & WebSocket responses call.respondText( - text = "$HttpStatusCode.Accepted", - status = HttpStatusCode.Accepted, + text = "${HttpStatusCode.OK}", + status = HttpStatusCode.OK, ) webSocket.emit( - RestSynchronisation.Campaign( + value = CampaignEvent.CharacterRemoved( timestamp = System.currentTimeMillis(), + characterSheetId = characterSheetId, ) ) } catch (exception: Exception) { diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/DELETE_Campaign_npc.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/DELETE_Campaign_Npc.kt similarity index 59% rename from server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/DELETE_Campaign_npc.kt rename to server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/DELETE_Campaign_Npc.kt index 967edb6..1bf91b7 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/DELETE_Campaign_npc.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/DELETE_Campaign_Npc.kt @@ -1,29 +1,29 @@ package com.pixelized.server.lwa.server.rest.campaign import com.pixelized.server.lwa.server.Engine -import com.pixelized.server.lwa.utils.extentions.characterInstanceId -import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation +import com.pixelized.server.lwa.utils.extentions.characterSheetId +import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent import io.ktor.http.HttpStatusCode import io.ktor.server.response.respondText -fun Engine.deleteCampaignNpc(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { +fun Engine.removeCampaignNpc(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { return { try { // get the query parameter - val characterInstanceId = call.queryParameters.characterInstanceId + val characterSheetId = call.queryParameters.characterSheetId // remove the character form the party - val updated = campaignService.removeNpc(npcInstanceId = characterInstanceId) + val updated = campaignService.removeNpc(characterSheetId = characterSheetId) // error case - if (!updated) { - error("Unexpected error when removing character (id:$characterInstanceId) from npcs.") + if (updated.not()) { + error("Unexpected error when removing character (characterSheetId:$characterSheetId) from npcs.") } // API & WebSocket responses call.respondText( - text = "$HttpStatusCode.Accepted", - status = HttpStatusCode.Accepted, + text = "${HttpStatusCode.OK}", + status = HttpStatusCode.OK, ) webSocket.emit( - RestSynchronisation.Campaign( + value = CampaignEvent.UpdateScene( timestamp = System.currentTimeMillis(), ) ) diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/GET_Campaign.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/GET_Campaign.kt index 8dc0403..13bf259 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/GET_Campaign.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/GET_Campaign.kt @@ -5,6 +5,8 @@ import io.ktor.server.response.respond fun Engine.getCampaign(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { return { - call.respond(campaignService.campaignJson()) + call.respond( + message = campaignService.campaignJson(), + ) } } \ No newline at end of file diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_Character.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_Character.kt new file mode 100644 index 0000000..1c5a381 --- /dev/null +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_Character.kt @@ -0,0 +1,38 @@ +package com.pixelized.server.lwa.server.rest.campaign + +import com.pixelized.server.lwa.server.Engine +import com.pixelized.server.lwa.utils.extentions.characterSheetId +import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent +import io.ktor.http.HttpStatusCode +import io.ktor.server.response.respondText + +fun Engine.putCampaignCharacter(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { + return { + try { + // get the query parameter + val characterSheetId = call.queryParameters.characterSheetId + // add the character to the party. + val update = campaignService.addCharacter(characterSheetId = characterSheetId) + // error case + if (update.not()) { + error("Unexpected error occurred when the character instance was added to the party") + } + // API & WebSocket responses. + call.respondText( + text = "Character $characterSheetId successfully added to the party", + status = HttpStatusCode.OK, + ) + webSocket.emit( + value = CampaignEvent.CharacterAdded( + timestamp = System.currentTimeMillis(), + characterSheetId = characterSheetId, + ) + ) + } catch (exception: Exception) { + call.respondText( + text = "${exception.message}", + status = HttpStatusCode.UnprocessableEntity, + ) + } + } +} \ No newline at end of file diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_Npc.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_Npc.kt new file mode 100644 index 0000000..d9d31aa --- /dev/null +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_Npc.kt @@ -0,0 +1,38 @@ +package com.pixelized.server.lwa.server.rest.campaign + +import com.pixelized.server.lwa.server.Engine +import com.pixelized.server.lwa.utils.extentions.characterSheetId +import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent +import io.ktor.http.HttpStatusCode +import io.ktor.server.response.respondText + +fun Engine.putCampaignNpc(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { + return { + try { + // get the query parameter + val characterSheetId = call.queryParameters.characterSheetId + // add the character to the npcs. + val update = campaignService.addNpc(characterSheetId = characterSheetId) + // error case + if (update.not()) { + error("Unexpected error occurred when the character instance was added to the npcs") + } + // API & WebSocket responses. + call.respondText( + text = "Character $characterSheetId successfully added to the npcs", + status = HttpStatusCode.OK, + ) + webSocket.emit( + value = CampaignEvent.NpcAdded( + timestamp = System.currentTimeMillis(), + characterSheetId = characterSheetId, + ) + ) + } catch (exception: Exception) { + call.respondText( + text = "${exception.message}", + status = HttpStatusCode.UnprocessableEntity, + ) + } + } +} \ No newline at end of file diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_Scene_Name.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_Scene_Name.kt index 1a73d35..fe6d506 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_Scene_Name.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_Scene_Name.kt @@ -1,34 +1,40 @@ package com.pixelized.server.lwa.server.rest.campaign import com.pixelized.server.lwa.server.Engine -import com.pixelized.shared.lwa.model.campaign.CampaignJsonV1 -import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation +import com.pixelized.shared.lwa.model.campaign.CampaignJsonV2 +import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent import io.ktor.http.HttpStatusCode import io.ktor.server.request.receive import io.ktor.server.response.respondText fun Engine.putCampaignScene(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { return { - val form = call.receive() - - val scene = campaignJsonFactory.convertFromJson(json = form) - - val updated = campaignService.setScene(scene = scene) - - val code = when (updated) { - true -> HttpStatusCode.Accepted - else -> HttpStatusCode.UnprocessableEntity - } - - call.respondText( - text = "$code", - status = code, - ) - - webSocket.emit( - RestSynchronisation.Campaign( - timestamp = System.currentTimeMillis(), + try { + // Get the scene json from the body of the request + val form = call.receive() + // convert the scene into the a usable data model. + val scene = campaignJsonFactory.convertFromJson(json = form) + // update the campaign. + val updated = campaignService.setScene(scene = scene) + // error case + if (updated.not()) { + error("Unexpected error when updating the scene.") + } + // API & WebSocket responses + call.respondText( + text = "${HttpStatusCode.OK}", + status = HttpStatusCode.OK, ) - ) + webSocket.emit( + value = CampaignEvent.UpdateScene( + timestamp = System.currentTimeMillis(), + ) + ) + } catch (exception: Exception) { + call.respondText( + text = exception.localizedMessage, + status = HttpStatusCode.UnprocessableEntity, + ) + } } } \ No newline at end of file diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_character.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_character.kt deleted file mode 100644 index e98ade9..0000000 --- a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_character.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.pixelized.server.lwa.server.rest.campaign - -import com.pixelized.server.lwa.server.Engine -import com.pixelized.server.lwa.utils.extentions.characterSheetId -import com.pixelized.shared.lwa.model.campaign.Campaign -import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation -import io.ktor.http.HttpStatusCode -import io.ktor.server.response.respondText - -fun Engine.putCampaignCharacter(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { - return { - try { - // get the query parameter - val characterSheetId = call.queryParameters.characterSheetId - // check if the character is already in the party. - val instanceId = campaignService.campaign().characters.keys - .firstOrNull { key -> key.characterSheetId == characterSheetId } - // handle the error case. - if (instanceId != null) { - error("Character (characterSheetId:$characterSheetId) Already in party") - } - // create the instance id for the character. - val id = Campaign.CharacterInstance.Id( - prefix = Campaign.CharacterInstance.Id.PLAYER, - characterSheetId = characterSheetId, - instanceId = 0, - ) - // add the character to the party. - if (campaignService.addCharacter(id).not()) { - error("Unexpected error occurred when the character instance was added to the party") - } - // API & WebSocket responses. - call.respondText( - text = "Character $characterSheetId successfully added to the party", - status = HttpStatusCode.Accepted, - ) - webSocket.emit( - RestSynchronisation.Campaign( - timestamp = System.currentTimeMillis(), - ) - ) - } catch (exception: Exception) { - call.run { - respondText( - text = "${exception.message}", - status = HttpStatusCode.UnprocessableEntity, - ) - } - } - } -} \ No newline at end of file diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_npc.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_npc.kt deleted file mode 100644 index 1a58990..0000000 --- a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_Campaign_npc.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.pixelized.server.lwa.server.rest.campaign - -import com.pixelized.server.lwa.server.Engine -import com.pixelized.server.lwa.utils.extentions.characterSheetId -import com.pixelized.shared.lwa.model.campaign.Campaign -import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation -import io.ktor.http.HttpStatusCode -import io.ktor.server.response.respondText - -fun Engine.putCampaignNpc(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { - return { - try { - // get the query parameter - val characterSheetId = call.queryParameters.characterSheetId - // compute the npc id base on similar character sheets. - val instanceId = campaignService.campaign().npcs.keys - .filter { it.characterSheetId == characterSheetId } - .reduceOrNull { acc, id -> - if (acc.instanceId < id.instanceId) { - id - } else { - acc - } - } - // create the instance id for the character. - val id = Campaign.CharacterInstance.Id( - prefix = Campaign.CharacterInstance.Id.NPC, - characterSheetId = characterSheetId, - instanceId = instanceId?.let { it.instanceId + 1 } ?: 0, - ) - // add the character to the npcs. - if (campaignService.addNpc(id).not()) { - error("Unexpected error occurred when the character instance was added to the npcs") - } - // API & WebSocket responses. - call.respondText( - text = "Character $characterSheetId successfully added to the npcs", - status = HttpStatusCode.Accepted, - ) - webSocket.emit( - RestSynchronisation.Campaign( - timestamp = System.currentTimeMillis(), - ) - ) - } catch (exception: Exception) { - call.run { - respondText( - text = "${exception.message}", - status = HttpStatusCode.UnprocessableEntity, - ) - } - } - } -} \ No newline at end of file diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_ToggleAlteration.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_ToggleAlteration.kt deleted file mode 100644 index 89b85ec..0000000 --- a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/campaign/PUT_ToggleAlteration.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.pixelized.server.lwa.server.rest.campaign - -import com.pixelized.server.lwa.server.Engine -import com.pixelized.server.lwa.utils.extentions.characterInstanceId -import com.pixelized.shared.lwa.protocol.websocket.CampaignMessage -import io.ktor.http.HttpStatusCode -import io.ktor.server.request.receive -import io.ktor.server.response.respondText - -fun Engine.putToggleAlteration(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { - return { - try { - // get the query parameter - val characterInstanceId = call.queryParameters.characterInstanceId - - // fetch the query parameters - val alterationId = call.receive() - - // Update the alteration - campaignService.toggleAlteration( - characterInstanceId = characterInstanceId, - alterationId = alterationId, - ) - // build the Http response & send it - call.respondText( - text = "$HttpStatusCode.Accepted", - status = HttpStatusCode.Accepted, - ) - - val isAlterationActive = campaignService.campaign() - .instances[characterInstanceId] - ?.alterations - ?.contains(alterationId) - ?: false - - // share the modification to all client through the websocket. - webSocket.emit( - CampaignMessage.ToggleActiveAlteration( - timestamp = System.currentTimeMillis(), - prefix = characterInstanceId.prefix, - characterSheetId = characterInstanceId.characterSheetId, - instanceId = characterInstanceId.instanceId, - alterationId = alterationId, - active = isAlterationActive, - ) - ) - } catch (exception: Exception) { - call.respondText( - text = exception.localizedMessage, - status = HttpStatusCode.UnprocessableEntity, - ) - } - } -} \ No newline at end of file diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/DELETE_Character.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/DELETE_Character.kt index 033ec74..a9e7ab7 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/DELETE_Character.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/DELETE_Character.kt @@ -2,7 +2,7 @@ package com.pixelized.server.lwa.server.rest.character import com.pixelized.server.lwa.server.Engine import com.pixelized.server.lwa.utils.extentions.characterSheetId -import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation +import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation import io.ktor.http.HttpStatusCode import io.ktor.server.response.respondText @@ -12,7 +12,9 @@ fun Engine.deleteCharacter(): suspend io.ktor.server.routing.RoutingContext.() - val deleted = characterService.deleteCharacterSheet( characterSheetId = characterSheetId - ) && campaignService.removeInstance( + ) + // Remove the character fom the campaign if needed. + campaignService.removeInstance( characterSheetId = characterSheetId, ) @@ -22,7 +24,7 @@ fun Engine.deleteCharacter(): suspend io.ktor.server.routing.RoutingContext.() - status = HttpStatusCode.OK, ) webSocket.emit( - RestSynchronisation.CharacterSheetDelete( + value = ApiSynchronisation.CharacterSheetDelete( timestamp = System.currentTimeMillis(), characterSheetId = characterSheetId, ), diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/GET_Character.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/GET_Character.kt index f6124ec..3bc8428 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/GET_Character.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/GET_Character.kt @@ -8,12 +8,18 @@ import io.ktor.server.response.respondText fun Engine.getCharacter(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { return { - val id = call.queryParameters.characterSheetId - val body = characterService.characterSheet(id) - - if (body != null) { - call.respond(body) - } else { + try { + // get the query parameter + val characterSheetId = call.queryParameters.characterSheetId + // get the character sheet of the given id. + val characterSheet = characterService + .characterSheet(characterSheetId = characterSheetId) + ?: error("CharacterSheet with id:$characterSheetId not found.") + // send it back to the user. + call.respond( + message = characterSheet, + ) + } catch (exception: Exception) { call.respondText( text = "${HttpStatusCode.UnprocessableEntity}", status = HttpStatusCode.UnprocessableEntity diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/GET_Characters.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/GET_Characters.kt index 0198dc0..ea5417d 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/GET_Characters.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/GET_Characters.kt @@ -5,6 +5,8 @@ import io.ktor.server.response.respond fun Engine.getCharacters(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { return { - call.respond(characterService.characters()) + call.respond( + message = characterService.characters(), + ) } } \ No newline at end of file diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character.kt index 044b994..e521ca5 100644 --- a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character.kt +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character.kt @@ -2,26 +2,33 @@ package com.pixelized.server.lwa.server.rest.character import com.pixelized.server.lwa.server.Engine import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJson -import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation +import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation import io.ktor.http.HttpStatusCode import io.ktor.server.request.receive import io.ktor.server.response.respondText fun Engine.putCharacter(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { return { - val form = call.receive() - characterService.updateCharacterSheet( - character = form - ) - call.respondText( - text = "${HttpStatusCode.OK}", - status = HttpStatusCode.OK - ) - webSocket.emit( - RestSynchronisation.CharacterSheetUpdate( - timestamp = System.currentTimeMillis(), - characterSheetId = form.id, - ), - ) + try { + val form = call.receive() + characterService.updateCharacterSheet( + character = form, + ) + call.respondText( + text = "${HttpStatusCode.OK}", + status = HttpStatusCode.OK, + ) + webSocket.emit( + value = ApiSynchronisation.CharacterSheetUpdate( + timestamp = System.currentTimeMillis(), + characterSheetId = form.id, + ), + ) + } catch (exception: Exception) { + call.respondText( + text = "${HttpStatusCode.UnprocessableEntity}", + status = HttpStatusCode.UnprocessableEntity, + ) + } } } \ No newline at end of file diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character_Alteration.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character_Alteration.kt new file mode 100644 index 0000000..b4fd0fa --- /dev/null +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character_Alteration.kt @@ -0,0 +1,44 @@ +package com.pixelized.server.lwa.server.rest.character + +import com.pixelized.server.lwa.server.Engine +import com.pixelized.server.lwa.utils.extentions.alterationId +import com.pixelized.server.lwa.utils.extentions.characterSheetId +import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent +import io.ktor.http.HttpStatusCode +import io.ktor.server.response.respondText + +fun Engine.putCharacterAlteration(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { + return { + try { + // get the query parameter + val characterSheetId = call.queryParameters.characterSheetId + val alterationId = call.queryParameters.alterationId + val active = call.queryParameters["active"]?.toBooleanStrictOrNull() + ?: error("Missing active parameter.") + // Update the character damage + characterService.updateAlteration( + characterSheetId = characterSheetId, + alterationId = alterationId, + active = active + ) + // API & WebSocket responses. + call.respondText( + text = "${HttpStatusCode.OK}", + status = HttpStatusCode.OK, + ) + webSocket.emit( + value = CharacterSheetEvent.UpdateAlteration( + timestamp = System.currentTimeMillis(), + characterSheetId = characterSheetId, + alterationId = alterationId, + active = active, + ) + ) + } catch (exception: Exception) { + call.respondText( + text = "${HttpStatusCode.UnprocessableEntity}", + status = HttpStatusCode.UnprocessableEntity, + ) + } + } +} \ No newline at end of file diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character_Damage.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character_Damage.kt new file mode 100644 index 0000000..193dc8d --- /dev/null +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character_Damage.kt @@ -0,0 +1,40 @@ +package com.pixelized.server.lwa.server.rest.character + +import com.pixelized.server.lwa.server.Engine +import com.pixelized.server.lwa.utils.extentions.characterSheetId +import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent +import io.ktor.http.HttpStatusCode +import io.ktor.server.response.respondText + +fun Engine.putCharacterDamage(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { + return { + try { + // get the query parameter + val characterSheetId = call.queryParameters.characterSheetId + val damage = call.queryParameters["damage"]?.toIntOrNull() + ?: error("Missing damage parameter.") + // Update the character damage + characterService.updateDamage( + characterSheetId = characterSheetId, + damage = damage + ) + // API & WebSocket responses. + call.respondText( + text = "${HttpStatusCode.OK}", + status = HttpStatusCode.OK, + ) + webSocket.emit( + value = CharacterSheetEvent.UpdateDamage( + timestamp = System.currentTimeMillis(), + characterSheetId = characterSheetId, + damage = damage, + ) + ) + } catch (exception: Exception) { + call.respondText( + text = "${HttpStatusCode.UnprocessableEntity}", + status = HttpStatusCode.UnprocessableEntity, + ) + } + } +} \ No newline at end of file diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character_Diminished.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character_Diminished.kt new file mode 100644 index 0000000..fc44ae9 --- /dev/null +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character_Diminished.kt @@ -0,0 +1,40 @@ +package com.pixelized.server.lwa.server.rest.character + +import com.pixelized.server.lwa.server.Engine +import com.pixelized.server.lwa.utils.extentions.characterSheetId +import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent +import io.ktor.http.HttpStatusCode +import io.ktor.server.response.respondText + +fun Engine.putCharacterDiminished(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { + return { + try { + // get the query parameter + val characterSheetId = call.queryParameters.characterSheetId + val diminished = call.queryParameters["diminished"]?.toIntOrNull() + ?: error("Missing diminished parameter.") + // Update the character damage + characterService.updateDiminished( + characterSheetId = characterSheetId, + diminished = diminished + ) + // API & WebSocket responses. + call.respondText( + text = "${HttpStatusCode.OK}", + status = HttpStatusCode.OK, + ) + webSocket.emit( + value = CharacterSheetEvent.UpdateDiminished( + timestamp = System.currentTimeMillis(), + characterSheetId = characterSheetId, + diminished = diminished, + ) + ) + } catch (exception: Exception) { + call.respondText( + text = "${HttpStatusCode.UnprocessableEntity}", + status = HttpStatusCode.UnprocessableEntity, + ) + } + } +} \ No newline at end of file diff --git a/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character_Fatigue.kt b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character_Fatigue.kt new file mode 100644 index 0000000..9afd591 --- /dev/null +++ b/server/src/main/kotlin/com/pixelized/server/lwa/server/rest/character/PUT_Character_Fatigue.kt @@ -0,0 +1,40 @@ +package com.pixelized.server.lwa.server.rest.character + +import com.pixelized.server.lwa.server.Engine +import com.pixelized.server.lwa.utils.extentions.characterSheetId +import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent +import io.ktor.http.HttpStatusCode +import io.ktor.server.response.respondText + +fun Engine.putCharacterFatigue(): suspend io.ktor.server.routing.RoutingContext.() -> Unit { + return { + try { + // get the query parameter + val characterSheetId = call.queryParameters.characterSheetId + val fatigue = call.queryParameters["fatigue"]?.toIntOrNull() + ?: error("Missing fatigue parameter.") + // Update the character damage + characterService.updateFatigue( + characterSheetId = characterSheetId, + fatigue = fatigue + ) + // API & WebSocket responses. + call.respondText( + text = "${HttpStatusCode.OK}", + status = HttpStatusCode.OK, + ) + webSocket.emit( + value = CharacterSheetEvent.UpdateFatigue( + timestamp = System.currentTimeMillis(), + characterSheetId = characterSheetId, + fatigue = fatigue, + ) + ) + } catch (exception: Exception) { + call.respondText( + text = "${HttpStatusCode.UnprocessableEntity}", + status = HttpStatusCode.UnprocessableEntity, + ) + } + } +} \ No newline at end of file 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 fd90995..ef7f6da 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 @@ -1,20 +1,9 @@ package com.pixelized.server.lwa.utils.extentions -import com.pixelized.shared.lwa.model.campaign.Campaign import io.ktor.http.Parameters -val Parameters.characterInstanceId: Campaign.CharacterInstance.Id - get() = Campaign.CharacterInstance.Id( - characterSheetId = characterSheetId, - instanceId = instanceId, - prefix = prefix, - ) - val Parameters.characterSheetId - get() = this["characterSheetId"] ?: error("Missing character sheet id.") + get() = this["characterSheetId"] ?: error("Missing characterSheetId parameter.") -val Parameters.instanceId: Int - get() = this["instanceId"]?.toIntOrNull() ?: error("Missing character instance id.") - -val Parameters.prefix: Char - get() = this["prefix"]?.get(0) ?: error("Missing character prefix.") +val Parameters.alterationId + get() = this["alterationId"] ?: error("Missing alterationId parameter.") \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/Module.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/Module.kt index 4a94907..e4203b0 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/Module.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/Module.kt @@ -4,11 +4,12 @@ import com.pixelized.shared.lwa.model.AlteredCharacterSheetFactory import com.pixelized.shared.lwa.model.alteration.AlterationJsonFactory import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonV1Factory -import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJsonFactory +import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonV2Factory +import com.pixelized.shared.lwa.model.characterSheet.factory.CharacterSheetJsonFactory +import com.pixelized.shared.lwa.model.characterSheet.factory.CharacterSheetJsonV1Factory import com.pixelized.shared.lwa.parser.dice.DiceParser import com.pixelized.shared.lwa.parser.expression.ExpressionParser import com.pixelized.shared.lwa.parser.word.WordParser -import com.pixelized.shared.lwa.usecase.CampaignUseCase import com.pixelized.shared.lwa.usecase.CharacterSheetUseCase import com.pixelized.shared.lwa.usecase.ExpressionUseCase import com.pixelized.shared.lwa.usecase.RollUseCase @@ -38,8 +39,10 @@ val toolsDependencies val factoryDependencies get() = module { factoryOf(::CharacterSheetJsonFactory) + factoryOf(::CharacterSheetJsonV1Factory) factoryOf(::CampaignJsonFactory) factoryOf(::CampaignJsonV1Factory) + factoryOf(::CampaignJsonV2Factory) factoryOf(::AlteredCharacterSheetFactory) factoryOf(::AlterationJsonFactory) } @@ -54,7 +57,6 @@ val parserDependencies val useCaseDependencies get() = module { factoryOf(::CharacterSheetUseCase) - factoryOf(::CampaignUseCase) factoryOf(::SkillStepUseCase) factoryOf(::RollUseCase) factoryOf(::ExpressionUseCase) diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/alteration/AlterationJson.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/alteration/AlterationJson.kt index aeeb465..c28daa5 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/alteration/AlterationJson.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/alteration/AlterationJson.kt @@ -3,4 +3,6 @@ package com.pixelized.shared.lwa.model.alteration import kotlinx.serialization.Serializable @Serializable -sealed interface AlterationJson \ No newline at end of file +sealed interface AlterationJson { + val id: String +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/alteration/AlterationJsonV1.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/alteration/AlterationJsonV1.kt index dbdd13a..1132588 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/alteration/AlterationJsonV1.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/alteration/AlterationJsonV1.kt @@ -4,7 +4,7 @@ import kotlinx.serialization.Serializable @Serializable data class AlterationJsonV1( - val id: String, + override val id: String, val metadata: AlterationMetadataJsonV1, val fields: List, ) : AlterationJson { diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/Campaign.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/Campaign.kt index f3c7b8a..2633b1c 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/Campaign.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/Campaign.kt @@ -1,53 +1,13 @@ package com.pixelized.shared.lwa.model.campaign data class Campaign( - val characters: Map, - val npcs: Map, + val characters: Set, + val npcs: Set, val scene: Scene, val options: Options, ) { val instances = characters + npcs - data class CharacterInstance( - val characteristic: Map, - val alterations: List, - val diminished: Int, - ) { - data class Id( - val prefix: Char, - val characterSheetId: String, - val instanceId: Int, - ) { - fun equals( - prefix: Char, - characterSheetId: String?, - instanceId: Int?, - ): Boolean { - return this.prefix == prefix && - this.characterSheetId == characterSheetId && - this.instanceId == instanceId - } - - companion object { - const val PLAYER = 'c' - const val NPC = 'n' - } - } - - enum class Characteristic { - Damage, - Power, - } - - companion object { - fun empty() = CharacterInstance( - characteristic = emptyMap(), - alterations = emptyList(), - diminished = 0, - ) - } - } - data class Scene( val name: String, ) { @@ -71,28 +31,11 @@ data class Campaign( } companion object { - val EMPTY = Campaign( - characters = emptyMap(), - npcs = emptyMap(), + fun empty() = Campaign( + characters = emptySet(), + npcs = emptySet(), scene = Scene.empty(), options = Options.empty(), ) } -} - -fun Campaign.character(id: Campaign.CharacterInstance.Id): Campaign.CharacterInstance { - return characters[id] ?: Campaign.CharacterInstance.empty() -} - -fun Campaign.npc(id: Campaign.CharacterInstance.Id): Campaign.CharacterInstance { - return npcs[id] ?: Campaign.CharacterInstance.empty() -} - -val Campaign.CharacterInstance.level - get() = characteristic[Campaign.CharacterInstance.Characteristic.Damage] ?: 1 - -val Campaign.CharacterInstance.damage - get() = characteristic[Campaign.CharacterInstance.Characteristic.Damage] ?: 0 - -val Campaign.CharacterInstance.power - get() = characteristic[Campaign.CharacterInstance.Characteristic.Power] ?: 0 \ No newline at end of file +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/CampaignJsonV2.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/CampaignJsonV2.kt new file mode 100644 index 0000000..26d0b9c --- /dev/null +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/CampaignJsonV2.kt @@ -0,0 +1,23 @@ +package com.pixelized.shared.lwa.model.campaign + +import kotlinx.serialization.Serializable + +@Serializable +data class CampaignJsonV2( + val characters: Set, + val npcs: Set, + val scene: SceneJsonV2?, + val options: OptionsJsonV2?, +) : CampaignJson { + + @Serializable + data class SceneJsonV2( + val name: String, + ) : CampaignJson.SceneJson + + @Serializable + data class OptionsJsonV2( + val showPlayer: Boolean, + val showNpcs: Boolean, + ) : CampaignJson.OptionJson +} diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/factory/CampaignJsonFactory.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/factory/CampaignJsonFactory.kt index 1c7b203..ddda468 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/factory/CampaignJsonFactory.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/factory/CampaignJsonFactory.kt @@ -3,38 +3,18 @@ package com.pixelized.shared.lwa.model.campaign.factory import com.pixelized.shared.lwa.model.campaign.Campaign import com.pixelized.shared.lwa.model.campaign.CampaignJson import com.pixelized.shared.lwa.model.campaign.CampaignJsonV1 +import com.pixelized.shared.lwa.model.campaign.CampaignJsonV2 class CampaignJsonFactory( private val v1: CampaignJsonV1Factory, + private val v2: CampaignJsonV2Factory, ) { - fun characterInstanceIdFromJson( - characterInstanceIdJson: String, - ): Campaign.CharacterInstance.Id { - return v1.convertFromV1(characterInstanceIdJson) - } - fun convertFromJson( json: CampaignJson, ): Campaign { return when (json) { - is CampaignJsonV1 -> v1.convertFromV1(campaignJson = json) - } - } - - fun convertFromJson( - json: CampaignJson.CharacterInstanceJson, - ): Campaign.CharacterInstance { - return when (json) { - is CampaignJsonV1.CharacterInstanceJsonV1 -> v1.convertFromV1(characterInstanceJson = json) - } - } - - fun convertFromJson( - json: CampaignJson.CharacterInstanceJson.CharacteristicJson, - ): Campaign.CharacterInstance.Characteristic { - return when (json) { - CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Damage -> Campaign.CharacterInstance.Characteristic.Damage - CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Power -> Campaign.CharacterInstance.Characteristic.Power + is CampaignJsonV1 -> v1.convertFromJson(campaignJson = json) + is CampaignJsonV2 -> v2.convertFromJson(campaignJson = json) } } @@ -42,62 +22,26 @@ class CampaignJsonFactory( json: CampaignJson.SceneJson, ): Campaign.Scene { return when (json) { - is CampaignJsonV1.SceneJsonV1 -> v1.convertFromV1(sceneJson = json) + is CampaignJsonV1.SceneJsonV1 -> v1.convertFromJson(sceneJson = json) + is CampaignJsonV2.SceneJsonV2 -> v2.convertFromJson(sceneJson = json) } } + // Json conversion. + fun convertToJson( - data: Campaign, + campaign: Campaign, ): CampaignJson { - return CampaignJsonV1( - characters = data.characters - .map { convertToJson(id = it.key) to convertToJson(data = it.value) } - .toMap(), - npcs = data.npcs - .map { convertToJson(id = it.key) to convertToJson(data = it.value) } - .toMap(), - scene = CampaignJsonV1.SceneJsonV1( - name = data.scene.name + return CampaignJsonV2( + characters = campaign.characters, + npcs = campaign.npcs, + scene = CampaignJsonV2.SceneJsonV2( + name = campaign.scene.name, ), - options = CampaignJsonV1.OptionsJsonV1( - showPlayer = data.options.showParty, - showNpcs = data.options.showNpcs, + options = CampaignJsonV2.OptionsJsonV2( + showPlayer = campaign.options.showParty, + showNpcs = campaign.options.showNpcs, ) ) } - - fun convertToJson( - id: Campaign.CharacterInstance.Id, - ): String { - return "${id.prefix}-${String.format("%03d", id.instanceId)}-${id.characterSheetId}" - } - - fun convertToJson( - data: Campaign.CharacterInstance, - ): CampaignJsonV1.CharacterInstanceJsonV1 { - return CampaignJsonV1.CharacterInstanceJsonV1( - characteristic = data.characteristic - .map { char -> convertToJson(characteristic = char.key) to char.value } - .toMap(), - alterations = data.alterations, - diminished = data.diminished, - ) - } - - fun convertToJson( - characteristic: Campaign.CharacterInstance.Characteristic, - ): CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1 { - return when (characteristic) { - Campaign.CharacterInstance.Characteristic.Damage -> CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Damage - Campaign.CharacterInstance.Characteristic.Power -> CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Power - } - } - - fun convertToJson( - scene: Campaign.Scene, - ): CampaignJsonV1.SceneJsonV1 { - return CampaignJsonV1.SceneJsonV1( - name = scene.name, - ) - } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/factory/CampaignJsonV1Factory.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/factory/CampaignJsonV1Factory.kt index 887d7f6..3053833 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/factory/CampaignJsonV1Factory.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/factory/CampaignJsonV1Factory.kt @@ -5,65 +5,25 @@ import com.pixelized.shared.lwa.model.campaign.CampaignJsonV1 class CampaignJsonV1Factory { - fun convertFromV1( + fun convertFromJson( campaignJson: CampaignJsonV1, ): Campaign { + // Characters & npcs were previously a map of a CharacterInstanceID ( Char + instance number + Character Sheet Id) + // Map to an instance object with data related to said instance (HP / PP / alterations etc.) + // This have been deleted and moved to the CharacterSheet. return Campaign( - characters = campaignJson.characters - .map { - val key = convertFromV1(characterInstanceIdJson = it.key) - val instance = convertFromV1(characterInstanceJson = it.value) - key to instance - } - .toMap(), - npcs = campaignJson.npcs - .map { - val key = convertFromV1(characterInstanceIdJson = it.key) - val instance = convertFromV1(characterInstanceJson = it.value) - key to instance - } - .toMap(), + characters = emptySet(), + npcs = emptySet(), scene = campaignJson.scene - ?.let { convertFromV1(it) } + ?.let { convertFromJson(it) } ?: Campaign.Scene.empty(), options = campaignJson.options - ?.let { convertFromV1(it) } - ?:Campaign.Options.empty() + ?.let { convertFromJson(it) } + ?: Campaign.Options.empty() ) } - fun convertFromV1( - characterInstanceIdJson: String, - ): Campaign.CharacterInstance.Id { - return Campaign.CharacterInstance.Id( - prefix = characterInstanceIdJson.take(1)[0], - characterSheetId = characterInstanceIdJson.drop(2 + 4), // drop the char then the - then the first 3 number then the - - instanceId = characterInstanceIdJson.drop(2).take(3).toIntOrNull() ?: 0, - ) - } - - fun convertFromV1( - characterInstanceJson: CampaignJsonV1.CharacterInstanceJsonV1, - ): Campaign.CharacterInstance { - return Campaign.CharacterInstance( - characteristic = characterInstanceJson.characteristic - .mapKeys { convertFromV1(characteristicJson = it.key) } - .toMap(), - alterations = characterInstanceJson.alterations ?: emptyList(), - diminished = characterInstanceJson.diminished ?: 0, - ) - } - - fun convertFromV1( - characteristicJson: CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1, - ): Campaign.CharacterInstance.Characteristic { - return when (characteristicJson) { - CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Damage -> Campaign.CharacterInstance.Characteristic.Damage - CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Power -> Campaign.CharacterInstance.Characteristic.Power - } - } - - fun convertFromV1( + fun convertFromJson( sceneJson: CampaignJsonV1.SceneJsonV1, ): Campaign.Scene { return Campaign.Scene( @@ -71,7 +31,7 @@ class CampaignJsonV1Factory { ) } - fun convertFromV1( + fun convertFromJson( optionsJson: CampaignJsonV1.OptionsJsonV1, ): Campaign.Options { return Campaign.Options( diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/factory/CampaignJsonV2Factory.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/factory/CampaignJsonV2Factory.kt new file mode 100644 index 0000000..40598c2 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/campaign/factory/CampaignJsonV2Factory.kt @@ -0,0 +1,39 @@ +package com.pixelized.shared.lwa.model.campaign.factory + +import com.pixelized.shared.lwa.model.campaign.Campaign +import com.pixelized.shared.lwa.model.campaign.CampaignJsonV2 + +class CampaignJsonV2Factory { + + fun convertFromJson( + campaignJson: CampaignJsonV2, + ): Campaign { + return Campaign( + characters = campaignJson.characters, + npcs = campaignJson.npcs, + scene = campaignJson.scene + ?.let { convertFromJson(it) } + ?: Campaign.Scene.empty(), + options = campaignJson.options + ?.let { convertFromJson(it) } + ?: Campaign.Options.empty() + ) + } + + fun convertFromJson( + sceneJson: CampaignJsonV2.SceneJsonV2, + ): Campaign.Scene { + return Campaign.Scene( + name = sceneJson.name + ) + } + + fun convertFromJson( + optionsJson: CampaignJsonV2.OptionsJsonV2, + ): Campaign.Options { + return Campaign.Options( + showParty = optionsJson.showPlayer, + showNpcs = optionsJson.showNpcs + ) + } +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheet.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheet.kt index 97652c9..bd6b4c3 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheet.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheet.kt @@ -15,9 +15,11 @@ data class CharacterSheet( val intelligence: Int, val power: Int, val charisma: Int, - // sub characteristics - val movement: Int, - val armor: Int, + // alterations + val damage: Int, // damage taken on the hp pool + val fatigue: Int, // damage taken on the pp pool + val diminished: Int, + val alterations: List, // skills val commonSkills: List, val specialSkills: List, diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheetJson.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheetJson.kt index 0055d07..e9b41c8 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheetJson.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheetJson.kt @@ -5,4 +5,5 @@ import kotlinx.serialization.Serializable @Serializable sealed interface CharacterSheetJson { val id: String + val name: String } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheetJsonV1.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheetJsonV1.kt index e4eb980..c72e69a 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheetJsonV1.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheetJsonV1.kt @@ -5,7 +5,7 @@ import kotlinx.serialization.Serializable @Serializable data class CharacterSheetJsonV1( override val id: String, - val name: String, + override val name: String, val portrait: String?, val thumbnail: String?, val level: Int, @@ -18,13 +18,16 @@ data class CharacterSheetJsonV1( val intelligence: Int, val power: Int, val charisma: Int, + // alterations + val damage: Int?, + val fatigue: Int?, + val diminished: Int?, + val alterations: List?, // skills val skills: List, - // occupations val occupations: List, - // magic skill val magics: List, - // attack + // actions val rolls: List, ) : CharacterSheetJson { diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheetJsonFactory.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/factory/CharacterSheetJsonFactory.kt similarity index 54% rename from shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheetJsonFactory.kt rename to shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/factory/CharacterSheetJsonFactory.kt index 3aa28f4..d17eb51 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/CharacterSheetJsonFactory.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/factory/CharacterSheetJsonFactory.kt @@ -1,108 +1,24 @@ -package com.pixelized.shared.lwa.model.characterSheet +package com.pixelized.shared.lwa.model.characterSheet.factory +import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet +import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJson +import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJsonV1 +import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetPreview import com.pixelized.shared.lwa.protocol.rest.CharacterPreviewJson -import com.pixelized.shared.lwa.usecase.CharacterSheetUseCase class CharacterSheetJsonFactory( - private val characterSheetUseCase: CharacterSheetUseCase, + private val v1: CharacterSheetJsonV1Factory, ) { suspend fun convertFromJson( json: CharacterSheetJson, ): CharacterSheet { return when (json) { - is CharacterSheetJsonV1 -> convertFromV1(json = json) + is CharacterSheetJsonV1 -> v1.convertFromJson(json = json) } } - suspend fun convertFromJson( - json: CharacterPreviewJson, - ): CharacterSheetPreview { - return CharacterSheetPreview( - characterSheetId = json.id, - name = json.name, - level = json.level, - ) - } - - private suspend fun convertFromV1( - json: CharacterSheetJsonV1, - ): CharacterSheet = characterSheetUseCase.run { - CharacterSheet( - id = json.id, - name = json.name, - portrait = json.portrait, - thumbnail = json.thumbnail, - level = json.level, - shouldLevelUp = json.shouldLevelUp ?: false, - strength = json.strength, - dexterity = json.dexterity, - constitution = json.constitution, - height = json.height, - intelligence = json.intelligence, - power = json.power, - charisma = json.charisma, - movement = movement(), - armor = armor(), - commonSkills = json.skills.map { - CharacterSheet.Skill( - id = it.id, - label = it.label, - description = it.description, - base = it.base, - bonus = it.bonus, - level = it.level, - occupation = it.occupation, - used = it.used, - ) - }, - specialSkills = json.occupations.map { - CharacterSheet.Skill( - id = it.id, - label = it.label, - description = it.description, - base = it.base, - bonus = it.bonus, - level = it.level, - occupation = it.occupation, - used = it.used, - ) - }, - magicSkills = json.magics.map { - CharacterSheet.Skill( - id = it.id, - label = it.label, - description = it.description, - base = it.base, - bonus = it.bonus, - level = it.level, - occupation = it.occupation, - used = it.used, - ) - }, - actions = json.rolls.map { - CharacterSheet.Roll( - id = it.id, - label = it.label, - description = it.description, - canBeCritical = it.canBeCritical, - roll = it.roll, - ) - }, - ) - } - - fun convertToPreviewJson( - sheet: CharacterSheet, - ): CharacterPreviewJson { - return CharacterPreviewJson( - id = sheet.id, - portrait = sheet.portrait, - thumbnail = sheet.thumbnail, - name = sheet.name, - level = sheet.level, - ) - } + // Json conversion. fun convertToJson( sheet: CharacterSheet, @@ -121,6 +37,10 @@ class CharacterSheetJsonFactory( intelligence = sheet.intelligence, power = sheet.power, charisma = sheet.charisma, + damage = sheet.damage, + fatigue = sheet.fatigue, + diminished = sheet.diminished, + alterations = sheet.alterations, skills = sheet.commonSkills.map { CharacterSheetJsonV1.Skill( id = it.id, @@ -169,4 +89,26 @@ class CharacterSheetJsonFactory( ) return json } + + suspend fun convertFromJson( + json: CharacterPreviewJson, + ): CharacterSheetPreview { + return CharacterSheetPreview( + characterSheetId = json.id, + name = json.name, + level = json.level, + ) + } + + fun convertToPreviewJson( + sheet: CharacterSheet, + ): CharacterPreviewJson { + return CharacterPreviewJson( + id = sheet.id, + portrait = sheet.portrait, + thumbnail = sheet.thumbnail, + name = sheet.name, + level = sheet.level, + ) + } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/factory/CharacterSheetJsonV1Factory.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/factory/CharacterSheetJsonV1Factory.kt new file mode 100644 index 0000000..069b551 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/model/characterSheet/factory/CharacterSheetJsonV1Factory.kt @@ -0,0 +1,78 @@ +package com.pixelized.shared.lwa.model.characterSheet.factory + +import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet +import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJsonV1 +import com.pixelized.shared.lwa.usecase.CharacterSheetUseCase + +class CharacterSheetJsonV1Factory( + private val characterSheetUseCase: CharacterSheetUseCase, +) { + suspend fun convertFromJson( + json: CharacterSheetJsonV1, + ): CharacterSheet = characterSheetUseCase.run { + CharacterSheet( + id = json.id, + name = json.name, + portrait = json.portrait, + thumbnail = json.thumbnail, + level = json.level, + shouldLevelUp = json.shouldLevelUp ?: false, + strength = json.strength, + dexterity = json.dexterity, + constitution = json.constitution, + height = json.height, + intelligence = json.intelligence, + power = json.power, + charisma = json.charisma, + damage = json.damage ?: 0, + fatigue = json.fatigue ?: 0, + diminished = json.diminished ?: 0, + alterations = json.alterations ?: emptyList(), + commonSkills = json.skills.map { + CharacterSheet.Skill( + id = it.id, + label = it.label, + description = it.description, + base = it.base, + bonus = it.bonus, + level = it.level, + occupation = it.occupation, + used = it.used, + ) + }, + specialSkills = json.occupations.map { + CharacterSheet.Skill( + id = it.id, + label = it.label, + description = it.description, + base = it.base, + bonus = it.bonus, + level = it.level, + occupation = it.occupation, + used = it.used, + ) + }, + magicSkills = json.magics.map { + CharacterSheet.Skill( + id = it.id, + label = it.label, + description = it.description, + base = it.base, + bonus = it.bonus, + level = it.level, + occupation = it.occupation, + used = it.used, + ) + }, + actions = json.rolls.map { + CharacterSheet.Roll( + id = it.id, + label = it.label, + description = it.description, + canBeCritical = it.canBeCritical, + roll = it.roll, + ) + }, + ) + } +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/RestSynchronisation.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/ApiSynchronisation.kt similarity index 59% rename from shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/RestSynchronisation.kt rename to shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/ApiSynchronisation.kt index 98e0209..6fecdd1 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/RestSynchronisation.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/ApiSynchronisation.kt @@ -3,22 +3,17 @@ package com.pixelized.shared.lwa.protocol.websocket import kotlinx.serialization.Serializable @Serializable -sealed class RestSynchronisation : SocketMessage { - - @Serializable - data class CharacterSheetUpdate( - override val timestamp: Long, - override val characterSheetId: String, - ) : RestSynchronisation(), CharacterSheetIdMessage +sealed interface ApiSynchronisation : SocketMessage { @Serializable data class CharacterSheetDelete( override val timestamp: Long, override val characterSheetId: String, - ) : RestSynchronisation(), CharacterSheetIdMessage + ) : ApiSynchronisation, CharacterSheetIdMessage @Serializable - data class Campaign( + data class CharacterSheetUpdate( override val timestamp: Long, - ) : RestSynchronisation() + override val characterSheetId: String, + ) : ApiSynchronisation, CharacterSheetIdMessage } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CampaignEvent.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CampaignEvent.kt new file mode 100644 index 0000000..02c3ee5 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CampaignEvent.kt @@ -0,0 +1,37 @@ +package com.pixelized.shared.lwa.protocol.websocket + +import kotlinx.serialization.Serializable + +@Serializable +sealed interface CampaignEvent : SocketMessage { + + // TODO Will probably be moved when the scene become more complex, (should already actually) + @Serializable + data class UpdateScene( + override val timestamp: Long, + ) : CampaignEvent + + @Serializable + data class CharacterRemoved( + override val timestamp: Long, + override val characterSheetId: String, + ) : CampaignEvent, CharacterSheetIdMessage + + @Serializable + data class CharacterAdded( + override val timestamp: Long, + override val characterSheetId: String, + ) : CampaignEvent, CharacterSheetIdMessage + + @Serializable + data class NpcRemoved( + override val timestamp: Long, + override val characterSheetId: String, + ) : CampaignEvent, CharacterSheetIdMessage + + @Serializable + data class NpcAdded( + override val timestamp: Long, + override val characterSheetId: String, + ) : CampaignEvent, CharacterSheetIdMessage +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CampaignMessage.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CampaignMessage.kt deleted file mode 100644 index d3acc73..0000000 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CampaignMessage.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.pixelized.shared.lwa.protocol.websocket - -import com.pixelized.shared.lwa.model.campaign.CampaignJsonV1 -import kotlinx.serialization.Serializable - -@Serializable -sealed interface CampaignMessage : SocketMessage, CharacterInstanceIdMessage { - override val prefix: Char - override val characterSheetId: String - override val instanceId: Int - - @Serializable - data class UpdateCharacteristic( - override val timestamp: Long, - override val prefix: Char, - override val characterSheetId: String, - override val instanceId: Int, - val characteristic: CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1, - val oldValue: Int, - val newValue: Int, - ) : CampaignMessage - - @Serializable - data class UpdateDiminished( - override val timestamp: Long, - override val prefix: Char, - override val characterSheetId: String, - override val instanceId: Int, - val diminished: Int, - ) : CampaignMessage - - @Serializable - data class ToggleActiveAlteration( - override val timestamp: Long, - override val characterSheetId: String, - override val prefix: Char, - override val instanceId: Int, - val alterationId: String, - val active: Boolean, - ) : CampaignMessage, CharacterInstanceIdMessage -} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CharacterSheetEvent.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CharacterSheetEvent.kt new file mode 100644 index 0000000..9b9e099 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CharacterSheetEvent.kt @@ -0,0 +1,44 @@ +package com.pixelized.shared.lwa.protocol.websocket + +import kotlinx.serialization.Serializable + +@Serializable +sealed interface CharacterSheetEvent : SocketMessage, CharacterSheetIdMessage { + + @Serializable + data class UpdateDamage( + override val characterSheetId: String, + override val timestamp: Long, + val damage: Int, + ) : CharacterSheetEvent + + @Serializable + data class UpdateFatigue( + override val characterSheetId: String, + override val timestamp: Long, + val fatigue: Int, + ) : CharacterSheetEvent + + @Serializable + data class UpdateDiminished( + override val timestamp: Long, + override val characterSheetId: String, + val diminished: Int, + ) : CharacterSheetEvent + + @Serializable + data class UpdateAlteration( + override val timestamp: Long, + override val characterSheetId: String, + val alterationId: String, + val active: Boolean, + ) : CharacterSheetEvent + + @Serializable + data class UpdateSkillUsageEvent( + override val timestamp: Long, + override val characterSheetId: String, + val skillId: String, + val used: Boolean, + ) : CharacterSheetEvent +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CharacterInstanceIdMessage.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CharacterSheetIdMessage.kt similarity index 51% rename from shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CharacterInstanceIdMessage.kt rename to shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CharacterSheetIdMessage.kt index 9b1984b..5e77765 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CharacterInstanceIdMessage.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/CharacterSheetIdMessage.kt @@ -5,11 +5,4 @@ import kotlinx.serialization.Serializable @Serializable sealed interface CharacterSheetIdMessage { val characterSheetId: String -} - -@Serializable -sealed interface CharacterInstanceIdMessage : CharacterSheetIdMessage { - override val characterSheetId: String - val prefix: Char - val instanceId: Int } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/GameEvent.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/GameEvent.kt deleted file mode 100644 index a59c2cd..0000000 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/GameEvent.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.pixelized.shared.lwa.protocol.websocket - -import kotlinx.serialization.Serializable - -@Serializable -sealed interface GameEvent : SocketMessage { - - @Serializable - data class DisplayPortrait( - override val timestamp: Long, - val characterSheetId: String?, - ) : GameEvent -} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/GameMasterEvent.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/GameMasterEvent.kt index 85b4ec6..1596a6e 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/GameMasterEvent.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/GameMasterEvent.kt @@ -14,4 +14,10 @@ sealed interface GameMasterEvent : SocketMessage { class TogglePlayer( override val timestamp: Long, ) : GameMasterEvent + + @Serializable + data class DisplayPortrait( + override val timestamp: Long, + val characterSheetId: String?, // nullable so no CharacterSheetIdMessage implementation + ) : GameMasterEvent } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/RollMessage.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/RollEvent.kt similarity index 80% rename from shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/RollMessage.kt rename to shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/RollEvent.kt index 821b696..c3ed529 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/RollMessage.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/RollEvent.kt @@ -3,19 +3,17 @@ package com.pixelized.shared.lwa.protocol.websocket import kotlinx.serialization.Serializable @Serializable -data class RollMessage( +data class RollEvent( override val timestamp: Long, + override val characterSheetId: String, val uuid: String, - val prefix: Char, - val characterSheetId: String, - val instanceId: Int?, val skillLabel: String, val rollValue: Int, val resultLabel: String? = null, val rollDifficulty: String? = null, val rollSuccessLimit: Int? = null, val critical: Critical? = null, -) : SocketMessage { +) : SocketMessage, CharacterSheetIdMessage { enum class Critical { CRITICAL_SUCCESS, SPECIAL_SUCCESS, diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/UpdateSkillUsageMessage.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/UpdateSkillUsageMessage.kt deleted file mode 100644 index 67a4c01..0000000 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/protocol/websocket/UpdateSkillUsageMessage.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.pixelized.shared.lwa.protocol.websocket - -import kotlinx.serialization.Serializable - -@Serializable -data class UpdateSkillUsageMessage( - override val timestamp: Long, - override val characterSheetId: String, - val skillId: String, - val used: Boolean, -) : SocketMessage, CharacterSheetIdMessage \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/usecase/CampaignUseCase.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/usecase/CampaignUseCase.kt deleted file mode 100644 index 5d172a9..0000000 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/usecase/CampaignUseCase.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.pixelized.shared.lwa.usecase - -import com.pixelized.shared.lwa.model.campaign.Campaign - -class CampaignUseCase { - - fun updateCharacteristic( - instance: Campaign.CharacterInstance, - characteristic: Campaign.CharacterInstance.Characteristic, - value: Int, - ): Campaign.CharacterInstance { - return instance.copy( - characteristic = instance.characteristic.toMutableMap().also { - it[characteristic] = value - } - ) - } - - fun updateDiminished( - instance: Campaign.CharacterInstance, - diminished: Int, - ): Campaign.CharacterInstance { - return instance.copy( - diminished = diminished, - ) - } -} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/usecase/CharacterSheetUseCase.kt b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/usecase/CharacterSheetUseCase.kt index 1ac6f92..88152ac 100644 --- a/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/usecase/CharacterSheetUseCase.kt +++ b/shared/src/commonMain/kotlin/com/pixelized/shared/lwa/usecase/CharacterSheetUseCase.kt @@ -1,6 +1,5 @@ package com.pixelized.shared.lwa.usecase -import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet import kotlin.math.ceil import kotlin.math.max @@ -76,51 +75,4 @@ class CharacterSheetUseCase { fun hpGrow(constitution: Int): Int { return (constitution / 3) } - - // Update character sheet. - - fun updateLevel( - character: CharacterSheet, - level: Int, - ): CharacterSheet { - return character.copy( - level = level, - ) - } - - fun updateSkillLevel( - character: CharacterSheet, - skillId: String, - level: Int, - ): CharacterSheet { - return character.copy( - commonSkills = character.commonSkills.map { skill -> - skill.takeIf { skill.id == skillId }?.copy(level = level) ?: skill - }, - specialSkills = character.specialSkills.map { skill -> - skill.takeIf { skill.id == skillId }?.copy(level = level) ?: skill - }, - magicSkills = character.magicSkills.map { skill -> - skill.takeIf { skill.id == skillId }?.copy(level = level) ?: skill - }, - ) - } - - fun updateSkillUsage( - character: CharacterSheet, - skillId: String, - used: Boolean, - ): CharacterSheet { - return character.copy( - commonSkills = character.commonSkills.map { skill -> - skill.takeIf { skill.id == skillId }?.copy(used = used) ?: skill - }, - specialSkills = character.specialSkills.map { skill -> - skill.takeIf { skill.id == skillId }?.copy(used = used) ?: skill - }, - magicSkills = character.magicSkills.map { skill -> - skill.takeIf { skill.id == skillId }?.copy(used = used) ?: skill - }, - ) - } }