ReModel of the ActiveAlteration system into the Campaign.
This commit is contained in:
parent
ecb0a6705f
commit
b314a28f82
22 changed files with 254 additions and 317 deletions
|
|
@ -1,56 +1,13 @@
|
|||
package com.pixelized.server.lwa.model.alteration
|
||||
|
||||
import com.pixelized.shared.lwa.model.alteration.AlterationJson
|
||||
import com.pixelized.shared.lwa.model.campaign.Campaign
|
||||
import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory
|
||||
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(
|
||||
private val store: AlterationStore,
|
||||
private val campaignJsonFactory: CampaignJsonFactory,
|
||||
store: AlterationStore,
|
||||
) {
|
||||
private val scope = CoroutineScope(Dispatchers.IO + Job())
|
||||
private val alterations = store.alterationsFlow()
|
||||
private val actives = store.activeFlow()
|
||||
.map { data ->
|
||||
data.mapKeys { it: Map.Entry<String, List<String>> ->
|
||||
campaignJsonFactory.characterInstanceIdFromJson(characterInstanceIdJson = it.key)
|
||||
}
|
||||
}.stateIn(
|
||||
scope = scope,
|
||||
started = SharingStarted.Eagerly,
|
||||
initialValue = emptyMap()
|
||||
)
|
||||
private val alterationsFlow = store.alterationsFlow()
|
||||
|
||||
fun alterations(): List<AlterationJson> {
|
||||
return alterations.value
|
||||
}
|
||||
|
||||
fun active(
|
||||
characterInstanceId: Campaign.CharacterInstance.Id,
|
||||
): List<String> {
|
||||
return actives.value[characterInstanceId] ?: emptyList()
|
||||
}
|
||||
|
||||
fun isAlterationActive(
|
||||
characterInstanceId: Campaign.CharacterInstance.Id,
|
||||
alterationId: String,
|
||||
): Boolean {
|
||||
return actives.value[characterInstanceId]?.contains(alterationId) ?: false
|
||||
}
|
||||
|
||||
suspend fun toggleActiveAlteration(
|
||||
characterInstanceId: Campaign.CharacterInstance.Id,
|
||||
alterationId: String,
|
||||
): Boolean {
|
||||
return store.toggleActiveAlteration(
|
||||
characterInstanceId = characterInstanceId,
|
||||
alterationId = alterationId,
|
||||
)
|
||||
return alterationsFlow.value
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,6 +121,40 @@ 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
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun setScene(
|
||||
scene: Campaign.Scene,
|
||||
): Boolean {
|
||||
|
|
@ -142,8 +176,8 @@ class CampaignService(
|
|||
characteristic: Campaign.CharacterInstance.Characteristic,
|
||||
value: Int,
|
||||
) {
|
||||
when {
|
||||
campaign.characters.containsKey(characterInstanceId) -> {
|
||||
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.
|
||||
|
|
@ -158,7 +192,7 @@ class CampaignService(
|
|||
)
|
||||
}
|
||||
|
||||
campaign.npcs.containsKey(characterInstanceId) -> {
|
||||
Campaign.CharacterInstance.Id.NPC -> {
|
||||
// fetch all the current campaign character
|
||||
val npcs = campaign.npcs.toMutableMap()
|
||||
// update the corresponding character using the use case.
|
||||
|
|
@ -179,8 +213,8 @@ class CampaignService(
|
|||
characterInstanceId: Campaign.CharacterInstance.Id,
|
||||
diminished: Int,
|
||||
) {
|
||||
when {
|
||||
campaign.characters.containsKey(characterInstanceId) -> {
|
||||
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.
|
||||
|
|
@ -194,7 +228,7 @@ class CampaignService(
|
|||
)
|
||||
}
|
||||
|
||||
campaign.npcs.containsKey(characterInstanceId) -> {
|
||||
Campaign.CharacterInstance.Id.NPC -> {
|
||||
// fetch all the current campaign character
|
||||
val npcs = campaign.npcs.toMutableMap()
|
||||
// update the corresponding character using the use case.
|
||||
|
|
@ -210,6 +244,55 @@ class CampaignService(
|
|||
}
|
||||
}
|
||||
|
||||
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(
|
||||
campaign = campaign.copy(
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ class CharacterSheetService(
|
|||
return store.save(sheet = factory.convertFromJson(character))
|
||||
}
|
||||
|
||||
fun deleteCharacterSheet(characterId: String): Boolean {
|
||||
return store.delete(id = characterId)
|
||||
fun deleteCharacterSheet(characterSheetId: String): Boolean {
|
||||
return store.delete(id = characterSheetId)
|
||||
}
|
||||
|
||||
// Data manipulation through WebSocket.
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ 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.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
|
||||
|
||||
|
|
@ -45,6 +45,11 @@ class Engine(
|
|||
characterInstanceId = instanceId,
|
||||
diminished = message.diminished,
|
||||
)
|
||||
|
||||
is ToggleActiveAlteration -> campaignService.toggleAlteration(
|
||||
characterInstanceId = instanceId,
|
||||
alterationId = message.alterationId,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
package com.pixelized.server.lwa.server
|
||||
|
||||
|
||||
import com.pixelized.server.lwa.server.rest.alteration.getActiveAlteration
|
||||
import com.pixelized.server.lwa.server.rest.alteration.getAlteration
|
||||
import com.pixelized.server.lwa.server.rest.alteration.putActiveAlteration
|
||||
import com.pixelized.server.lwa.server.rest.campaign.removeCampaignCharacter
|
||||
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.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
|
||||
|
|
@ -86,7 +85,7 @@ class LocalServer {
|
|||
val frame = Frame.Text(text = data)
|
||||
try {
|
||||
send(frame)
|
||||
} catch (exception : Exception) {
|
||||
} catch (exception: Exception) {
|
||||
// TODO
|
||||
println("WebSocket exception: ${exception.localizedMessage}")
|
||||
}
|
||||
|
|
@ -112,6 +111,10 @@ class LocalServer {
|
|||
}
|
||||
}
|
||||
)
|
||||
get(
|
||||
path = "/alterations",
|
||||
body = engine.getAlterations(),
|
||||
)
|
||||
get(
|
||||
path = "/characters",
|
||||
body = engine.getCharacters(),
|
||||
|
|
@ -135,6 +138,10 @@ class LocalServer {
|
|||
path = "",
|
||||
body = engine.getCampaign(),
|
||||
)
|
||||
put(
|
||||
path = "/toggleAlteration",
|
||||
body = engine.putToggleAlteration(),
|
||||
)
|
||||
route(path = "/character") {
|
||||
put(
|
||||
path = "/update",
|
||||
|
|
@ -160,20 +167,6 @@ class LocalServer {
|
|||
body = engine.putCampaignScene(),
|
||||
)
|
||||
}
|
||||
route(path = "/alterations") {
|
||||
get(
|
||||
path = "",
|
||||
body = engine.getAlteration(),
|
||||
)
|
||||
get(
|
||||
path = "/active",
|
||||
body = engine.getActiveAlteration(),
|
||||
)
|
||||
put(
|
||||
path = "/active/toggle",
|
||||
body = engine.putActiveAlteration(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
package com.pixelized.server.lwa.server.rest.alteration
|
||||
|
||||
import com.pixelized.server.lwa.server.Engine
|
||||
import com.pixelized.server.lwa.utils.extentions.characterInstanceId
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.response.respondText
|
||||
|
||||
fun Engine.getActiveAlteration(): suspend io.ktor.server.routing.RoutingContext.() -> Unit {
|
||||
return {
|
||||
try {
|
||||
// get the query parameter
|
||||
val characterInstanceId = call.queryParameters.characterInstanceId
|
||||
// fetch the data from the service
|
||||
val data = alterationService.active(characterInstanceId = characterInstanceId)
|
||||
// respond to the client.
|
||||
call.respond(data)
|
||||
} catch (exception: Exception) {
|
||||
call.respondText(
|
||||
text = exception.localizedMessage,
|
||||
status = HttpStatusCode.UnprocessableEntity,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ package com.pixelized.server.lwa.server.rest.alteration
|
|||
import com.pixelized.server.lwa.server.Engine
|
||||
import io.ktor.server.response.respond
|
||||
|
||||
fun Engine.getAlteration(): suspend io.ktor.server.routing.RoutingContext.() -> Unit {
|
||||
fun Engine.getAlterations(): suspend io.ktor.server.routing.RoutingContext.() -> Unit {
|
||||
return {
|
||||
call.respond(alterationService.alterations())
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package com.pixelized.server.lwa.server.rest.alteration
|
||||
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.ToggleActiveAlteration
|
||||
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.putActiveAlteration(): suspend io.ktor.server.routing.RoutingContext.() -> Unit {
|
||||
fun Engine.putToggleAlteration(): suspend io.ktor.server.routing.RoutingContext.() -> Unit {
|
||||
return {
|
||||
try {
|
||||
// get the query parameter
|
||||
|
|
@ -17,30 +17,31 @@ fun Engine.putActiveAlteration(): suspend io.ktor.server.routing.RoutingContext.
|
|||
val alterationId = call.receive<String>()
|
||||
|
||||
// Update the alteration
|
||||
val updated = alterationService.toggleActiveAlteration(
|
||||
campaignService.toggleAlteration(
|
||||
characterInstanceId = characterInstanceId,
|
||||
alterationId = alterationId,
|
||||
)
|
||||
if (!updated) {
|
||||
error("Unexpected error occurred when toggling the alteration (id:$alterationId) for the character (id:$characterInstanceId)")
|
||||
}
|
||||
// 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(
|
||||
ToggleActiveAlteration(
|
||||
CampaignMessage.ToggleActiveAlteration(
|
||||
timestamp = System.currentTimeMillis(),
|
||||
prefix = characterInstanceId.prefix,
|
||||
characterSheetId = characterInstanceId.characterSheetId,
|
||||
instanceId = characterInstanceId.instanceId,
|
||||
alterationId = alterationId,
|
||||
active = alterationService.isAlterationActive(
|
||||
characterInstanceId = characterInstanceId,
|
||||
alterationId = alterationId
|
||||
),
|
||||
active = isAlterationActive,
|
||||
)
|
||||
)
|
||||
} catch (exception: Exception) {
|
||||
|
|
@ -11,9 +11,10 @@ fun Engine.deleteCharacter(): suspend io.ktor.server.routing.RoutingContext.() -
|
|||
val characterSheetId = call.parameters.characterSheetId
|
||||
|
||||
val deleted = characterService.deleteCharacterSheet(
|
||||
characterId = characterSheetId
|
||||
characterSheetId = characterSheetId
|
||||
) && campaignService.removeInstance(
|
||||
characterSheetId = characterSheetId,
|
||||
)
|
||||
// TODO campaign & alteration cleanup.
|
||||
|
||||
if (deleted) {
|
||||
call.respondText(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue