Feat/ms 4 integration #282

Merged
jona.walpert merged 23 commits from feat/ms-4-integration into main 2026-04-13 03:07:52 +02:00
6 changed files with 208 additions and 4 deletions
Showing only changes of commit 1f8cf35e55 - Show all commits
@@ -157,6 +157,12 @@ public class ChatController {
} }
} }
/**
* Method to get the lobbyId of the currently active lobby chat, to check if incoming lobby messages
* belong to the same lobby.
*
* @return the lobbyId of the currently active lobby chat.
*/
private int getActiveLobbyChatId() { private int getActiveLobbyChatId() {
ChatModel lobbyModel = chatModelMap.get(new ChatKey(ChatType.LOBBY)); ChatModel lobbyModel = chatModelMap.get(new ChatKey(ChatType.LOBBY));
if (lobbyModel != null) { if (lobbyModel != null) {
@@ -12,12 +12,22 @@ public class GameService {
private final GameClient client; private final GameClient client;
private GameState state; private GameState state;
/**
* Constructs a GameService with the specified GameClient.
*
* @param client The GameClient used to communicate with the server. Must not be null.
*/
public GameService(GameClient client) { public GameService(GameClient client) {
if (client == null) throw new IllegalArgumentException("GameClient must not be null"); if (client == null) throw new IllegalArgumentException("GameClient must not be null");
this.client = client; this.client = client;
LOG.info("GameService created"); LOG.info("GameService created");
} }
/**
* Refreshes the game state by fetching the latest state from the server using the GameClient.
*
* @return The updated GameState after refreshing.
*/
public GameState refresh() { public GameState refresh() {
LOG.fine("Refreshing game state..."); LOG.fine("Refreshing game state...");
@@ -45,21 +55,41 @@ public class GameService {
return state; return state;
} }
/**
* Retrieves the current phase of the game.
*
* @return The current game phase as a string (e.g., "Pre-Flop", "Flop", "Turn", "River").
*/
public int getPot() { public int getPot() {
ensureState(); ensureState();
return state.pot; return state.pot;
} }
/**
* Retrieves the current phase of the game.
*
* @return The current game phase as a string (e.g., "Pre-Flop", "Flop", "Turn", "River").
*/
public List<Card> getCommunityCards() { public List<Card> getCommunityCards() {
ensureState(); ensureState();
return state.communityCards != null ? state.communityCards : List.of(); return state.communityCards != null ? state.communityCards : List.of();
} }
/**
* Retrieves the list of players currently in the game.
*
* @return A list of Player objects representing the players in the game. A list of Player objects representing the players in the game.
*/
public List<Player> getPlayers() { public List<Player> getPlayers() {
ensureState(); ensureState();
return state.players != null ? state.players : List.of(); return state.players != null ? state.players : List.of();
} }
/**
* Retrieves the index of the current player whose turn it is.
*
* @return The index of the current player in the players list, or -1 if not available.
*/
public Player getWinner() { public Player getWinner() {
ensureState(); ensureState();
if (state.winnerIndex < 0 || state.players == null || state.winnerIndex >= state.players.size()) { if (state.winnerIndex < 0 || state.players == null || state.winnerIndex >= state.players.size()) {
@@ -68,17 +98,52 @@ public class GameService {
return state.players.get(state.winnerIndex); return state.players.get(state.winnerIndex);
} }
public void call() { client.sendCall(); } /**
public void fold() { client.sendFold(); } * Retrieves the current phase of the game.
public void bet(int amount) { client.sendBet(amount); } */
public void raise(int amount) { client.sendRaise(amount); } public void call() {
client.sendCall();
}
/**
* Retrieves the current phase of the game.
*/
public void fold() {
client.sendFold();
}
/**
* Retrieves the current phase of the game.
*
* @param amount The amount to bet. Must be a positive integer.
*/
public void bet(int amount) {
client.sendBet(amount);
}
/**
* Retrieves the current phase of the game.
*
* @param amount The amount to raise. Must be a positive integer.
*/
public void raise(int amount) {
client.sendRaise(amount);
}
/**
* Ensures that the game state has been initialized before accessing it.
*/
private void ensureState() { private void ensureState() {
if (state == null) { if (state == null) {
throw new IllegalStateException("GameService used before any successful refresh()"); throw new IllegalStateException("GameService used before any successful refresh()");
} }
} }
/**
* Returns the current GameState without refreshing from the server.
*
* @return The current GameState, or null if it has not been initialized yet.
*/
public GameState peekStateOrNull() { public GameState peekStateOrNull() {
return state; return state;
} }
@@ -45,6 +45,12 @@ public class ChatBoxController {
private String ressource = "/ui-structure/components/chatui/chattab.fxml"; private String ressource = "/ui-structure/components/chatui/chattab.fxml";
/**
* Constructor for the ChatBoxController, initializes the necessary fields and data structures for managing chat tabs and whisper chats.
*
* @param username The username of the current user.
* @param chatController The ChatController instance responsible for handling chat logic and communication with the server.
*/
public ChatBoxController(String username, ChatController chatController) { public ChatBoxController(String username, ChatController chatController) {
this.username = username; this.username = username;
this.chatController = chatController; this.chatController = chatController;
@@ -148,6 +148,12 @@ public class CasinoGameController {
// default constructor for FXML // default constructor for FXML
} }
/**
* Generate a unique key for a given card based on its suit and value.
*
* @param c The card for which to generate the key.
* @return A string key representing the card, formatted as "suit:value".
*/
private String cardKey(Card c) { private String cardKey(Card c) {
if (c == null) return "null"; if (c == null) return "null";
String suit = (c.getSuit() == null) ? "" : c.getSuit().toLowerCase(); String suit = (c.getSuit() == null) ? "" : c.getSuit().toLowerCase();
@@ -155,6 +161,13 @@ public class CasinoGameController {
return suit + ":" + value; return suit + ":" + value;
} }
/**
* Generate a list of unique keys for a list of cards.
*
* @param cards The list of cards for which to generate keys.
* @param slots The number of slots to generate keys for.
* @return A list of string keys representing the cards, with "null" for any empty slots.
*/
private java.util.List<String> cardKeys(java.util.List<Card> cards, int slots) { private java.util.List<String> cardKeys(java.util.List<Card> cards, int slots) {
java.util.List<String> keys = new java.util.ArrayList<>(slots); java.util.List<String> keys = new java.util.ArrayList<>(slots);
for (int i = 0; i < slots; i++) { for (int i = 0; i < slots; i++) {
@@ -224,6 +237,13 @@ public class CasinoGameController {
initializeChatIfPossible(); initializeChatIfPossible();
} }
/**
* Set the context for the chat functionality by providing the username, ClientService, and lobby ID.
*
* @param username The username of the player, used for chat identification. Must not be null or blank.
* @param clientService The ClientService instance used for communicating with the server. Must not be null.
* @param lobbyId The ID of the lobby associated with the chat, used to determine the chat context. Must be a non-negative integer.
*/
public void setChatContext(String username, ClientService clientService, int lobbyId) { public void setChatContext(String username, ClientService clientService, int lobbyId) {
this.chatUsername = username; this.chatUsername = username;
this.chatClientService = clientService; this.chatClientService = clientService;
@@ -231,6 +251,9 @@ public class CasinoGameController {
initializeChatIfPossible(); initializeChatIfPossible();
} }
/**
* Initialize the chat UI if all necessary information (username, ClientService, and lobby ID) is available and the chat has not already been initialized.
*/
private void initializeChatIfPossible() { private void initializeChatIfPossible() {
if (chatInitialized || chatClientService == null || chatUsername == null) { if (chatInitialized || chatClientService == null || chatUsername == null) {
return; return;
@@ -491,6 +514,11 @@ public class CasinoGameController {
} }
} }
/**
* Synchronize the whisper chat targets with the current list of players.
*
* @param players The list of players currently in the game, used to update the whisper chat targets in the chat controller.
*/
private void syncWhisperTargetsFromPlayers(List<Player> players) { private void syncWhisperTargetsFromPlayers(List<Player> players) {
if (chatController == null || players == null || players.isEmpty()) { if (chatController == null || players == null || players.isEmpty()) {
return; return;
@@ -507,6 +535,12 @@ public class CasinoGameController {
} }
} }
/**
* Retrieve the hole cards of the current player based on their PlayerId and the list of players in the game state.
*
* @param players The list of players currently in the game, used to find the player matching myPlayerId and retrieve their hole cards.
* @return A list of Card objects representing the current player's hole cards, or an empty list if the player is not found or has no cards.
*/
private List<Card> getMyCards(List<Player> players) { private List<Card> getMyCards(List<Player> players) {
if (myPlayerId == null || players == null) { if (myPlayerId == null || players == null) {
@@ -578,6 +612,11 @@ public class CasinoGameController {
} }
} }
/**
* Update the opponent player slots based on the list of players in the game state. This method identifies the opponents by comparing their PlayerIds with myPlayerId and updates the corresponding PlayerStatusControllers for each opponent slot.
*
* @param players The list of players currently in the game, used to determine which players are opponents and update their display in the UI accordingly. If the list is null or empty, all opponent slots will be cleared.
*/
private void updatePlayers(List<Player> players) { private void updatePlayers(List<Player> players) {
if (players == null || players.isEmpty()) { if (players == null || players.isEmpty()) {
clearOpponentSlots(); clearOpponentSlots();
@@ -601,6 +640,14 @@ public class CasinoGameController {
safeRefresh(player3Controller); safeRefresh(player3Controller);
} }
/**
* Build a list of opponent players by filtering out the current player (identified by myPlayerId) from the provided list of players. If the current player is not found in the list, it assumes all players are opponents and returns the original list.
*
* @param players The list of players to filter, which may include the current player and their opponents.
* This list is typically obtained from the game state and may be null or empty, in which case an empty list of opponents will be returned.
* @return A list of Player objects representing the opponents, excluding the current player if found.
* If the current player is not found, the original list of players is returned as opponents.
*/
private java.util.List<Player> buildOpponents(List<Player> players) { private java.util.List<Player> buildOpponents(List<Player> players) {
java.util.List<Player> opponents = new java.util.ArrayList<>(); java.util.List<Player> opponents = new java.util.ArrayList<>();
boolean meFound = false; boolean meFound = false;
@@ -626,16 +673,31 @@ public class CasinoGameController {
return opponents; return opponents;
} }
/**
* Set the opponent player information in the specified PlayerStatusController based on the provided list of opponents and the index of the opponent to display.
*
* @param slot The PlayerStatusController instance representing the opponent slot in the UI, which will be updated with the player information if available.
* @param list The list of opponent players to choose from, which is typically built by filtering the game state's player list to exclude the current player.
* @param index The index of the opponent in the list to display in the specified slot.
*/
private void setOpponent(PlayerStatusController slot, java.util.List<Player> list, int index) { private void setOpponent(PlayerStatusController slot, java.util.List<Player> list, int index) {
if (slot == null) return; if (slot == null) return;
slot.setPlayer(index < list.size() ? list.get(index) : null); slot.setPlayer(index < list.size() ? list.get(index) : null);
} }
/**
* Safely refresh the PlayerStatusController by calling its refresh method, while catching and ignoring any exceptions that may occur during the refresh process.
*
* @param c The PlayerStatusController instance to refresh, which may be null.
*/
private void safeRefresh(PlayerStatusController c) { private void safeRefresh(PlayerStatusController c) {
if (c == null) return; if (c == null) return;
try { c.refresh(); } catch (Exception ignored) {} try { c.refresh(); } catch (Exception ignored) {}
} }
/**
* Clear all opponent slots in the UI by setting their player information to null and refreshing their display.
*/
private void clearOpponentSlots() { private void clearOpponentSlots() {
if (player1Controller != null) player1Controller.setPlayer(null); if (player1Controller != null) player1Controller.setPlayer(null);
if (player2Controller != null) player2Controller.setPlayer(null); if (player2Controller != null) player2Controller.setPlayer(null);
@@ -686,6 +748,13 @@ public class CasinoGameController {
} }
} }
/**
* Compare two Player objects to determine if they represent the same player based on their PlayerIds. This method checks for null values and compares the IDs for equality.
*
* @param a The first Player object to compare, which may be null.
* @param b The second Player object to compare, which may be null.
* @return true if both Player objects are non-null and have the same non-null PlayerId, false otherwise.
*/
private boolean samePlayer(Player a, Player b) { private boolean samePlayer(Player a, Player b) {
if (a == null || b == null || a.getId() == null || b.getId() == null) { if (a == null || b == null || a.getId() == null || b.getId() == null) {
return false; return false;
@@ -1155,6 +1224,11 @@ public class CasinoGameController {
st.play(); st.play();
} }
/**
* Set the PlayerId of the current player, which is used to identify the player's hole cards and update the taskbar with the correct player information.
*
* @param id The PlayerId of the current player, which should match the PlayerId in the game state for the player's own information to be displayed correctly.
*/
public void setMyPlayerId(PlayerId id) { public void setMyPlayerId(PlayerId id) {
this.myPlayerId = id; this.myPlayerId = id;
TaskbarController controller = resolveTaskbarController(); TaskbarController controller = resolveTaskbarController();
@@ -1163,6 +1237,11 @@ public class CasinoGameController {
} }
} }
/**
* Resolve the TaskbarController instance to be used for updating the taskbar with game information.
*
* @return The TaskbarController instance to use for taskbar updates, which may be the directly injected taskbarController or the one obtained from the taskbarIncludeController.
*/
private TaskbarController resolveTaskbarController() { private TaskbarController resolveTaskbarController() {
if (taskbarController != null) { if (taskbarController != null) {
return taskbarController; return taskbarController;
@@ -31,22 +31,49 @@ public class CasinoGameUI extends Application {
private static final int DEFAULT_WIDTH = 1200; private static final int DEFAULT_WIDTH = 1200;
private static final int DEFAULT_HEIGHT = 800; private static final int DEFAULT_HEIGHT = 800;
/**
* Default constructor for the CasinoGameUI application.
*/
public CasinoGameUI() { public CasinoGameUI() {
// default no-arg constructor // default no-arg constructor
} }
/**
* Sets the ClientService instance to be used by the application.
*
* @param clientService the ClientService instance to set
*/
public static void setClientService(ClientService clientService) { public static void setClientService(ClientService clientService) {
CasinoGameUI.clientService = clientService; CasinoGameUI.clientService = clientService;
} }
/**
* Sets the username to be used by the application.
*
* @param username the username to set
*/
public static void setUsername(String username) { public static void setUsername(String username) {
CasinoGameUI.username = username; CasinoGameUI.username = username;
} }
/**
* Sets the lobby ID to be used by the application.
*
* @param lobbyId the lobby ID to set
*/
public static void setLobbyId(int lobbyId) { public static void setLobbyId(int lobbyId) {
CasinoGameUI.lobbyId = lobbyId; CasinoGameUI.lobbyId = lobbyId;
} }
/**
* The main entry point for the JavaFX application. This method is called after the application is
*
* @param stage the primary stage for this application, onto which
* the application scene can be set.
* Applications may create other stages, if needed, but they will not be
* primary stages.
* @throws IOException
*/
@Override @Override
public void start(Stage stage) throws IOException { public void start(Stage stage) throws IOException {
@@ -102,12 +129,23 @@ public class CasinoGameUI extends Application {
controller.start(); controller.start();
} }
/**
* Normalizes a string by trimming whitespace and converting blank strings to null.
*
* @param s the string to normalize
* @return the normalized string, or null if the input is null or blank
*/
private static String normalize(String s) { private static String normalize(String s) {
if (s == null) return null; if (s == null) return null;
String t = s.trim(); String t = s.trim();
return t.isBlank() ? null : t; return t.isBlank() ? null : t;
} }
/**
* The main method serves as the entry point for the application. It launches the JavaFX application.
*
* @param args command line arguments (not used)
*/
public static void main(String[] args) { public static void main(String[] args) {
launch(); launch();
} }
@@ -107,6 +107,11 @@ public class CasinomainuiController {
initializeChat(clientService); initializeChat(clientService);
} }
/**
* Initializes the chat UI if a valid ClientService is available. If the client is offline or the
*
* @param clientService
*/
private void initializeChat(ClientService clientService) { private void initializeChat(ClientService clientService) {
if (clientService == null || clientService.isOffline() || chatContainer == null) { if (clientService == null || clientService.isOffline() || chatContainer == null) {
return; return;
@@ -128,6 +133,11 @@ public class CasinomainuiController {
} }
} }
/**
* Resolves the username to be used in the chat. It first checks for a shared username set at the
*
* @return The resolved username, or "Guest" if no valid username is found.
*/
private String resolveChatUsername() { private String resolveChatUsername() {
String shared = ClientApp.getSharedUsername(); String shared = ClientApp.getSharedUsername();
if (shared != null && !shared.isBlank()) { if (shared != null && !shared.isBlank()) {