Add character portrait display feature.

This commit is contained in:
Thomas Andres Gomez 2025-03-20 23:22:56 +01:00
parent 50c34c8520
commit 67e154ed4a
18 changed files with 214 additions and 20 deletions

View file

@ -52,11 +52,11 @@ import com.pixelized.desktop.lwa.ui.navigation.window.destination.RollHistoryWin
import com.pixelized.desktop.lwa.ui.navigation.window.rememberMaxWindowHeight import com.pixelized.desktop.lwa.ui.navigation.window.rememberMaxWindowHeight
import com.pixelized.desktop.lwa.ui.overlay.roll.RollHostState import com.pixelized.desktop.lwa.ui.overlay.roll.RollHostState
import com.pixelized.desktop.lwa.ui.overlay.roll.RollOverlay import com.pixelized.desktop.lwa.ui.overlay.roll.RollOverlay
import com.pixelized.desktop.lwa.ui.screen.campaign.player.CharacterPortraitDefault
import com.pixelized.desktop.lwa.ui.screen.characterSheet.CharacterSheetMainNavHost import com.pixelized.desktop.lwa.ui.screen.characterSheet.CharacterSheetMainNavHost
import com.pixelized.desktop.lwa.ui.screen.gamemaster.GameMasterScreen import com.pixelized.desktop.lwa.ui.screen.gamemaster.GameMasterScreen
import com.pixelized.desktop.lwa.ui.screen.rollhistory.RollHistoryPage import com.pixelized.desktop.lwa.ui.screen.rollhistory.RollHistoryPage
import com.pixelized.desktop.lwa.ui.theme.LwaTheme import com.pixelized.desktop.lwa.ui.theme.LwaTheme
import com.pixelized.desktop.lwa.ui.theme.lwa
import com.pixelized.desktop.lwa.utils.InstallCoil import com.pixelized.desktop.lwa.utils.InstallCoil
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -108,7 +108,7 @@ fun ApplicationScope.LwaApplication() {
size = DpSize( size = DpSize(
width = 800.dp, width = 800.dp,
height = min( height = min(
a = 56.dp + CharacterPortraitDefault.size.height * 6 + 8.dp * 7 + 40.dp, a = 56.dp + 128.dp * 6 + 8.dp * 7 + 40.dp, // 128 is the height of a minimized portrait.
b = maxWindowHeight, b = maxWindowHeight,
), ),
), ),

View file

@ -15,6 +15,7 @@ import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
import com.pixelized.desktop.lwa.repository.settings.SettingsStore import com.pixelized.desktop.lwa.repository.settings.SettingsStore
import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterDetailCharacteristicDialogViewModel import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterDetailCharacteristicDialogViewModel
import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogFactory import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogFactory
import com.pixelized.desktop.lwa.ui.overlay.portrait.PortraitOverlayViewModel
import com.pixelized.desktop.lwa.ui.overlay.roll.RollViewModel import com.pixelized.desktop.lwa.ui.overlay.roll.RollViewModel
import com.pixelized.desktop.lwa.ui.screen.campaign.network.NetworkFactory import com.pixelized.desktop.lwa.ui.screen.campaign.network.NetworkFactory
import com.pixelized.desktop.lwa.ui.screen.campaign.network.NetworkViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.network.NetworkViewModel
@ -138,6 +139,7 @@ val viewModelDependencies
viewModelOf(::SettingsViewModel) viewModelOf(::SettingsViewModel)
viewModelOf(::LevelUpViewModel) viewModelOf(::LevelUpViewModel)
viewModelOf(::GameMasterViewModel) viewModelOf(::GameMasterViewModel)
viewModelOf(::PortraitOverlayViewModel)
} }
val useCaseDependencies val useCaseDependencies

View file

@ -59,8 +59,8 @@ class CampaignRepository(
initialValue = campaignFlow.value.character(id = characterInstanceId), initialValue = campaignFlow.value.character(id = characterInstanceId),
) )
} }
@Deprecated(message = "Check if deprecated")
@Deprecated(message = "Check if deprecated")
fun characterInstance( fun characterInstance(
characterInstanceId: Campaign.CharacterInstance.Id, characterInstanceId: Campaign.CharacterInstance.Id,
): Campaign.CharacterInstance { ): Campaign.CharacterInstance {

View file

@ -6,10 +6,10 @@ import com.pixelized.shared.lwa.model.campaign.Campaign
import com.pixelized.shared.lwa.model.campaign.character import com.pixelized.shared.lwa.model.campaign.character
import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory
import com.pixelized.shared.lwa.model.campaign.npc import com.pixelized.shared.lwa.model.campaign.npc
import com.pixelized.shared.lwa.protocol.websocket.SocketMessage
import com.pixelized.shared.lwa.protocol.websocket.CampaignMessage import com.pixelized.shared.lwa.protocol.websocket.CampaignMessage
import com.pixelized.shared.lwa.protocol.websocket.GameMasterEvent import com.pixelized.shared.lwa.protocol.websocket.GameMasterEvent
import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation
import com.pixelized.shared.lwa.protocol.websocket.SocketMessage
import com.pixelized.shared.lwa.usecase.CampaignUseCase import com.pixelized.shared.lwa.usecase.CampaignUseCase
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers

View file

@ -0,0 +1,100 @@
package com.pixelized.desktop.lwa.ui.overlay.portrait
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.FilterQuality
import coil3.compose.AsyncImage
import com.pixelized.desktop.lwa.ui.theme.lwa
import kotlinx.coroutines.launch
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.ic_cancel_24dp
import org.jetbrains.compose.resources.painterResource
import org.koin.compose.viewmodel.koinViewModel
@Composable
fun PortraitOverlay(
modifier: Modifier = Modifier,
viewModel: PortraitOverlayViewModel = koinViewModel(),
) {
val scope = rememberCoroutineScope()
val portrait = viewModel.portrait.collectAsState()
val isGameMaster = viewModel.isGameMaster.collectAsState()
PortraitContent(
modifier = modifier,
portrait = portrait,
isGameMaster = isGameMaster,
onGameMaster = {
scope.launch {
viewModel.dismissPortrait()
}
}
)
}
@Composable
private fun PortraitContent(
modifier: Modifier = Modifier,
portrait: State<String?>,
isGameMaster: State<Boolean>,
onGameMaster: () -> Unit,
) {
AnimatedContent(
modifier = Modifier
.clip(shape = MaterialTheme.lwa.shapes.portrait)
.then(other = modifier),
targetState = portrait.value,
transitionSpec = {
fadeIn() togetherWith fadeOut()
}
) {
when (it) {
null -> Box(
modifier = Modifier.size(MaterialTheme.lwa.size.portrait.maximized)
)
else -> Box(
modifier = Modifier.size(MaterialTheme.lwa.size.portrait.maximized)
) {
AsyncImage(
modifier = Modifier.matchParentSize(),
model = it,
filterQuality = FilterQuality.High,
contentDescription = null
)
AnimatedVisibility(
modifier = Modifier.align(alignment = Alignment.TopEnd),
visible = isGameMaster.value,
enter = fadeIn(),
exit = fadeOut(),
) {
IconButton(
onClick = onGameMaster,
) {
Icon(
painter = painterResource(Res.drawable.ic_cancel_24dp),
tint = MaterialTheme.lwa.colorScheme.base.primary,
contentDescription = null
)
}
}
}
}
}
}

View file

@ -0,0 +1,51 @@
package com.pixelized.desktop.lwa.ui.overlay.portrait
import androidx.lifecycle.ViewModel
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
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.stateIn
class PortraitOverlayViewModel(
private val networkRepository: NetworkRepository,
settingsRepository: SettingsRepository,
characterSheetRepository: CharacterSheetRepository,
) : ViewModel() {
@OptIn(ExperimentalCoroutinesApi::class)
val portrait = networkRepository.data
.mapNotNull { it as? GameEvent.DisplayPortrait }
.flatMapLatest { characterSheetRepository.characterDetailFlow(characterSheetId = it.characterSheetId) }
.map { it?.portrait }
.distinctUntilChanged()
.stateIn(
scope = viewModelScope,
started = SharingStarted.Eagerly,
initialValue = null
)
val isGameMaster = settingsRepository.settingsFlow()
.map { settings -> settings.isGameMaster ?: false }
.stateIn(
scope = viewModelScope,
started = SharingStarted.Eagerly,
initialValue = false
)
suspend fun dismissPortrait() {
networkRepository.share(
GameEvent.DisplayPortrait(
timestamp = System.currentTimeMillis(),
characterSheetId = null,
)
)
}
}

View file

@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.material.Surface import androidx.compose.material.Surface
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -35,6 +36,7 @@ import com.pixelized.desktop.lwa.ui.composable.character.characteristic.Characte
import com.pixelized.desktop.lwa.ui.composable.key.KeyHandler import com.pixelized.desktop.lwa.ui.composable.key.KeyHandler
import com.pixelized.desktop.lwa.ui.navigation.screen.LocalScreenController import com.pixelized.desktop.lwa.ui.navigation.screen.LocalScreenController
import com.pixelized.desktop.lwa.ui.navigation.screen.destination.navigateToLevelScreen import com.pixelized.desktop.lwa.ui.navigation.screen.destination.navigateToLevelScreen
import com.pixelized.desktop.lwa.ui.overlay.portrait.PortraitOverlay
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailPanel import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailPanel
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailViewModel
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDiminishedViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDiminishedViewModel
@ -84,7 +86,14 @@ fun CampaignScreen(
}, },
main = { main = {
Box(
modifier = Modifier.matchParentSize(),
contentAlignment = Alignment.BottomCenter,
) {
PortraitOverlay(
modifier = Modifier.padding(all = 8.dp)
)
}
}, },
chat = { chat = {
CampaignChat( CampaignChat(

View file

@ -54,11 +54,6 @@ import org.jetbrains.compose.resources.painterResource
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@Stable
object CharacterPortraitDefault {
val size = DpSize(96.dp, 128.dp)
}
@Stable @Stable
data class CharacterPortraitUio( data class CharacterPortraitUio(
val id: Campaign.CharacterInstance.Id, val id: Campaign.CharacterInstance.Id,
@ -82,7 +77,7 @@ data class CharacterPortraitUio(
@Composable @Composable
fun CharacterPortrait( fun CharacterPortrait(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
size: DpSize = CharacterPortraitDefault.size, size: DpSize = MaterialTheme.lwa.size.portrait.minimized,
levelUpOffset: Dp = 9.dp, levelUpOffset: Dp = 9.dp,
character: CharacterPortraitUio, character: CharacterPortraitUio,
onCharacter: (id: Campaign.CharacterInstance.Id) -> Unit, onCharacter: (id: Campaign.CharacterInstance.Id) -> Unit,

View file

@ -37,6 +37,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.theme.lwa
import com.pixelized.shared.lwa.model.campaign.Campaign import com.pixelized.shared.lwa.model.campaign.Campaign
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import lwacharactersheet.composeapp.generated.resources.Res import lwacharactersheet.composeapp.generated.resources.Res
@ -61,7 +62,7 @@ data class CharacterPortraitRollAnimation(
@Composable @Composable
fun CharacterPortraitRoll( fun CharacterPortraitRoll(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
size: DpSize = CharacterPortraitDefault.size, size: DpSize = MaterialTheme.lwa.size.portrait.minimized,
value: CharacterPortraitRollUio?, value: CharacterPortraitRollUio?,
onLeftClick: (CharacterPortraitRollUio) -> Unit, onLeftClick: (CharacterPortraitRollUio) -> Unit,
onRightClick: (CharacterPortraitRollUio) -> Unit, onRightClick: (CharacterPortraitRollUio) -> Unit,

View file

@ -10,7 +10,6 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.screen.campaign.player.CharacterPortrait import com.pixelized.desktop.lwa.ui.screen.campaign.player.CharacterPortrait
import com.pixelized.desktop.lwa.ui.screen.campaign.player.CharacterPortraitDefault
import com.pixelized.desktop.lwa.ui.screen.campaign.player.CharacterPortraitRoll import com.pixelized.desktop.lwa.ui.screen.campaign.player.CharacterPortraitRoll
import com.pixelized.shared.lwa.model.campaign.Campaign import com.pixelized.shared.lwa.model.campaign.Campaign
import org.koin.compose.viewmodel.koinViewModel import org.koin.compose.viewmodel.koinViewModel
@ -38,7 +37,6 @@ fun NpcRibbon(
modifier = Modifier.animateItem(), modifier = Modifier.animateItem(),
) { ) {
CharacterPortraitRoll( CharacterPortraitRoll(
size = CharacterPortraitDefault.size,
value = viewModel.roll(characterId = it.id).value, value = viewModel.roll(characterId = it.id).value,
onRightClick = { onRightClick = {
viewModel.onPortraitRollRightClick(characterId = it.characterId) viewModel.onPortraitRollRightClick(characterId = it.characterId)
@ -48,7 +46,6 @@ fun NpcRibbon(
}, },
) )
CharacterPortrait( CharacterPortrait(
size = CharacterPortraitDefault.size,
character = it, character = it,
onCharacter = onCharacter, onCharacter = onCharacter,
onLevelUp = onLevelUp, onLevelUp = onLevelUp,

View file

@ -35,7 +35,6 @@ import androidx.compose.ui.window.WindowState
import com.pixelized.desktop.lwa.ui.navigation.window.LocalWindowState import com.pixelized.desktop.lwa.ui.navigation.window.LocalWindowState
import com.pixelized.desktop.lwa.ui.screen.campaign.CampaignLayoutScope import com.pixelized.desktop.lwa.ui.screen.campaign.CampaignLayoutScope
import com.pixelized.desktop.lwa.ui.screen.campaign.LocalCampaignLayoutScope import com.pixelized.desktop.lwa.ui.screen.campaign.LocalCampaignLayoutScope
import com.pixelized.desktop.lwa.ui.screen.campaign.player.CharacterPortraitDefault
import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.CharacteristicTextMessage import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.CharacteristicTextMessage
import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.CharacteristicTextMessageUio import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.CharacteristicTextMessageUio
import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.DiminishedTextMessage import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.DiminishedTextMessage
@ -90,7 +89,7 @@ fun CampaignChat(
modifier = modifier modifier = modifier
.size( .size(
width = animatedChatWidth.value, width = animatedChatWidth.value,
height = CharacterPortraitDefault.size.height * 2 + 8.dp, height = MaterialTheme.lwa.size.portrait.minimized.height * 2 + 8.dp,
) )
.graphicsLayer { .graphicsLayer {
alpha = chatViewModel.chatAnimatedVisibility.value alpha = chatViewModel.chatAnimatedVisibility.value

View file

@ -9,6 +9,7 @@ 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.Damage
import com.pixelized.shared.lwa.model.campaign.CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Power 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.CampaignMessage
import com.pixelized.shared.lwa.protocol.websocket.GameEvent
import com.pixelized.shared.lwa.protocol.websocket.GameMasterEvent import com.pixelized.shared.lwa.protocol.websocket.GameMasterEvent
import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation
import com.pixelized.shared.lwa.protocol.websocket.RollMessage import com.pixelized.shared.lwa.protocol.websocket.RollMessage
@ -105,6 +106,7 @@ class TextMessageFactory(
is ToggleActiveAlteration -> null is ToggleActiveAlteration -> null
is UpdateSkillUsageMessage -> null is UpdateSkillUsageMessage -> null
is GameMasterEvent -> null is GameMasterEvent -> null
is GameEvent.DisplayPortrait -> null
} }
} }
} }

View file

@ -1,17 +1,25 @@
package com.pixelized.desktop.lwa.ui.screen.gamemaster package com.pixelized.desktop.lwa.ui.screen.gamemaster
import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository 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.desktop.lwa.ui.screen.gamemaster.items.GMCharacterUio.Action
import com.pixelized.shared.lwa.protocol.websocket.GameEvent
class GameMasterActionUseCase( class GameMasterActionUseCase(
private val campaignRepository: CampaignRepository, private val campaignRepository: CampaignRepository,
private val networkRepository: NetworkRepository,
) { ) {
suspend fun handleAction( suspend fun handleAction(
characterSheetId: String, characterSheetId: String,
action: Action, action: Action,
) { ) {
when (action) { when (action) {
Action.DisplayPortrait -> TODO() Action.DisplayPortrait -> networkRepository.share(
GameEvent.DisplayPortrait(
timestamp = System.currentTimeMillis(),
characterSheetId = characterSheetId,
)
)
Action.AddToGroup -> campaignRepository.addCharacter( Action.AddToGroup -> campaignRepository.addCharacter(
characterSheetId = characterSheetId, characterSheetId = characterSheetId,

View file

@ -92,6 +92,7 @@ class GameMasterFactory {
} }
// build the cell action list // build the cell action list
val actions = buildList { val actions = buildList {
add(Action.DisplayPortrait)
add( add(
when (characterInstanceId) { when (characterInstanceId) {
null -> Action.AddToGroup null -> Action.AddToGroup

View file

@ -17,7 +17,6 @@ import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable

View file

@ -9,8 +9,15 @@ import androidx.compose.ui.unit.dp
data class LwaSize( data class LwaSize(
val portrait: Portrait,
val sheet: Sheet, val sheet: Sheet,
) { ) {
@Stable
data class Portrait(
val maximized: DpSize,
val minimized: DpSize,
)
@Stable @Stable
data class Sheet( data class Sheet(
val subCategory: Dp, val subCategory: Dp,
@ -21,12 +28,17 @@ data class LwaSize(
@Composable @Composable
@Stable @Stable
fun lwaSize( fun lwaSize(
portrait: LwaSize.Portrait = LwaSize.Portrait(
minimized = DpSize(width = 96.dp, height = 128.dp),
maximized = DpSize(width = 512.dp, height = 512.dp),
),
sheet: LwaSize.Sheet = LwaSize.Sheet( sheet: LwaSize.Sheet = LwaSize.Sheet(
subCategory = 14.dp, subCategory = 14.dp,
characteristic = DpSize(width = 76.dp, height = 110.dp), characteristic = DpSize(width = 76.dp, height = 110.dp),
), ),
) = remember { ) = remember {
LwaSize( LwaSize(
portrait = portrait,
sheet = sheet, sheet = sheet,
) )
} }

View file

@ -5,11 +5,12 @@ import com.pixelized.server.lwa.model.campaign.CampaignService
import com.pixelized.server.lwa.model.character.CharacterSheetService import com.pixelized.server.lwa.model.character.CharacterSheetService
import com.pixelized.shared.lwa.model.campaign.Campaign import com.pixelized.shared.lwa.model.campaign.Campaign
import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory
import com.pixelized.shared.lwa.protocol.websocket.SocketMessage
import com.pixelized.shared.lwa.protocol.websocket.CampaignMessage import com.pixelized.shared.lwa.protocol.websocket.CampaignMessage
import com.pixelized.shared.lwa.protocol.websocket.GameEvent
import com.pixelized.shared.lwa.protocol.websocket.GameMasterEvent import com.pixelized.shared.lwa.protocol.websocket.GameMasterEvent
import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation import com.pixelized.shared.lwa.protocol.websocket.RestSynchronisation
import com.pixelized.shared.lwa.protocol.websocket.RollMessage import com.pixelized.shared.lwa.protocol.websocket.RollMessage
import com.pixelized.shared.lwa.protocol.websocket.SocketMessage
import com.pixelized.shared.lwa.protocol.websocket.ToggleActiveAlteration import com.pixelized.shared.lwa.protocol.websocket.ToggleActiveAlteration
import com.pixelized.shared.lwa.protocol.websocket.UpdateSkillUsageMessage import com.pixelized.shared.lwa.protocol.websocket.UpdateSkillUsageMessage
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
@ -65,6 +66,10 @@ class Engine(
is GameMasterEvent.TogglePlayer -> campaignService.updateToggleParty() is GameMasterEvent.TogglePlayer -> campaignService.updateToggleParty()
is GameMasterEvent.ToggleNpc -> campaignService.updateToggleNpc() is GameMasterEvent.ToggleNpc -> campaignService.updateToggleNpc()
} }
is GameEvent -> when (message) {
is GameEvent.DisplayPortrait -> Unit // Nothing to do here.
}
} }
} }
} }

View file

@ -0,0 +1,13 @@
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
}