Feat/ms 4 integration #282
@@ -63,13 +63,17 @@ public class ChatController {
|
|||||||
localUserList = new ArrayList<>();
|
localUserList = new ArrayList<>();
|
||||||
this.chatBoxController = new ChatBoxController(username, this);
|
this.chatBoxController = new ChatBoxController(username, this);
|
||||||
this.logger = LogManager.getLogger(ChatController.class);
|
this.logger = LogManager.getLogger(ChatController.class);
|
||||||
this.timer = new Timer();
|
this.timer = new Timer(true);
|
||||||
timer.schedule(
|
timer.schedule(
|
||||||
new TimerTask() {
|
new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
try {
|
||||||
receiveMessage();
|
receiveMessage();
|
||||||
checkWhisperUsers();
|
checkWhisperUsers();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
logger.warn("Chat refresh failed: {}", e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
@@ -84,8 +88,12 @@ public class ChatController {
|
|||||||
*/
|
*/
|
||||||
public void setLobbyChat(int lobbyId) {
|
public void setLobbyChat(int lobbyId) {
|
||||||
this.lobbyId = lobbyId;
|
this.lobbyId = lobbyId;
|
||||||
|
ChatKey key = new ChatKey(ChatType.LOBBY);
|
||||||
|
if (chatModelMap.containsKey(key)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
ChatModel lobbyChatModel = new ChatModel(ChatType.LOBBY, username, lobbyId, null);
|
ChatModel lobbyChatModel = new ChatModel(ChatType.LOBBY, username, lobbyId, null);
|
||||||
chatModelMap.put(new ChatKey(ChatType.LOBBY), lobbyChatModel);
|
chatModelMap.put(key, lobbyChatModel);
|
||||||
this.chatBoxController.addChatTab("Lobby", lobbyChatModel);
|
this.chatBoxController.addChatTab("Lobby", lobbyChatModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,13 +170,30 @@ public class ChatController {
|
|||||||
for (String user : users) {
|
for (String user : users) {
|
||||||
String value = user.split("\\=")[1];
|
String value = user.split("\\=")[1];
|
||||||
logger.info(value);
|
logger.info(value);
|
||||||
if (!(localUserList.contains(value) || value.equals(username))) {
|
addWhisperUser(value);
|
||||||
localUserList.add(value);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a whisper target locally and updates the UI if it is a new user.
|
||||||
|
*
|
||||||
|
* @param user target username
|
||||||
|
*/
|
||||||
|
public synchronized void addWhisperUser(String user) {
|
||||||
|
if (user == null || user.isBlank()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(localUserList.contains(user) || user.equals(username))) {
|
||||||
|
localUserList.add(user);
|
||||||
logger.info("adding new whisper user");
|
logger.info("adding new whisper user");
|
||||||
chatBoxController.addWhisperUser(value);
|
chatBoxController.addWhisperUser(user);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Stops polling background tasks for this chat controller instance. */
|
||||||
|
public void shutdown() {
|
||||||
|
timer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+67
@@ -1,19 +1,27 @@
|
|||||||
package ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui;
|
package ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatController;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.game.Card;
|
import ch.unibas.dmi.dbis.cs108.casono.client.game.Card;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.game.GameService;
|
import ch.unibas.dmi.dbis.cs108.casono.client.game.GameService;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.game.GameState;
|
import ch.unibas.dmi.dbis.cs108.casono.client.game.GameState;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.game.Player;
|
import ch.unibas.dmi.dbis.cs108.casono.client.game.Player;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.game.PlayerId;
|
import ch.unibas.dmi.dbis.cs108.casono.client.game.PlayerId;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents.PlayerStatusController;
|
import ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents.PlayerStatusController;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents.TaskbarController;
|
import ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents.TaskbarController;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
|
|
||||||
@@ -44,6 +52,7 @@ public class CasinoGameController {
|
|||||||
@FXML private VBox player2;
|
@FXML private VBox player2;
|
||||||
@FXML private VBox player3;
|
@FXML private VBox player3;
|
||||||
@FXML private ImageView myDealerIcon;
|
@FXML private ImageView myDealerIcon;
|
||||||
|
@FXML private AnchorPane chatContainer;
|
||||||
|
|
||||||
private GameService gameService;
|
private GameService gameService;
|
||||||
private PlayerId myPlayerId;
|
private PlayerId myPlayerId;
|
||||||
@@ -125,6 +134,12 @@ public class CasinoGameController {
|
|||||||
private static final long CHIP_DROP_DURATION_MS = 250;
|
private static final long CHIP_DROP_DURATION_MS = 250;
|
||||||
private static final long CHIP_STAGGER_DELAY_MULTIPLIER = 35L;
|
private static final long CHIP_STAGGER_DELAY_MULTIPLIER = 35L;
|
||||||
|
|
||||||
|
private ChatController chatController;
|
||||||
|
private String chatUsername;
|
||||||
|
private ClientService chatClientService;
|
||||||
|
private int chatLobbyId = -1;
|
||||||
|
private boolean chatInitialized;
|
||||||
|
|
||||||
/** Standard constructor. Used by FXML. */
|
/** Standard constructor. Used by FXML. */
|
||||||
public CasinoGameController() {
|
public CasinoGameController() {
|
||||||
// default constructor for FXML
|
// default constructor for FXML
|
||||||
@@ -203,6 +218,38 @@ public class CasinoGameController {
|
|||||||
// empty display only (optional)
|
// empty display only (optional)
|
||||||
renderCommunityCards(List.of());
|
renderCommunityCards(List.of());
|
||||||
renderPlayerCards(List.of());
|
renderPlayerCards(List.of());
|
||||||
|
initializeChatIfPossible();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChatContext(String username, ClientService clientService, int lobbyId) {
|
||||||
|
this.chatUsername = username;
|
||||||
|
this.chatClientService = clientService;
|
||||||
|
this.chatLobbyId = lobbyId;
|
||||||
|
initializeChatIfPossible();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeChatIfPossible() {
|
||||||
|
if (chatInitialized || chatContainer == null || chatClientService == null || chatUsername == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
chatController = new ChatController(chatUsername, chatClientService);
|
||||||
|
URL resource = getClass().getResource("/ui-structure/components/chatui/chatbox.fxml");
|
||||||
|
FXMLLoader loader = new FXMLLoader(resource);
|
||||||
|
loader.setController(chatController.getChatBoxController());
|
||||||
|
javafx.scene.Node chatNode = loader.load();
|
||||||
|
chatContainer.getChildren().setAll(chatNode);
|
||||||
|
AnchorPane.setTopAnchor(chatNode, 0.0);
|
||||||
|
AnchorPane.setBottomAnchor(chatNode, 0.0);
|
||||||
|
AnchorPane.setLeftAnchor(chatNode, 0.0);
|
||||||
|
AnchorPane.setRightAnchor(chatNode, 0.0);
|
||||||
|
if (chatLobbyId >= 0) {
|
||||||
|
chatController.setLobbyChat(chatLobbyId);
|
||||||
|
}
|
||||||
|
chatInitialized = true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.warning("Could not initialize game chat UI: " + e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test method to demonstrate the UI functionality with sample data.
|
// Test method to demonstrate the UI functionality with sample data.
|
||||||
@@ -329,6 +376,9 @@ public class CasinoGameController {
|
|||||||
if (timeline != null) {
|
if (timeline != null) {
|
||||||
timeline.stop();
|
timeline.stop();
|
||||||
}
|
}
|
||||||
|
if (chatController != null) {
|
||||||
|
chatController.shutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -405,6 +455,7 @@ public class CasinoGameController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updatePlayers(players);
|
updatePlayers(players);
|
||||||
|
syncWhisperTargetsFromPlayers(players);
|
||||||
updateGameInfo(s);
|
updateGameInfo(s);
|
||||||
highlightDealer(s);
|
highlightDealer(s);
|
||||||
updateTaskbar(s);
|
updateTaskbar(s);
|
||||||
@@ -419,6 +470,22 @@ public class CasinoGameController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void syncWhisperTargetsFromPlayers(List<Player> players) {
|
||||||
|
if (chatController == null || players == null || players.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<String> seen = new HashSet<>();
|
||||||
|
for (Player player : players) {
|
||||||
|
if (player == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String name = player.getName();
|
||||||
|
if (name != null && !name.isBlank() && seen.add(name)) {
|
||||||
|
chatController.addWhisperUser(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<Card> getMyCards(List<Player> players) {
|
private List<Card> getMyCards(List<Player> players) {
|
||||||
|
|
||||||
if (myPlayerId == null || players == null) {
|
if (myPlayerId == null || players == null) {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ public class CasinoGameUI extends Application {
|
|||||||
private static ClientService clientService;
|
private static ClientService clientService;
|
||||||
|
|
||||||
private static String username;
|
private static String username;
|
||||||
|
private static int lobbyId = -1;
|
||||||
|
|
||||||
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;
|
||||||
@@ -42,6 +43,10 @@ public class CasinoGameUI extends Application {
|
|||||||
CasinoGameUI.username = username;
|
CasinoGameUI.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setLobbyId(int lobbyId) {
|
||||||
|
CasinoGameUI.lobbyId = lobbyId;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage stage) throws IOException {
|
public void start(Stage stage) throws IOException {
|
||||||
|
|
||||||
@@ -81,6 +86,7 @@ public class CasinoGameUI extends Application {
|
|||||||
controller.setGameService(gameService);
|
controller.setGameService(gameService);
|
||||||
|
|
||||||
controller.setMyPlayerId(PlayerId.of(effectiveUsername));
|
controller.setMyPlayerId(PlayerId.of(effectiveUsername));
|
||||||
|
controller.setChatContext(effectiveUsername, clientService, lobbyId);
|
||||||
|
|
||||||
Scene scene = new Scene(root, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
Scene scene = new Scene(root, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||||
stage.setTitle("Casono");
|
stage.setTitle("Casono");
|
||||||
@@ -90,6 +96,7 @@ public class CasinoGameUI extends Application {
|
|||||||
|
|
||||||
stage.setScene(scene);
|
stage.setScene(scene);
|
||||||
stage.setFullScreen(true);
|
stage.setFullScreen(true);
|
||||||
|
stage.setOnHidden(e -> controller.stop());
|
||||||
stage.show();
|
stage.show();
|
||||||
|
|
||||||
controller.start();
|
controller.start();
|
||||||
|
|||||||
+44
@@ -1,10 +1,14 @@
|
|||||||
package ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui;
|
package ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui;
|
||||||
|
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.ClientApp;
|
import ch.unibas.dmi.dbis.cs108.casono.client.ClientApp;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatController;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService;
|
import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.network.LobbyClient;
|
import ch.unibas.dmi.dbis.cs108.casono.client.network.LobbyClient;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.Alert.AlertType;
|
import javafx.scene.control.Alert.AlertType;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
@@ -13,6 +17,7 @@ import javafx.scene.control.TextField;
|
|||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
|
import javafx.scene.Node;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.scene.shape.Rectangle;
|
import javafx.scene.shape.Rectangle;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
@@ -31,11 +36,13 @@ public class CasinomainuiController {
|
|||||||
@FXML private VBox casinoTable;
|
@FXML private VBox casinoTable;
|
||||||
@FXML private TextField usernameField;
|
@FXML private TextField usernameField;
|
||||||
@FXML private Button loginButton;
|
@FXML private Button loginButton;
|
||||||
|
@FXML private AnchorPane chatContainer;
|
||||||
|
|
||||||
private LobbyButtonTranslationManager translationManager;
|
private LobbyButtonTranslationManager translationManager;
|
||||||
private LobbyButtonGridManager gridManager;
|
private LobbyButtonGridManager gridManager;
|
||||||
private int nextButtonId = 1;
|
private int nextButtonId = 1;
|
||||||
private LobbyClient lobbyClient;
|
private LobbyClient lobbyClient;
|
||||||
|
private ChatController chatController;
|
||||||
|
|
||||||
/** Default constructor used by FXMLLoader. */
|
/** Default constructor used by FXMLLoader. */
|
||||||
public CasinomainuiController() {
|
public CasinomainuiController() {
|
||||||
@@ -96,6 +103,40 @@ public class CasinomainuiController {
|
|||||||
casinoTable.getChildren().clear();
|
casinoTable.getChildren().clear();
|
||||||
casinoTable.getChildren().add(gridManager.getGridPane());
|
casinoTable.getChildren().add(gridManager.getGridPane());
|
||||||
gridManager.renderLobbyButtons();
|
gridManager.renderLobbyButtons();
|
||||||
|
|
||||||
|
initializeChat(clientService);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeChat(ClientService clientService) {
|
||||||
|
if (clientService == null || clientService.isOffline() || chatContainer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String username = resolveChatUsername();
|
||||||
|
chatController = new ChatController(username, clientService);
|
||||||
|
URL resource = getClass().getResource("/ui-structure/components/chatui/chatbox.fxml");
|
||||||
|
FXMLLoader loader = new FXMLLoader(resource);
|
||||||
|
loader.setController(chatController.getChatBoxController());
|
||||||
|
Node chatNode = loader.load();
|
||||||
|
chatContainer.getChildren().setAll(chatNode);
|
||||||
|
AnchorPane.setTopAnchor(chatNode, 0.0);
|
||||||
|
AnchorPane.setBottomAnchor(chatNode, 0.0);
|
||||||
|
AnchorPane.setLeftAnchor(chatNode, 0.0);
|
||||||
|
AnchorPane.setRightAnchor(chatNode, 0.0);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.warn("Could not initialize lobby chat UI: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveChatUsername() {
|
||||||
|
String shared = ClientApp.getSharedUsername();
|
||||||
|
if (shared != null && !shared.isBlank()) {
|
||||||
|
return shared.trim();
|
||||||
|
}
|
||||||
|
if (usernameField != null && usernameField.getText() != null && !usernameField.getText().isBlank()) {
|
||||||
|
return usernameField.getText().trim();
|
||||||
|
}
|
||||||
|
return "Guest";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Handles the login button action. Validates input and calls LobbyClient.login(). */
|
/** Handles the login button action. Validates input and calls LobbyClient.login(). */
|
||||||
@@ -139,6 +180,9 @@ public class CasinomainuiController {
|
|||||||
/** Handles the exit button action to close the application. */
|
/** Handles the exit button action to close the application. */
|
||||||
@FXML
|
@FXML
|
||||||
public void handleexitbutton() {
|
public void handleexitbutton() {
|
||||||
|
if (chatController != null) {
|
||||||
|
chatController.shutdown();
|
||||||
|
}
|
||||||
Platform.exit();
|
Platform.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
@@ -554,6 +554,7 @@ public class LobbyButtonGridManager {
|
|||||||
var cs = lobbyClient.getClientService();
|
var cs = lobbyClient.getClientService();
|
||||||
|
|
||||||
ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.CasinoGameUI.setClientService(cs);
|
ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.CasinoGameUI.setClientService(cs);
|
||||||
|
ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.CasinoGameUI.setLobbyId(lobbyId);
|
||||||
|
|
||||||
String username = ch.unibas.dmi.dbis.cs108.casono.client.ClientApp.getSharedUsername();
|
String username = ch.unibas.dmi.dbis.cs108.casono.client.ClientApp.getSharedUsername();
|
||||||
if (username == null || username.isBlank()) {
|
if (username == null || username.isBlank()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user