Compare commits

...

4 Commits

Author SHA1 Message Date
TeamCity
d667a2f68c ci: bump version to v4.15.0 2025-12-14 14:15:11 +00:00
35f608513d feat: Update routing and websocket configuration for game state management (#109)
Reviewed-on: #109
2025-12-14 15:10:43 +01:00
TeamCity
13038b0cb9 ci: bump version to v4.14.0 2025-12-11 06:13:24 +00:00
b17aae5795 feat: FRO-31 Small backend changes (#108)
Force pushing Janis changes

Co-authored-by: Janis <janis.e.20@gmx.de>
Co-authored-by: Janis <janis-e@gmx.de>
Reviewed-on: #108
Co-authored-by: lq64 <lq@blackhole.local>
Co-committed-by: lq64 <lq@blackhole.local>
2025-12-11 07:10:24 +01:00
10 changed files with 31 additions and 22 deletions

View File

@@ -244,3 +244,13 @@
### Features
* **api:** FRO-14 Create Game ([#107](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/issues/107)) ([bd7a055](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/bd7a055a0944a1c5219f21bb080bf658229f49e9))
## (2025-12-11)
### Features
* FRO-31 Small backend changes ([#108](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/issues/108)) ([b17aae5](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/b17aae5795b35ce3805db87c9bf741a5a96cd5ac))
## (2025-12-14)
### Features
* Update routing and websocket configuration for game state management ([#109](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/issues/109)) ([35f6085](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/35f608513dd80eece46d49b40ecf31c8e915d307))

View File

@@ -34,7 +34,7 @@ class StatusController @Inject()(
Json.obj(
"status" -> "authenticated",
"username" -> user.name,
"inGame" -> "false"
"inGame" -> false
)
)
} else {
@@ -43,7 +43,7 @@ class StatusController @Inject()(
Json.obj(
"status" -> "authenticated",
"username" -> user.name,
"inGame" -> "true",
"inGame" -> true,
"gameId" -> game.id
)
)
@@ -80,7 +80,7 @@ class StatusController @Inject()(
}}
private def getUserFromSession(request: RequestHeader): Option[User] = {
val session = request.cookies.get("sessionId")
val session = request.cookies.get("accessToken")
if (session.isDefined)
return sessionManager.getUserBySession(session.get.value)
None

View File

@@ -21,7 +21,7 @@ class WebsocketController @Inject()(
)(implicit system: ActorSystem, mat: Materializer) extends AbstractController(cc) {
def socket(): WebSocket = WebSocket.accept[String, String] { request =>
val session = request.cookies.get("sessionId")
val session = request.cookies.get("accessToken")
if (session.isEmpty) throw new Exception("No session cookie found")
val userOpt = sessionManger.getUserBySession(session.get.value)
if (userOpt.isEmpty) throw new Exception("Invalid session")

View File

@@ -2,13 +2,13 @@ package dto.subDTO
import de.knockoutwhist.cards.Hand
case class HandDTO(card: List[CardDTO])
case class HandDTO(cards: List[CardDTO])
object HandDTO {
def apply(hand: Hand): HandDTO = {
HandDTO(
card = hand.cards.zipWithIndex.map { case (card, idx) => CardDTO(card, idx) }
cards = hand.cards.zipWithIndex.map { case (card, idx) => CardDTO(card, idx) }
)
}

View File

@@ -8,7 +8,7 @@ object TrickDTO {
def apply(trick: Trick): TrickDTO = {
TrickDTO(
cards = trick.cards.map { case (card, player) => player.id.toString -> CardDTO(card) },
cards = trick.cards.map { case (card, player) => player.name -> CardDTO(card) },
firstCard = trick.firstCard.map(card => CardDTO(card)),
winner = trick.winner.map(player => PlayerDTO(player))
)

View File

@@ -46,13 +46,13 @@ class UserSession(val user: User, val host: Boolean, val gameLobby: GameLobby) e
case "StartGame" =>
gameLobby.startGame(user)
case "PlayCard" =>
val maybeCardIndex: Option[String] = (data \ "cardindex").asOpt[String]
val maybeCardIndex: Option[Int] = (data \ "cardindex").asOpt[Int]
maybeCardIndex match {
case Some(index) =>
val session = gameLobby.getUserSession(user.id)
gameLobby.playCard(session, index.toInt)
gameLobby.playCard(session, index)
case None =>
println("Card Index not found or is not a number.")
println("Card Index not found or is not a number." + data)
}
case "PickTrumpsuit" =>
val maybeSuitIndex: Option[Int] = (data \ "suitIndex").asOpt[Int]
@@ -74,6 +74,10 @@ class UserSession(val user: User, val host: Boolean, val gameLobby: GameLobby) e
}
case "ReturnToLobby" =>
gameLobby.returnToLobby(this)
case "LeaveGame" =>
gameLobby.leaveGame(user.id, false)
case _ =>
println("Unknown event type: " + eventType + " with data: " + data)
}
}

View File

@@ -57,7 +57,8 @@ object WebsocketEventMapper {
Json.obj(
"id" -> ("request-" + java.util.UUID.randomUUID().toString),
"event" -> obj.id,
"state" -> stateToJson(session),
"state" -> session.gameLobby.getLogic.getCurrentState.toString,
"stateData" -> stateToJson(session),
"data" -> data
)
}

View File

@@ -1,11 +1,9 @@
// javascript
let ws = null; // will be created by connectWebSocket()
const pending = new Map(); // id -> { resolve, reject, timer }
const handlers = new Map(); // eventType -> handler(data) -> (value|Promise)
let ws = null;
const pending = new Map();
const handlers = new Map();
let timer = null;
// helper to attach message/error/close handlers to a socket
function setupSocketHandlers(socket) {
socket.onmessage = (event) => {
console.debug("SERVER MESSAGE:", event.data);
@@ -48,7 +46,6 @@ function setupSocketHandlers(socket) {
};
if (!handler) {
// no handler: respond with an error object in data so server can fail it
console.warn("No handler for event:", eventType);
sendResponse({error: "No handler for event: " + eventType});
return;
@@ -91,7 +88,6 @@ function setupSocketHandlers(socket) {
};
}
// connect/disconnect helpers
function connectWebSocket(url = null) {
if (!url) {
const loc = window.location;
@@ -100,7 +96,6 @@ function connectWebSocket(url = null) {
}
if (ws && ws.readyState === WebSocket.OPEN) return Promise.resolve();
if (ws && ws.readyState === WebSocket.CONNECTING) {
// already connecting - return a promise that resolves on open
return new Promise((resolve, reject) => {
const prevOnOpen = ws.onopen;
const prevOnError = ws.onerror;
@@ -121,7 +116,6 @@ function connectWebSocket(url = null) {
return new Promise((resolve, reject) => {
ws.onopen = () => {
console.log("WebSocket connection established!");
// start heartbeat
timer = setInterval(() => {
if (ws && ws.readyState === WebSocket.OPEN) {
sendEventAndWait("ping", {}).then(

View File

@@ -1,3 +1,3 @@
MAJOR=4
MINOR=13
MINOR=15
PATCH=0