Compare commits
4 Commits
4.18.0
...
edfba93f83
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
edfba93f83 | ||
|
|
4f7eed9ac4 | ||
|
|
ee3f65efd9 | ||
|
|
89d1626bb2 |
@@ -8,6 +8,7 @@ import model.sessions.{PlayerSession, UserSession}
|
|||||||
import play.api.*
|
import play.api.*
|
||||||
import play.api.mvc.*
|
import play.api.mvc.*
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
import javax.inject.*
|
import javax.inject.*
|
||||||
import scala.util.Try
|
import scala.util.Try
|
||||||
|
|
||||||
@@ -28,11 +29,11 @@ class IngameController @Inject()(
|
|||||||
game match {
|
game match {
|
||||||
case Some(g) =>
|
case Some(g) =>
|
||||||
g.logic.getCurrentState match {
|
g.logic.getCurrentState match {
|
||||||
case Lobby => Ok("Lobby: " + gameId)
|
case Lobby => Ok(views.html.lobby.lobby(Some(request.user), g))
|
||||||
case InGame =>
|
case InGame =>
|
||||||
Ok(views.html.ingame.ingame(
|
Ok(views.html.ingame.ingame(
|
||||||
g.getPlayerByUser(request.user),
|
g.getPlayerByUser(request.user),
|
||||||
g.logic
|
g
|
||||||
))
|
))
|
||||||
case SelectTrump =>
|
case SelectTrump =>
|
||||||
Ok(views.html.ingame.selecttrump(
|
Ok(views.html.ingame.selecttrump(
|
||||||
@@ -63,7 +64,7 @@ class IngameController @Inject()(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result.isSuccess) {
|
if (result.isSuccess) {
|
||||||
NoContent
|
Redirect(routes.IngameController.game(gameId))
|
||||||
} else {
|
} else {
|
||||||
val throwable = result.failed.get
|
val throwable = result.failed.get
|
||||||
throwable match {
|
throwable match {
|
||||||
@@ -78,6 +79,16 @@ class IngameController @Inject()(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
def kickPlayer(gameId: String, playerToKick: UUID): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] =>
|
||||||
|
val game = podManager.getGame(gameId)
|
||||||
|
game.get.leaveGame(playerToKick)
|
||||||
|
Redirect(routes.IngameController.game(gameId))
|
||||||
|
}
|
||||||
|
def leaveGame(gameId: String): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] =>
|
||||||
|
val game = podManager.getGame(gameId)
|
||||||
|
game.get.leaveGame(request.user.id)
|
||||||
|
Redirect(routes.MainMenuController.mainMenu())
|
||||||
|
}
|
||||||
def joinGame(gameId: String): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] =>
|
def joinGame(gameId: String): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] =>
|
||||||
val game = podManager.getGame(gameId)
|
val game = podManager.getGame(gameId)
|
||||||
val result = Try {
|
val result = Try {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class MainMenuController @Inject()(
|
|||||||
|
|
||||||
// Pass the request-handling function directly to authAction (no nested Action)
|
// Pass the request-handling function directly to authAction (no nested Action)
|
||||||
def mainMenu(): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] =>
|
def mainMenu(): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] =>
|
||||||
Ok(views.html.mainmenu.navbar(Some(request.user)))
|
Ok(views.html.mainmenu.creategame(Some(request.user)))
|
||||||
}
|
}
|
||||||
|
|
||||||
def index(): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] =>
|
def index(): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] =>
|
||||||
@@ -29,12 +29,20 @@ class MainMenuController @Inject()(
|
|||||||
}
|
}
|
||||||
|
|
||||||
def createGame(): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] =>
|
def createGame(): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] =>
|
||||||
|
val postData = request.body.asFormUrlEncoded
|
||||||
|
if (postData.isDefined) {
|
||||||
|
val gamename = postData.get.get("lobbyname").flatMap(_.headOption).getOrElse(s"${request.user.name}'s Game")
|
||||||
|
val playeramount = postData.get.get("playeramount").flatMap(_.headOption).getOrElse("")
|
||||||
val gameLobby = podManager.createGame(
|
val gameLobby = podManager.createGame(
|
||||||
host = request.user,
|
host = request.user,
|
||||||
name = s"${request.user.name}'s Game",
|
name = gamename,
|
||||||
maxPlayers = 4
|
maxPlayers = playeramount.toInt
|
||||||
)
|
)
|
||||||
Redirect(routes.IngameController.game(gameLobby.id))
|
Redirect(routes.IngameController.game(gameLobby.id))
|
||||||
|
} else {
|
||||||
|
BadRequest("Invalid form submission")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def joinGame(): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] =>
|
def joinGame(): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] =>
|
||||||
|
|||||||
@@ -88,12 +88,12 @@ class GameLobby private(
|
|||||||
* Remove the user from the game lobby.
|
* Remove the user from the game lobby.
|
||||||
* @param user the user who wants to leave the game.
|
* @param user the user who wants to leave the game.
|
||||||
*/
|
*/
|
||||||
def leaveGame(user: User): Unit = {
|
def leaveGame(userId: UUID): Unit = {
|
||||||
val sessionOpt = users.get(user.id)
|
val sessionOpt = users.get(userId)
|
||||||
if (sessionOpt.isEmpty) {
|
if (sessionOpt.isEmpty) {
|
||||||
throw new NotInThisGameException("You are not in this game!")
|
throw new NotInThisGameException("You are not in this game!")
|
||||||
}
|
}
|
||||||
users.remove(user.id)
|
users.remove(userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -176,6 +176,14 @@ class GameLobby private(
|
|||||||
getPlayerBySession(getUserSession(user.id))
|
getPlayerBySession(getUserSession(user.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def getPlayers: mutable.Map[UUID, UserSession] = {
|
||||||
|
users.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
def getLogic: GameLogic = {
|
||||||
|
logic
|
||||||
|
}
|
||||||
|
|
||||||
private def getPlayerBySession(userSession: UserSession): AbstractPlayer = {
|
private def getPlayerBySession(userSession: UserSession): AbstractPlayer = {
|
||||||
val playerOption = getMatch.totalplayers.find(_.id == userSession.id)
|
val playerOption = getMatch.totalplayers.find(_.id == userSession.id)
|
||||||
if (playerOption.isEmpty) {
|
if (playerOption.isEmpty) {
|
||||||
|
|||||||
@@ -1,50 +1,51 @@
|
|||||||
@(player: de.knockoutwhist.player.AbstractPlayer, logic: de.knockoutwhist.control.GameLogic)
|
@(player: de.knockoutwhist.player.AbstractPlayer, gamelobby: logic.game.GameLobby)
|
||||||
|
|
||||||
@main("Ingame") {
|
@main("Ingame") {
|
||||||
<div id="ingame" class="game-field game-field-background">
|
<div class="container">
|
||||||
<h1>Knockout Whist</h1>
|
<div class="row">
|
||||||
<div id="nextPlayers">
|
<div class="col-4 mt-5 text-start">
|
||||||
<p>Next Player:</p>
|
<p class="fs-4">Next Player</p>
|
||||||
<p>@logic.getPlayerQueue.get.duplicate().nextPlayer()</p>
|
<p class="fs-4">@gamelobby.getLogic.getPlayerQueue.get.duplicate().nextPlayer()</p>
|
||||||
</div>
|
</div>
|
||||||
<div id="firstCard">
|
<div class="col-4 mt-5 text-center">
|
||||||
<div id="trumpsuit">
|
<p class="fs-3">Cards played</p>
|
||||||
<p>Trumpsuit: </p>
|
|
||||||
<p>@logic.getCurrentRound.get.trumpSuit</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="firstCardObject">
|
<div class="col-4 mt-5 text-end">
|
||||||
<p>First Card</p>
|
<p class="fs-4">Trumpsuit:</p>
|
||||||
@if(logic.getCurrentTrick.get.firstCard.isDefined) {
|
<p class="fs-4">@gamelobby.getLogic.getCurrentRound.get.trumpSuit</p>
|
||||||
@util.WebUIUtils.cardtoImage(logic.getCurrentTrick.get.firstCard.get)
|
<p class="fs-4 mt-5">First Card:</p>
|
||||||
|
@if(gamelobby.getLogic.getCurrentTrick.get.firstCard.isDefined) {
|
||||||
|
@util.WebUIUtils.cardtoImage(gamelobby.getLogic.getCurrentTrick.get.firstCard.get) width="30%"/>
|
||||||
} else {
|
} else {
|
||||||
@views.html.render.card.apply("images/cards/1B.png")("Blank Card")
|
@views.html.render.card.apply("images/cards/1B.png")("Blank Card") width="30%"/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
<p>@logic.getCurrentPlayer.get has to play a card!</p>
|
<div class="col-6 mt-5">
|
||||||
@if(logic.getCurrentTrick.get.cards.nonEmpty) {
|
@for((cardplayed, player) <- gamelobby.getLogic.getCurrentTrick.get.cards) {
|
||||||
<p>Cards played</p>
|
<div class="col-auto">
|
||||||
} else {
|
<div class="card" style="max-width: 8rem;">
|
||||||
<p id="invisible">Cards played</p>
|
@util.WebUIUtils.cardtoImage(cardplayed) />
|
||||||
}
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">@player</h5>
|
||||||
<div id="cardsplayed">
|
</div>
|
||||||
@for((cardplayed, player) <- logic.getCurrentTrick.get.cards) {
|
</div>
|
||||||
<div id="playedcardplayer">
|
|
||||||
<p>@player</p>
|
|
||||||
@util.WebUIUtils.cardtoImage(cardplayed)
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>Your cards</p>
|
|
||||||
<div id="playercards">
|
|
||||||
@for(card <- player.currentHand().get.cards) {
|
|
||||||
@util.WebUIUtils.cardtoImage(card)
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row gx-0">
|
||||||
|
@for(i <- 0 until player.currentHand().get.cards.size) {
|
||||||
|
<div class="col-auto">
|
||||||
|
<form action="@(routes.IngameController.playCard(gamelobby.id))" class="d-flex" method="post">
|
||||||
|
<input type="hidden" name="cardId" value="@i" />
|
||||||
|
<button type="submit" class="btn bg-transparent p-0 m-0">
|
||||||
|
@util.WebUIUtils.cardtoImage(player.currentHand().get.cards(i)) width="40%" />
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
84
knockoutwhistweb/app/views/lobby/lobby.scala.html
Normal file
84
knockoutwhistweb/app/views/lobby/lobby.scala.html
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
@(user: Option[model.users.User], gamelobby: logic.game.GameLobby)
|
||||||
|
|
||||||
|
@main("Lobby") {
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="p-3 fs-1 d-flex align-items-center">
|
||||||
|
<div class="text-center" style="flex-grow: 1;">
|
||||||
|
Lobby-Name: @gamelobby.name
|
||||||
|
</div>
|
||||||
|
<form action="@(routes.IngameController.leaveGame(gamelobby.id))">
|
||||||
|
<button type="submit" class="btn btn-danger ms-auto">Exit</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="p-3 text-center fs-4">Playeramount: @gamelobby.getPlayers.size / @gamelobby.maxPlayers</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
|
||||||
|
@if((gamelobby.getUserSession(user.get.id).host)) {
|
||||||
|
@for(playersession <- gamelobby.getPlayers.values) {
|
||||||
|
<div class="col-auto">
|
||||||
|
<div class="card" style="width: 18rem;">
|
||||||
|
<img src="@routes.Assets.versioned("images/profile.png")" alt="Profile" class="card-img-top w-50 mx-auto mt-3" />
|
||||||
|
<div class="card-body">
|
||||||
|
@if(playersession.id == user.get.id) {
|
||||||
|
<h5 class="card-title">@playersession.name (You)</h5>
|
||||||
|
<p class="card-text">Your text could be here!</p>
|
||||||
|
<a href="#" class="btn btn-danger disabled" aria-disabled="true" tabindex="-1">Remove</a>
|
||||||
|
} else {
|
||||||
|
<h5 class="card-title">@playersession.name</h5>
|
||||||
|
<p class="card-text">Your text could be here!</p>
|
||||||
|
<form action="@(routes.IngameController.kickPlayer(gamelobby.id, playersession.id))" method="post">
|
||||||
|
<button type="submit" class="btn btn-danger">Remove</button>
|
||||||
|
</form>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col text-center mt-3">
|
||||||
|
<a href="@(routes.IngameController.startGame(gamelobby.id))" class="btn btn-success">Start Game</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
} else {
|
||||||
|
@for(playersession <- gamelobby.getPlayers.values) {
|
||||||
|
<div class="col-auto">
|
||||||
|
<div class="card" style="width: 18rem;">
|
||||||
|
<img src="@routes.Assets.versioned("images/profile.png")" alt="Profile" class="card-img-top w-50 mx-auto mt-3" />
|
||||||
|
<div class="card-body">
|
||||||
|
@if(playersession.id == user.get.id) {
|
||||||
|
<h5 class="card-title">@playersession.name (You)</h5>
|
||||||
|
<p class="card-text">Your text could be here!</p>
|
||||||
|
} else {
|
||||||
|
<h5 class="card-title">@playersession.name</h5>
|
||||||
|
<p class="card-text">Your text could be here!</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col mt-3">
|
||||||
|
<p class="text-center fs-4">Waiting for the host to start the game...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col mt-1">
|
||||||
|
<div class="text-center">
|
||||||
|
<div class="spinner-border" role="status">
|
||||||
|
<span class="visually-hidden">Loading...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
32
knockoutwhistweb/app/views/mainmenu/creategame.scala.html
Normal file
32
knockoutwhistweb/app/views/mainmenu/creategame.scala.html
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
@(user: Option[model.users.User])
|
||||||
|
|
||||||
|
@main("Create Game") {
|
||||||
|
@navbar(user)
|
||||||
|
<form action="@routes.MainMenuController.createGame()" method="post">
|
||||||
|
<div class="w-50 mx-auto">
|
||||||
|
<div class="mt-3">
|
||||||
|
<label for="lobbyname" class="form-label">Lobby-Name</label>
|
||||||
|
<input type="text" class="form-control" id="lobbyname" name="lobbyname" placeholder="Lobby 1" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-switch mt-3">
|
||||||
|
<input class="form-check-input" type="checkbox" id="visibilityswitch" disabled>
|
||||||
|
<label class="form-check-label" for="visibilityswitch">public/private</label>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3">
|
||||||
|
<label for="playeramount" class="form-label">Playeramount:</label>
|
||||||
|
<input type="range" class="form-range" min="2" max="7" value="2" id="playeramount" name="playeramount">
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<span>2</span>
|
||||||
|
<span>3</span>
|
||||||
|
<span>4</span>
|
||||||
|
<span>5</span>
|
||||||
|
<span>6</span>
|
||||||
|
<span>7</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-center">
|
||||||
|
<button type="submit" class="btn btn-success">Create Game</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
@(user: Option[model.users.User])
|
@(user: Option[model.users.User])
|
||||||
@main("Knockout Whist - Main Menu") {
|
|
||||||
<nav class="navbar navbar-expand-lg bg-body-tertiary">
|
<nav class="navbar navbar-expand-lg bg-body-tertiary">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navBar" aria-controls="navBar" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navBar" aria-controls="navBar" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
@@ -53,4 +52,3 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
@(src: String)(alt: String)
|
@(src: String)(alt: String)
|
||||||
<img src="@routes.Assets.versioned(src)" alt="@alt"/>
|
<img src="@routes.Assets.versioned(src)" alt="@alt"
|
||||||
@@ -24,6 +24,7 @@ GET /logout controllers.UserController.logout()
|
|||||||
# In-game routes
|
# In-game routes
|
||||||
GET /game/:id controllers.IngameController.game(id: String)
|
GET /game/:id controllers.IngameController.game(id: String)
|
||||||
GET /game/:id/join controllers.IngameController.joinGame(id: String)
|
GET /game/:id/join controllers.IngameController.joinGame(id: String)
|
||||||
POST /game/:id/start controllers.IngameController.startGame(id: String)
|
GET /game/:id/start controllers.IngameController.startGame(id: String)
|
||||||
|
POST /game/:id/kickPlayer controllers.IngameController.kickPlayer(id: String, playerId: java.util.UUID)
|
||||||
|
GET /game/:id/leaveGame controllers.IngameController.leaveGame(id: String)
|
||||||
POST /game/:id/playCard controllers.IngameController.playCard(id: String)
|
POST /game/:id/playCard controllers.IngameController.playCard(id: String)
|
||||||
Reference in New Issue
Block a user