Add character portrait display feature.
This commit is contained in:
parent
50c34c8520
commit
67e154ed4a
18 changed files with 214 additions and 20 deletions
|
|
@ -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.overlay.roll.RollHostState
|
||||
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.gamemaster.GameMasterScreen
|
||||
import com.pixelized.desktop.lwa.ui.screen.rollhistory.RollHistoryPage
|
||||
import com.pixelized.desktop.lwa.ui.theme.LwaTheme
|
||||
import com.pixelized.desktop.lwa.ui.theme.lwa
|
||||
import com.pixelized.desktop.lwa.utils.InstallCoil
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
|
@ -108,7 +108,7 @@ fun ApplicationScope.LwaApplication() {
|
|||
size = DpSize(
|
||||
width = 800.dp,
|
||||
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,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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.ui.composable.character.characteristic.CharacterDetailCharacteristicDialogViewModel
|
||||
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.screen.campaign.network.NetworkFactory
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.network.NetworkViewModel
|
||||
|
|
@ -138,6 +139,7 @@ val viewModelDependencies
|
|||
viewModelOf(::SettingsViewModel)
|
||||
viewModelOf(::LevelUpViewModel)
|
||||
viewModelOf(::GameMasterViewModel)
|
||||
viewModelOf(::PortraitOverlayViewModel)
|
||||
}
|
||||
|
||||
val useCaseDependencies
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ class CampaignRepository(
|
|||
initialValue = campaignFlow.value.character(id = characterInstanceId),
|
||||
)
|
||||
}
|
||||
@Deprecated(message = "Check if deprecated")
|
||||
|
||||
@Deprecated(message = "Check if deprecated")
|
||||
fun characterInstance(
|
||||
characterInstanceId: Campaign.CharacterInstance.Id,
|
||||
): Campaign.CharacterInstance {
|
||||
|
|
|
|||
|
|
@ -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.factory.CampaignJsonFactory
|
||||
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.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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column
|
|||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.Surface
|
||||
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.navigation.screen.LocalScreenController
|
||||
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.CharacterDetailViewModel
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDiminishedViewModel
|
||||
|
|
@ -84,7 +86,14 @@ fun CampaignScreen(
|
|||
|
||||
},
|
||||
main = {
|
||||
|
||||
Box(
|
||||
modifier = Modifier.matchParentSize(),
|
||||
contentAlignment = Alignment.BottomCenter,
|
||||
) {
|
||||
PortraitOverlay(
|
||||
modifier = Modifier.padding(all = 8.dp)
|
||||
)
|
||||
}
|
||||
},
|
||||
chat = {
|
||||
CampaignChat(
|
||||
|
|
|
|||
|
|
@ -54,11 +54,6 @@ import org.jetbrains.compose.resources.painterResource
|
|||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
@Stable
|
||||
object CharacterPortraitDefault {
|
||||
val size = DpSize(96.dp, 128.dp)
|
||||
}
|
||||
|
||||
@Stable
|
||||
data class CharacterPortraitUio(
|
||||
val id: Campaign.CharacterInstance.Id,
|
||||
|
|
@ -82,7 +77,7 @@ data class CharacterPortraitUio(
|
|||
@Composable
|
||||
fun CharacterPortrait(
|
||||
modifier: Modifier = Modifier,
|
||||
size: DpSize = CharacterPortraitDefault.size,
|
||||
size: DpSize = MaterialTheme.lwa.size.portrait.minimized,
|
||||
levelUpOffset: Dp = 9.dp,
|
||||
character: CharacterPortraitUio,
|
||||
onCharacter: (id: Campaign.CharacterInstance.Id) -> Unit,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.DpSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.desktop.lwa.ui.theme.lwa
|
||||
import com.pixelized.shared.lwa.model.campaign.Campaign
|
||||
import kotlinx.coroutines.launch
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
|
|
@ -61,7 +62,7 @@ data class CharacterPortraitRollAnimation(
|
|||
@Composable
|
||||
fun CharacterPortraitRoll(
|
||||
modifier: Modifier = Modifier,
|
||||
size: DpSize = CharacterPortraitDefault.size,
|
||||
size: DpSize = MaterialTheme.lwa.size.portrait.minimized,
|
||||
value: CharacterPortraitRollUio?,
|
||||
onLeftClick: (CharacterPortraitRollUio) -> Unit,
|
||||
onRightClick: (CharacterPortraitRollUio) -> Unit,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import androidx.compose.runtime.collectAsState
|
|||
import androidx.compose.ui.Modifier
|
||||
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.CharacterPortraitDefault
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.CharacterPortraitRoll
|
||||
import com.pixelized.shared.lwa.model.campaign.Campaign
|
||||
import org.koin.compose.viewmodel.koinViewModel
|
||||
|
|
@ -38,7 +37,6 @@ fun NpcRibbon(
|
|||
modifier = Modifier.animateItem(),
|
||||
) {
|
||||
CharacterPortraitRoll(
|
||||
size = CharacterPortraitDefault.size,
|
||||
value = viewModel.roll(characterId = it.id).value,
|
||||
onRightClick = {
|
||||
viewModel.onPortraitRollRightClick(characterId = it.characterId)
|
||||
|
|
@ -48,7 +46,6 @@ fun NpcRibbon(
|
|||
},
|
||||
)
|
||||
CharacterPortrait(
|
||||
size = CharacterPortraitDefault.size,
|
||||
character = it,
|
||||
onCharacter = onCharacter,
|
||||
onLevelUp = onLevelUp,
|
||||
|
|
|
|||
|
|
@ -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.screen.campaign.CampaignLayoutScope
|
||||
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.CharacteristicTextMessageUio
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.DiminishedTextMessage
|
||||
|
|
@ -90,7 +89,7 @@ fun CampaignChat(
|
|||
modifier = modifier
|
||||
.size(
|
||||
width = animatedChatWidth.value,
|
||||
height = CharacterPortraitDefault.size.height * 2 + 8.dp,
|
||||
height = MaterialTheme.lwa.size.portrait.minimized.height * 2 + 8.dp,
|
||||
)
|
||||
.graphicsLayer {
|
||||
alpha = chatViewModel.chatAnimatedVisibility.value
|
||||
|
|
|
|||
|
|
@ -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.Power
|
||||
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.RestSynchronisation
|
||||
import com.pixelized.shared.lwa.protocol.websocket.RollMessage
|
||||
|
|
@ -105,6 +106,7 @@ class TextMessageFactory(
|
|||
is ToggleActiveAlteration -> null
|
||||
is UpdateSkillUsageMessage -> null
|
||||
is GameMasterEvent -> null
|
||||
is GameEvent.DisplayPortrait -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,25 @@
|
|||
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,
|
||||
private val networkRepository: NetworkRepository,
|
||||
) {
|
||||
suspend fun handleAction(
|
||||
characterSheetId: String,
|
||||
action: Action,
|
||||
) {
|
||||
when (action) {
|
||||
Action.DisplayPortrait -> TODO()
|
||||
Action.DisplayPortrait -> networkRepository.share(
|
||||
GameEvent.DisplayPortrait(
|
||||
timestamp = System.currentTimeMillis(),
|
||||
characterSheetId = characterSheetId,
|
||||
)
|
||||
)
|
||||
|
||||
Action.AddToGroup -> campaignRepository.addCharacter(
|
||||
characterSheetId = characterSheetId,
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ class GameMasterFactory {
|
|||
}
|
||||
// build the cell action list
|
||||
val actions = buildList {
|
||||
add(Action.DisplayPortrait)
|
||||
add(
|
||||
when (characterInstanceId) {
|
||||
null -> Action.AddToGroup
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import androidx.compose.material.IconButton
|
|||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
|
|
|
|||
|
|
@ -9,8 +9,15 @@ import androidx.compose.ui.unit.dp
|
|||
|
||||
|
||||
data class LwaSize(
|
||||
val portrait: Portrait,
|
||||
val sheet: Sheet,
|
||||
) {
|
||||
@Stable
|
||||
data class Portrait(
|
||||
val maximized: DpSize,
|
||||
val minimized: DpSize,
|
||||
)
|
||||
|
||||
@Stable
|
||||
data class Sheet(
|
||||
val subCategory: Dp,
|
||||
|
|
@ -21,12 +28,17 @@ data class LwaSize(
|
|||
@Composable
|
||||
@Stable
|
||||
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(
|
||||
subCategory = 14.dp,
|
||||
characteristic = DpSize(width = 76.dp, height = 110.dp),
|
||||
),
|
||||
) = remember {
|
||||
LwaSize(
|
||||
portrait = portrait,
|
||||
sheet = sheet,
|
||||
)
|
||||
}
|
||||
|
|
@ -5,11 +5,12 @@ 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.SocketMessage
|
||||
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.RestSynchronisation
|
||||
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.UpdateSkillUsageMessage
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
|
|
@ -65,6 +66,10 @@ class Engine(
|
|||
is GameMasterEvent.TogglePlayer -> campaignService.updateToggleParty()
|
||||
is GameMasterEvent.ToggleNpc -> campaignService.updateToggleNpc()
|
||||
}
|
||||
|
||||
is GameEvent -> when (message) {
|
||||
is GameEvent.DisplayPortrait -> Unit // Nothing to do here.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue