diff --git a/pom.xml b/pom.xml index b656796..e63af11 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ justice-core com.drcorchit - 1.0-SNAPSHOT + 1.0.0 jar justice-core @@ -90,7 +90,7 @@ com.github.DrCorchit justice-utils - 1.1.3 + 1.2.1 org.jetbrains.kotlin diff --git a/src/main/kotlin/com/drcorchit/justice/games/AbstractElement.kt b/src/main/kotlin/com/drcorchit/justice/games/AbstractElement.kt index 8c14dc2..fef4f53 100644 --- a/src/main/kotlin/com/drcorchit/justice/games/AbstractElement.kt +++ b/src/main/kotlin/com/drcorchit/justice/games/AbstractElement.kt @@ -29,7 +29,9 @@ abstract class AbstractElement(private val parent: AbstractMechanic<*>, name: St } override fun sync(info: JsonObject) { - this.info = info.deepCopy() + preSync(info) + this.info = info + postSync(info) touch() } } \ No newline at end of file diff --git a/src/main/kotlin/com/drcorchit/justice/games/AbstractMechanic.kt b/src/main/kotlin/com/drcorchit/justice/games/AbstractMechanic.kt index 40c0124..fbf67d1 100644 --- a/src/main/kotlin/com/drcorchit/justice/games/AbstractMechanic.kt +++ b/src/main/kotlin/com/drcorchit/justice/games/AbstractMechanic.kt @@ -1,7 +1,7 @@ package com.drcorchit.justice.games import com.drcorchit.utils.Logger -import com.drcorchit.utils.json.get +import com.drcorchit.utils.json.getOrDefault import com.google.gson.JsonObject private val log = Logger.getLogger(AbstractMechanic::class.java) @@ -47,6 +47,7 @@ abstract class AbstractMechanic(game: Game, info: JsonObjec val message = "Mechanic info for $name is missing \"elements\". Found keys: ${info.keySet()}" throw IllegalArgumentException(message) } + preSync(info) elementsByName.clear() @@ -59,7 +60,7 @@ abstract class AbstractMechanic(game: Game, info: JsonObjec //Use "key" if present, otherwise default to name val name = eleInfo["name"].asString - val key = eleInfo["key", { nextId() }, { it.asInt }] + val key = eleInfo.getOrDefault("key", { nextId() }, { it.asInt }) var element: T if (has(key)) { @@ -85,6 +86,7 @@ abstract class AbstractMechanic(game: Game, info: JsonObjec //Remove all elements still marked for deletion deleteThese.forEach { elementsById.remove(it.key) } + postSync(info) val message = String.format("Synced AbstractMechanic $name", name) log.info("sync", message) } diff --git a/src/main/kotlin/com/drcorchit/justice/games/GameElement.kt b/src/main/kotlin/com/drcorchit/justice/games/GameElement.kt index 01c1cc9..26c2905 100644 --- a/src/main/kotlin/com/drcorchit/justice/games/GameElement.kt +++ b/src/main/kotlin/com/drcorchit/justice/games/GameElement.kt @@ -5,7 +5,7 @@ import com.drcorchit.utils.normalize import com.google.gson.JsonElement import com.google.gson.JsonObject -interface GameElement { +interface GameElement : Syncable { //The name of the object as seen by the client //The name is encouraged to be unique. It may also change from time to time. fun name(): String @@ -28,8 +28,6 @@ interface GameElement { parent().touch() } - fun sync(info: JsonObject) - //Serializes the object so it can be recreated fun serialize(): JsonElement { return GSON.toJsonTree(this) diff --git a/src/main/kotlin/com/drcorchit/justice/games/GameMechanic.kt b/src/main/kotlin/com/drcorchit/justice/games/GameMechanic.kt index 1c613bf..fa7a986 100644 --- a/src/main/kotlin/com/drcorchit/justice/games/GameMechanic.kt +++ b/src/main/kotlin/com/drcorchit/justice/games/GameMechanic.kt @@ -3,7 +3,7 @@ package com.drcorchit.justice.games import com.drcorchit.utils.json.GSON import com.google.gson.JsonObject -interface GameMechanic : Iterable { +interface GameMechanic : Syncable, Iterable { val name: String get() = javaClass.simpleName val parent: Game @@ -23,8 +23,6 @@ interface GameMechanic : Iterable { //Call this method whenever the mechanic is modified. This should also update lastModified fun touch() - fun sync(info: JsonObject) - fun serialize(): JsonObject { return GSON.toJsonTree(this).asJsonObject } diff --git a/src/main/kotlin/com/drcorchit/justice/games/GridElement.kt b/src/main/kotlin/com/drcorchit/justice/games/GridElement.kt new file mode 100644 index 0000000..5fa1bcc --- /dev/null +++ b/src/main/kotlin/com/drcorchit/justice/games/GridElement.kt @@ -0,0 +1,29 @@ +package com.drcorchit.justice.games + +import com.drcorchit.utils.json.getString +import com.drcorchit.utils.math.Space +import com.google.gson.JsonObject + +abstract class GridElement(val parent: GridMechanic<*>, val coord: Space.Coordinate) : GameElement { + + protected var info = JsonObject() + + override fun name(): String { + return coord.toString() + } + + override fun description(): String { + return info.getString("description", "No description is available.") + } + + override fun parent(): GridMechanic<*> { + return parent + } + + override fun sync(info: JsonObject) { + preSync(info) + this.info = info + postSync(info) + touch() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/drcorchit/justice/games/GridMechanic.kt b/src/main/kotlin/com/drcorchit/justice/games/GridMechanic.kt new file mode 100644 index 0000000..198ac2e --- /dev/null +++ b/src/main/kotlin/com/drcorchit/justice/games/GridMechanic.kt @@ -0,0 +1,106 @@ +package com.drcorchit.justice.games + +import com.drcorchit.utils.Logger +import com.drcorchit.utils.json.getBool +import com.drcorchit.utils.json.getOrDefault +import com.drcorchit.utils.math.Grid +import com.drcorchit.utils.math.Layout +import com.drcorchit.utils.math.Space +import com.google.gson.JsonObject + +private val log = Logger.getLogger(GridMechanic::class.java) + +abstract class GridMechanic(game: Game, info: JsonObject, date: Long) : GameMechanic { + + init { + sync(info) + } + + override val parent: Game = game + + override var lastModified: Long = date + + override var defaultElement: T? = null + + override fun size(): Int { + return grid.space.size + } + + override fun has(key: Any): Boolean { + return if (key is Space.Coordinate) { + grid.space.within(key.x, key.y) + } else throw java.lang.IllegalArgumentException("Supplied key is not a valid coordinate") + } + + override fun get(key: Any): T { + if (key is Space.Coordinate) { + return grid.get(key) + } else { + throw IllegalArgumentException("Supplied key is not a valid coordinate") + } + } + + override fun touch() { + lastModified = System.currentTimeMillis() + } + + final override fun sync(info: JsonObject) { + if (!info.has("elements")) { + val message = "Mechanic info for $name is missing \"elements\". Found keys: ${info.keySet()}" + throw IllegalArgumentException(message) + } + + preSync(info) + + val rows = info.getAsJsonArray("elements").asJsonArray + if (rows.size() != grid.height) { + throw IllegalArgumentException("Incorrect grid size; expected ${grid.height} but got ${rows.size()}") + } + + for ((j, row) in rows.withIndex()) { + val actualWidth = row.asJsonArray.size() + if (actualWidth != grid.width) { + throw java.lang.IllegalArgumentException("Incorrect grid size; expected ${grid.width} but got $actualWidth") + } + for ((i, ele) in row.asJsonArray.withIndex()) { + val eleInfo = ele.asJsonObject + val element: T = grid[i, j] ?: create(grid.space.coordinate(i, j)) + element.sync(eleInfo) + } + } + + defaultElement = + if (info.has("default")) { + val rawKey = info["default"].asJsonPrimitive + if (rawKey.isString) get(rawKey.asString) + else if (rawKey.isNumber) get(rawKey.asInt) + else throw IllegalArgumentException("That type of JsonPrimitive cannot specify a default element") + } else { + null + } + + postSync(info) + val message = String.format("Synced GridMechanic $name", name) + log.info("sync", message) + } + + + override fun iterator(): Iterator { + return grid.iterator() + } + + //New (non-inherited) functionality + + val grid: Grid by lazy { + val w = info["width"].asInt + val h = info["height"].asInt + val wrapH = info.getBool("wrapHoriz", false) + val wrapV = info.getBool("wrapVert", false) + val layout = info.getOrDefault("layout", { Layout.CARTESIAN }, { Layout.valueOf(it.asString) }) + val space = Space(w, h, wrapH, wrapV, layout) + Grid(space) + } + + abstract fun create(coordinate: Space.Coordinate): T + +} \ No newline at end of file diff --git a/src/main/kotlin/com/drcorchit/justice/games/Syncable.kt b/src/main/kotlin/com/drcorchit/justice/games/Syncable.kt new file mode 100644 index 0000000..aba4966 --- /dev/null +++ b/src/main/kotlin/com/drcorchit/justice/games/Syncable.kt @@ -0,0 +1,13 @@ +package com.drcorchit.justice.games + +interface Syncable { + + //This method is not intended to be called except by sync() + fun preSync(info: T) + + fun sync(info: T) + + //This method is not intended to be called except by sync() + fun postSync(info: T) + +} \ No newline at end of file