Feat/105 add fold command on server side #269
@@ -210,6 +210,20 @@ public class ServerApp {
|
||||
new ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.call
|
||||
.PlayerCallHandler(responseDispatcher, userRegistry, lobbyManager));
|
||||
|
||||
// FOLD registration
|
||||
parserDispatcher.register(
|
||||
"FOLD",
|
||||
new ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.fold
|
||||
.PlayerFoldParser());
|
||||
commandRouter.register(
|
||||
ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.fold.PlayerFoldRequest
|
||||
.class,
|
||||
(ch.unibas.dmi.dbis.cs108.casono.server.network.command.execution.CommandHandler<
|
||||
ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.fold
|
||||
.PlayerFoldRequest>)
|
||||
new ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.fold
|
||||
.PlayerFoldHandler(responseDispatcher, userRegistry, lobbyManager));
|
||||
|
||||
// GET_LOBBY_STATUS registration
|
||||
parserDispatcher.register(
|
||||
"GET_LOBBY_STATUS",
|
||||
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.fold;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.GameController;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.player.PlayerId;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.LobbyId;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.LobbyManager;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserRegistry;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.execution.CommandHandler;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.ErrorResponse;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.OkResponse;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Handler for the `FOLD` command.
|
||||
*
|
||||
* <p>This handler validates the session, resolves the lobby (by `GAME_ID` when provided or by
|
||||
* session username otherwise), checks for a running game and forwards the fold action to the {@code
|
||||
* GameController}.
|
||||
*/
|
||||
public class PlayerFoldHandler extends CommandHandler<PlayerFoldRequest> {
|
||||
private final UserRegistry userRegistry;
|
||||
private final LobbyManager lobbyManager;
|
||||
|
||||
/**
|
||||
* Creates a new {@code PlayerFoldHandler}.
|
||||
*
|
||||
* @param responseDispatcher dispatcher used to send responses back to the client
|
||||
* @param userRegistry registry to resolve users from session ids
|
||||
* @param lobbyManager manager used to lookup lobbies and their game controllers
|
||||
*/
|
||||
public PlayerFoldHandler(
|
||||
ResponseDispatcher responseDispatcher,
|
||||
UserRegistry userRegistry,
|
||||
LobbyManager lobbyManager) {
|
||||
super(responseDispatcher);
|
||||
this.userRegistry = userRegistry;
|
||||
this.lobbyManager = lobbyManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the fold request: resolve lobby by `GAME_ID` if present, otherwise by session user,
|
||||
* verify game is running, and forward the fold to the game controller.
|
||||
*
|
||||
* @param request the parsed {@link PlayerFoldRequest}
|
||||
*/
|
||||
@Override
|
||||
public void execute(PlayerFoldRequest request) {
|
||||
Optional<ch.unibas.dmi.dbis.cs108.casono.server.domain.user.User> opt =
|
||||
userRegistry.getBySessionId(request.getSessionId());
|
||||
if (opt.isEmpty()) {
|
||||
responseDispatcher.dispatch(
|
||||
new ErrorResponse(request.getContext(), "NOT_LOGGED_IN", "User not logged in"));
|
||||
return;
|
||||
}
|
||||
|
||||
String username = opt.get().getName();
|
||||
|
||||
Integer gameId = request.getGameId();
|
||||
var lobby =
|
||||
(gameId != null)
|
||||
? lobbyManager.getLobby(LobbyId.of(gameId))
|
||||
: lobbyManager.getLobbyByUsername(username);
|
||||
|
||||
if (lobby == null) {
|
||||
if (gameId != null) {
|
||||
responseDispatcher.dispatch(
|
||||
new ErrorResponse(
|
||||
request.getContext(), "LOBBY_NOT_FOUND", "Lobby not found"));
|
||||
} else {
|
||||
responseDispatcher.dispatch(
|
||||
new ErrorResponse(
|
||||
request.getContext(), "NOT_IN_LOBBY", "User not in a lobby"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
GameController game = lobby.getGameController();
|
||||
if (game == null) {
|
||||
responseDispatcher.dispatch(
|
||||
new ErrorResponse(
|
||||
request.getContext(), "GAME_NOT_STARTED", "Game not started"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
game.playerFold(PlayerId.of(username));
|
||||
} catch (RuntimeException e) {
|
||||
responseDispatcher.dispatch(
|
||||
new ErrorResponse(request.getContext(), "GAME_ACTION_FAILED", e.getMessage()));
|
||||
return;
|
||||
}
|
||||
|
||||
responseDispatcher.dispatch(new OkResponse(request.getContext()));
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.fold;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.CommandParser;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.PrimitiveRequest;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.accessor.RequestParameterAccessor;
|
||||
|
||||
/**
|
||||
* Parser for the `FOLD` command.
|
||||
*
|
||||
* <p>Accepts an optional `GAME_ID` parameter. If provided, the handler will target the specified
|
||||
* lobby; otherwise the server resolves the lobby by the requesting session's user.
|
||||
*/
|
||||
public class PlayerFoldParser implements CommandParser<PlayerFoldRequest> {
|
||||
@Override
|
||||
public PlayerFoldRequest parse(PrimitiveRequest primitiveRequest) {
|
||||
RequestParameterAccessor accessor =
|
||||
new RequestParameterAccessor(primitiveRequest.parameters());
|
||||
|
||||
Integer gameId = null;
|
||||
try {
|
||||
gameId = accessor.optional("GAME_ID", null, Integer::parseInt);
|
||||
} catch (Exception e) {
|
||||
// parse handled by framework
|
||||
}
|
||||
|
||||
return new PlayerFoldRequest(primitiveRequest.context(), gameId);
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.fold;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.Request;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
|
||||
|
||||
/**
|
||||
* Request for the `FOLD` command.
|
||||
*
|
||||
* <p>Contains an optional `gameId` when the client targets a specific lobby, otherwise the server
|
||||
* will resolve the lobby from the requesting session's user.
|
||||
*/
|
||||
public class PlayerFoldRequest extends Request {
|
||||
private final Integer gameId;
|
||||
|
||||
/**
|
||||
* Creates a new {@code PlayerFoldRequest}.
|
||||
*
|
||||
* @param context the request context
|
||||
* @param gameId optional game id of the targeted lobby (may be {@code null})
|
||||
*/
|
||||
public PlayerFoldRequest(RequestContext context, Integer gameId) {
|
||||
super(context);
|
||||
this.gameId = gameId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the optional target game id.
|
||||
*
|
||||
* @return the game id or {@code null} if not provided
|
||||
*/
|
||||
public Integer getGameId() {
|
||||
return gameId;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user