From 4bb8e2043f2f7a79eafd78d3626c9807b44e62cf Mon Sep 17 00:00:00 2001 From: joffrey-bion Date: Thu, 23 Jan 2020 01:40:57 +0100 Subject: Add kotlinx.serialization support to common model --- build.gradle.kts | 1 + sw-common-model/build.gradle.kts | 6 ++++++ .../kotlin/org/luxons/sevenwonders/model/CustomizableSettings.kt | 2 ++ .../commonMain/kotlin/org/luxons/sevenwonders/model/GameState.kt | 2 ++ .../src/commonMain/kotlin/org/luxons/sevenwonders/model/Moves.kt | 4 ++++ .../commonMain/kotlin/org/luxons/sevenwonders/model/api/Api.kt | 4 ++++ .../kotlin/org/luxons/sevenwonders/model/api/actions/Actions.kt | 7 +++++++ .../kotlin/org/luxons/sevenwonders/model/api/errors/Errors.kt | 6 +++++- .../kotlin/org/luxons/sevenwonders/model/boards/Boards.kt | 6 ++++++ .../kotlin/org/luxons/sevenwonders/model/cards/Cards.kt | 8 +++++++- .../kotlin/org/luxons/sevenwonders/model/resources/Resources.kt | 4 ++++ .../kotlin/org/luxons/sevenwonders/model/wonders/Wonders.kt | 4 ++++ .../src/main/kotlin/org/luxons/sevenwonders/server/Converters.kt | 2 +- 13 files changed, 53 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2bc38baa..5888c082 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,6 +4,7 @@ plugins { kotlin("jvm") version kotlinVersion apply false kotlin("multiplatform") version kotlinVersion apply false kotlin("plugin.spring") version kotlinVersion apply false + id("org.jetbrains.kotlin.plugin.serialization") version kotlinVersion apply false id("org.jlleitschuh.gradle.ktlint") version "9.1.1" apply false } diff --git a/sw-common-model/build.gradle.kts b/sw-common-model/build.gradle.kts index d94559c5..a35ef0ff 100644 --- a/sw-common-model/build.gradle.kts +++ b/sw-common-model/build.gradle.kts @@ -1,8 +1,11 @@ plugins { kotlin("multiplatform") + id("org.jetbrains.kotlin.plugin.serialization") id("org.jlleitschuh.gradle.ktlint") } +val kotlinSerialization = "0.14.0" + kotlin { jvm() js { @@ -12,6 +15,7 @@ kotlin { val commonMain by getting { dependencies { implementation(kotlin("stdlib-common")) + implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$kotlinSerialization") } } val commonTest by getting { @@ -23,6 +27,7 @@ kotlin { val jvmMain by getting { dependencies { implementation(kotlin("stdlib-jdk8")) + implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:$kotlinSerialization") } } val jvmTest by getting { @@ -34,6 +39,7 @@ kotlin { val jsMain by getting { dependencies { implementation(kotlin("stdlib-js")) + implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$kotlinSerialization") } } val jsTest by getting { diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/CustomizableSettings.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/CustomizableSettings.kt index e23a05a1..86a11bc1 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/CustomizableSettings.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/CustomizableSettings.kt @@ -1,7 +1,9 @@ package org.luxons.sevenwonders.model +import kotlinx.serialization.Serializable import kotlin.random.Random +@Serializable data class CustomizableSettings( val randomSeedForTests: Long? = null, val timeLimitInSeconds: Int = 45, diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/GameState.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/GameState.kt index 3de605b2..29423cd7 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/GameState.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/GameState.kt @@ -1,10 +1,12 @@ package org.luxons.sevenwonders.model +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.model.boards.Board import org.luxons.sevenwonders.model.cards.HandRotationDirection typealias Age = Int +@Serializable data class GameState( val boards: List, val currentAge: Age, diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/Moves.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/Moves.kt index 8206ec8d..05b95b17 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/Moves.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/Moves.kt @@ -1,5 +1,6 @@ package org.luxons.sevenwonders.model +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.model.cards.HandCard import org.luxons.sevenwonders.model.cards.TableCard import org.luxons.sevenwonders.model.resources.ResourceTransactions @@ -14,6 +15,7 @@ enum class Action(val message: String) { WAIT("Please wait for other players to perform extra actions.") } +@Serializable data class PlayerTurnInfo( val playerIndex: Int, val table: GameState, @@ -27,6 +29,7 @@ data class PlayerTurnInfo( val wonderBuildability: WonderBuildability = table.boards[playerIndex].wonder.buildability } +@Serializable data class PlayedMove( val playerIndex: Int, val type: MoveType, @@ -34,6 +37,7 @@ data class PlayedMove( val transactions: ResourceTransactions ) +@Serializable data class PlayerMove( val type: MoveType, val cardName: String, diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/Api.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/Api.kt index 04c7ef2f..c691a89d 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/Api.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/Api.kt @@ -1,11 +1,14 @@ package org.luxons.sevenwonders.model.api +import kotlinx.serialization.Serializable + const val SEVEN_WONDERS_WS_ENDPOINT = "/seven-wonders-websocket" enum class State { LOBBY, PLAYING } +@Serializable data class LobbyDTO( val id: Long, val name: String, @@ -14,6 +17,7 @@ data class LobbyDTO( val state: State ) +@Serializable data class PlayerDTO( val username: String, val displayName: String, diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/actions/Actions.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/actions/Actions.kt index 59bc2e5b..773e703f 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/actions/Actions.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/actions/Actions.kt @@ -1,11 +1,13 @@ package org.luxons.sevenwonders.model.api.actions +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.model.CustomizableSettings import org.luxons.sevenwonders.model.PlayerMove /** * The action to choose the player's name. This is the first action that should be called. */ +@Serializable class ChooseNameAction( /** * The display name of the player. May contain spaces and special characters. @@ -16,6 +18,7 @@ class ChooseNameAction( /** * The action to create a game. */ +@Serializable class CreateGameAction( /** * The name of the game to create. @@ -26,6 +29,7 @@ class CreateGameAction( /** * The action to join a game. */ +@Serializable class JoinGameAction( /** * The ID of the game to join. @@ -36,6 +40,7 @@ class JoinGameAction( /** * The action to prepare the next move during a game. */ +@Serializable class PrepareMoveAction( /** * The move to prepare. @@ -47,6 +52,7 @@ class PrepareMoveAction( * The action to update the order of the players around the table. Can only be called in the lobby by the owner of the * game. */ +@Serializable class ReorderPlayersAction( /** * The list of usernames of the players, in the new order. @@ -57,6 +63,7 @@ class ReorderPlayersAction( /** * The action to update the settings of the game. Can only be called in the lobby by the owner of the game. */ +@Serializable class UpdateSettingsAction( /** * The new values for the settings. diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/errors/Errors.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/errors/Errors.kt index f668f020..dea6ce5b 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/errors/Errors.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/errors/Errors.kt @@ -1,9 +1,12 @@ package org.luxons.sevenwonders.model.api.errors +import kotlinx.serialization.Serializable + enum class ErrorType { VALIDATION, CLIENT, SERVER } +@Serializable data class ErrorDTO( val code: String, val message: String, @@ -11,8 +14,9 @@ data class ErrorDTO( val details: List = emptyList() ) +@Serializable data class ValidationErrorDTO( val path: String, val message: String, - val rejectedValue: Any? = null + val rejectedValue: String? = null ) diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/boards/Boards.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/boards/Boards.kt index d06e203d..cdf5b65c 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/boards/Boards.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/boards/Boards.kt @@ -1,10 +1,12 @@ package org.luxons.sevenwonders.model.boards +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.model.cards.TableCard import org.luxons.sevenwonders.model.resources.CountedResource import org.luxons.sevenwonders.model.resources.ResourceType import org.luxons.sevenwonders.model.wonders.ApiWonder +@Serializable data class Board( val playerIndex: Int, val wonder: ApiWonder, @@ -16,22 +18,26 @@ data class Board( val gold: Int ) +@Serializable data class Requirements( val gold: Int = 0, val resources: List = emptyList() ) +@Serializable data class Production( val fixedResources: List, val alternativeResources: Set> ) +@Serializable data class Military( val nbShields: Int, val totalPoints: Int, val nbDefeatTokens: Int ) +@Serializable data class Science( val jokers: Int, val nbWheels: Int, diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/cards/Cards.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/cards/Cards.kt index 11a3e8d8..c538b3bf 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/cards/Cards.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/cards/Cards.kt @@ -1,9 +1,11 @@ package org.luxons.sevenwonders.model.cards +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.model.api.PlayerDTO import org.luxons.sevenwonders.model.boards.Requirements import org.luxons.sevenwonders.model.resources.ResourceTransactions +@Serializable data class TableCard( val name: String, val color: Color, @@ -19,6 +21,7 @@ data class TableCard( * A card with contextual information relative to the hand it is sitting in. The extra information is especially useful * because it frees the client from a painful business logic implementation. */ +@Serializable data class HandCard( val name: String, val color: Color, @@ -30,11 +33,13 @@ data class HandCard( val playability: CardPlayability ) -class PreparedCard( +@Serializable +data class PreparedCard( val player: PlayerDTO, val cardBack: CardBack ) +@Serializable data class CardBack(val image: String) enum class PlayabilityLevel { @@ -60,6 +65,7 @@ enum class Color(val isResource: Boolean) { PURPLE(false) } +@Serializable data class CardPlayability( val isPlayable: Boolean, val isChainable: Boolean = false, diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/resources/Resources.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/resources/Resources.kt index 905f8abf..7368fbd1 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/resources/Resources.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/resources/Resources.kt @@ -1,5 +1,6 @@ package org.luxons.sevenwonders.model.resources +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.model.boards.RelativeBoardPosition enum class ResourceType(val symbol: Char) { @@ -27,16 +28,19 @@ enum class ResourceType(val symbol: Char) { } } +@Serializable data class CountedResource( val count: Int, val type: ResourceType ) +@Serializable enum class Provider(val boardPosition: RelativeBoardPosition) { LEFT_PLAYER(RelativeBoardPosition.LEFT), RIGHT_PLAYER(RelativeBoardPosition.RIGHT) } +@Serializable data class ResourceTransaction(val provider: Provider, val resources: List) typealias ResourceTransactions = Collection diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/wonders/Wonders.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/wonders/Wonders.kt index a6273c5a..e48a37d0 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/wonders/Wonders.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/wonders/Wonders.kt @@ -1,11 +1,13 @@ package org.luxons.sevenwonders.model.wonders +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.model.boards.Requirements import org.luxons.sevenwonders.model.cards.CardBack import org.luxons.sevenwonders.model.cards.PlayabilityLevel import org.luxons.sevenwonders.model.resources.ResourceTransactions import org.luxons.sevenwonders.model.resources.ResourceType +@Serializable data class ApiWonder( val name: String, val initialResource: ResourceType, @@ -15,6 +17,7 @@ data class ApiWonder( val buildability: WonderBuildability ) +@Serializable data class ApiWonderStage( val cardBack: CardBack?, val isBuilt: Boolean, @@ -22,6 +25,7 @@ data class ApiWonderStage( val builtDuringLastMove: Boolean ) +@Serializable data class WonderBuildability( val isBuildable: Boolean, val minPrice: Int = Int.MAX_VALUE, diff --git a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/Converters.kt b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/Converters.kt index 7e1a6fdf..3958260c 100644 --- a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/Converters.kt +++ b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/Converters.kt @@ -7,7 +7,7 @@ import org.springframework.validation.ObjectError fun ObjectError.toDTO() = (this as? FieldError)?.fieldError() ?: objectError() fun FieldError.fieldError(): ValidationErrorDTO = - ValidationErrorDTO("$objectName.$field", "Invalid value for field '$field': $defaultMessage", rejectedValue) + ValidationErrorDTO("$objectName.$field", "Invalid value for field '$field': $defaultMessage", rejectedValue?.toString()) fun ObjectError.objectError(): ValidationErrorDTO = ValidationErrorDTO(objectName, "Invalid value for object '$objectName': $defaultMessage") -- cgit