Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7cba7ac1dd | |||
| c83a360fec | |||
| 2631791330 |
Binary file not shown.
Binary file not shown.
@@ -39,10 +39,6 @@ public class ClientApp {
|
|||||||
return sharedUsername;
|
return sharedUsername;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateSharedUsername(String username) {
|
|
||||||
setSharedUsername(username != null && !username.isBlank() ? username.trim() : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void setSharedUsername(String username) {
|
private static void setSharedUsername(String username) {
|
||||||
sharedUsername = username;
|
sharedUsername = username;
|
||||||
LOGGER.info("sharedUsername set to '{}'", getSharedUsername());
|
LOGGER.info("sharedUsername set to '{}'", getSharedUsername());
|
||||||
|
|||||||
@@ -1,20 +1,15 @@
|
|||||||
package ch.unibas.dmi.dbis.cs108.casono.client.chat;
|
package ch.unibas.dmi.dbis.cs108.casono.client.chat;
|
||||||
|
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.ClientApp;
|
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.network.ChatClient;
|
import ch.unibas.dmi.dbis.cs108.casono.client.network.ChatClient;
|
||||||
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.ui.chatui.ChatBoxController;
|
import ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui.ChatBoxController;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.RequestParameter;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
@@ -29,7 +24,7 @@ public class ChatController {
|
|||||||
private static final Map<ClientService, ChatController> ACTIVE_CONTROLLERS =
|
private static final Map<ClientService, ChatController> ACTIVE_CONTROLLERS =
|
||||||
new WeakHashMap<>();
|
new WeakHashMap<>();
|
||||||
|
|
||||||
private volatile String username;
|
private final String username;
|
||||||
|
|
||||||
private final ClientService clientService;
|
private final ClientService clientService;
|
||||||
|
|
||||||
@@ -42,7 +37,6 @@ public class ChatController {
|
|||||||
private final ChatBoxController chatBoxController;
|
private final ChatBoxController chatBoxController;
|
||||||
private int lobbyId = -1;
|
private int lobbyId = -1;
|
||||||
private final Timer timer;
|
private final Timer timer;
|
||||||
private final Consumer<List<String>> serverEventListener;
|
|
||||||
|
|
||||||
public record ChatKey(ChatType type, @Nullable String targetUser) {
|
public record ChatKey(ChatType type, @Nullable String targetUser) {
|
||||||
public ChatKey(ChatType type) {
|
public ChatKey(ChatType type) {
|
||||||
@@ -77,10 +71,8 @@ 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.serverEventListener = this::handleServerEvent;
|
|
||||||
|
|
||||||
registerAsActiveController(clientService);
|
registerAsActiveController(clientService);
|
||||||
clientService.addEventListener(serverEventListener);
|
|
||||||
|
|
||||||
this.timer = new Timer(true);
|
this.timer = new Timer(true);
|
||||||
timer.schedule(
|
timer.schedule(
|
||||||
@@ -139,7 +131,6 @@ public class ChatController {
|
|||||||
* <p>All Messages get added to a particular {@link ChatModel}, if the checks passed.
|
* <p>All Messages get added to a particular {@link ChatModel}, if the checks passed.
|
||||||
*/
|
*/
|
||||||
public void receiveMessage() {
|
public void receiveMessage() {
|
||||||
String currentUsername = getCurrentUsername();
|
|
||||||
List<Message> newMessages = chatClient.getMessages();
|
List<Message> newMessages = chatClient.getMessages();
|
||||||
if (!newMessages.isEmpty()) {
|
if (!newMessages.isEmpty()) {
|
||||||
for (Message msg : newMessages) {
|
for (Message msg : newMessages) {
|
||||||
@@ -155,17 +146,16 @@ public class ChatController {
|
|||||||
(_key) ->
|
(_key) ->
|
||||||
new ChatModel(
|
new ChatModel(
|
||||||
ChatType.LOBBY,
|
ChatType.LOBBY,
|
||||||
currentUsername,
|
username,
|
||||||
msg.lobbyId,
|
msg.lobbyId,
|
||||||
null))
|
null))
|
||||||
.addMessage(msg);
|
.addMessage(msg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ChatType.WHISPER:
|
case ChatType.WHISPER:
|
||||||
if (msg.target.equals(currentUsername)
|
if (msg.target.equals(username) || msg.sender.equals(username)) {
|
||||||
|| msg.sender.equals(currentUsername)) {
|
|
||||||
ChatKey key;
|
ChatKey key;
|
||||||
if (msg.target.equals(currentUsername)) {
|
if (msg.target.equals(username)) {
|
||||||
key = new ChatKey(ChatType.WHISPER, msg.sender);
|
key = new ChatKey(ChatType.WHISPER, msg.sender);
|
||||||
} else {
|
} else {
|
||||||
key = new ChatKey(ChatType.WHISPER, msg.target);
|
key = new ChatKey(ChatType.WHISPER, msg.target);
|
||||||
@@ -176,7 +166,7 @@ public class ChatController {
|
|||||||
ChatModel chatModel =
|
ChatModel chatModel =
|
||||||
new ChatModel(
|
new ChatModel(
|
||||||
ChatType.WHISPER,
|
ChatType.WHISPER,
|
||||||
currentUsername,
|
username,
|
||||||
lobbyId,
|
lobbyId,
|
||||||
key.targetUser());
|
key.targetUser());
|
||||||
chatBoxController.addWhisperChat(key.targetUser(), chatModel);
|
chatBoxController.addWhisperChat(key.targetUser(), chatModel);
|
||||||
@@ -213,29 +203,13 @@ public class ChatController {
|
|||||||
*/
|
*/
|
||||||
public synchronized void checkWhisperUsers() {
|
public synchronized void checkWhisperUsers() {
|
||||||
List<String> users = chatClient.getUsers();
|
List<String> users = chatClient.getUsers();
|
||||||
Set<String> remoteUsers = new HashSet<>();
|
logger.info(users);
|
||||||
String currentUsername = getCurrentUsername();
|
if (!users.isEmpty()) {
|
||||||
|
for (String user : users) {
|
||||||
for (String user : users) {
|
String value = user.split("\\=")[1];
|
||||||
if (user == null || !user.contains("=")) {
|
logger.info(value);
|
||||||
continue;
|
addWhisperUser(value);
|
||||||
}
|
}
|
||||||
String value = user.split("\\=", 2)[1].trim();
|
|
||||||
if (value.isBlank() || value.equals(currentUsername)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
remoteUsers.add(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String known : new ArrayList<>(localUserList)) {
|
|
||||||
if (!remoteUsers.contains(known)) {
|
|
||||||
localUserList.remove(known);
|
|
||||||
chatBoxController.removeWhisperUser(known);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String remote : remoteUsers) {
|
|
||||||
addWhisperUser(remote);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,110 +222,16 @@ public class ChatController {
|
|||||||
if (user == null || user.isBlank()) {
|
if (user == null || user.isBlank()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(localUserList.contains(user) || user.equals(getCurrentUsername()))) {
|
if (!(localUserList.contains(user) || user.equals(username))) {
|
||||||
localUserList.add(user);
|
localUserList.add(user);
|
||||||
logger.info("adding new whisper user");
|
logger.info("adding new whisper user");
|
||||||
chatBoxController.addWhisperUser(user);
|
chatBoxController.addWhisperUser(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void updateUsername(String newUsername) {
|
|
||||||
if (newUsername == null || newUsername.isBlank()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String oldUsername = this.username;
|
|
||||||
this.username = newUsername.trim();
|
|
||||||
chatBoxController.setUsername(this.username);
|
|
||||||
|
|
||||||
if (oldUsername != null && !oldUsername.equals(this.username)) {
|
|
||||||
localUserList.remove(oldUsername);
|
|
||||||
chatBoxController.removeWhisperUser(oldUsername);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleServerEvent(List<String> lines) {
|
|
||||||
if (lines == null || lines.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<RequestParameter> params;
|
|
||||||
try {
|
|
||||||
params = ClientService.convertToRequestParameters(lines);
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String event = null;
|
|
||||||
String oldUsername = null;
|
|
||||||
String newUsername = null;
|
|
||||||
|
|
||||||
for (RequestParameter p : params) {
|
|
||||||
if ("EVENT".equalsIgnoreCase(p.key())) {
|
|
||||||
event = p.value();
|
|
||||||
} else if ("OLD_USERNAME".equalsIgnoreCase(p.key())) {
|
|
||||||
oldUsername = p.value();
|
|
||||||
} else if ("NEW_USERNAME".equalsIgnoreCase(p.key())) {
|
|
||||||
newUsername = p.value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!"USERNAME_CHANGED".equalsIgnoreCase(event)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
applyUsernameMigration(oldUsername, newUsername);
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void applyUsernameMigration(String oldUsername, String newUsername) {
|
|
||||||
if (oldUsername == null
|
|
||||||
|| newUsername == null
|
|
||||||
|| oldUsername.isBlank()
|
|
||||||
|| newUsername.isBlank()
|
|
||||||
|| oldUsername.equals(newUsername)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String currentUsername = getCurrentUsername();
|
|
||||||
if (oldUsername.equals(currentUsername)) {
|
|
||||||
updateUsername(newUsername);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatKey oldKey = new ChatKey(ChatType.WHISPER, oldUsername);
|
|
||||||
ChatKey newKey = new ChatKey(ChatType.WHISPER, newUsername);
|
|
||||||
|
|
||||||
ChatModel oldModel = chatModelMap.remove(oldKey);
|
|
||||||
ChatModel existingNewModel = chatModelMap.get(newKey);
|
|
||||||
if (oldModel != null) {
|
|
||||||
oldModel.setTarget(newUsername);
|
|
||||||
if (existingNewModel == null) {
|
|
||||||
chatModelMap.put(newKey, oldModel);
|
|
||||||
} else {
|
|
||||||
// Merge possible parallel history into the already existing new-key model.
|
|
||||||
for (Message msg : oldModel.messages) {
|
|
||||||
existingNewModel.addMessage(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chatBoxController.renameWhisperUser(oldUsername, newUsername);
|
|
||||||
}
|
|
||||||
|
|
||||||
localUserList.remove(oldUsername);
|
|
||||||
chatBoxController.removeWhisperUser(oldUsername);
|
|
||||||
if (!newUsername.equals(getCurrentUsername())) {
|
|
||||||
addWhisperUser(newUsername);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCurrentUsername() {
|
|
||||||
String shared = ClientApp.getSharedUsername();
|
|
||||||
if (shared != null && !shared.isBlank()) {
|
|
||||||
return shared.trim();
|
|
||||||
}
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Stops polling background tasks for this chat controller instance. */
|
/** Stops polling background tasks for this chat controller instance. */
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
timer.cancel();
|
timer.cancel();
|
||||||
clientService.removeEventListener(serverEventListener);
|
|
||||||
synchronized (ACTIVE_CONTROLLERS) {
|
synchronized (ACTIVE_CONTROLLERS) {
|
||||||
if (ACTIVE_CONTROLLERS.get(clientService) == this) {
|
if (ACTIVE_CONTROLLERS.get(clientService) == this) {
|
||||||
ACTIVE_CONTROLLERS.remove(clientService);
|
ACTIVE_CONTROLLERS.remove(clientService);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class ChatModel {
|
|||||||
public final String username;
|
public final String username;
|
||||||
|
|
||||||
/** The person to send the message to If the chat is a whisper chat */
|
/** The person to send the message to If the chat is a whisper chat */
|
||||||
private String target;
|
private final String target;
|
||||||
|
|
||||||
private final IntegerProperty count;
|
private final IntegerProperty count;
|
||||||
|
|
||||||
@@ -82,8 +82,4 @@ public class ChatModel {
|
|||||||
public String getTarget() {
|
public String getTarget() {
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTarget(String target) {
|
|
||||||
this.target = target;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,29 +131,6 @@ public class LobbyClient {
|
|||||||
return new LoginResult(assigned, id);
|
return new LoginResult(assigned, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the username for the currently logged-in session.
|
|
||||||
*
|
|
||||||
* @param newUsername desired new username
|
|
||||||
* @return a {@link LoginResult} containing assigned username and id as returned by the server
|
|
||||||
*/
|
|
||||||
public LoginResult changeUsername(String newUsername) {
|
|
||||||
List<String> lines = client.processCommand("CHANGE_USERNAME USERNAME=" + newUsername);
|
|
||||||
|
|
||||||
List<RequestParameter> params = ClientService.convertToRequestParameters(lines);
|
|
||||||
|
|
||||||
String assigned = newUsername;
|
|
||||||
String id = null;
|
|
||||||
for (RequestParameter p : params) {
|
|
||||||
if ("USERNAME".equalsIgnoreCase(p.key())) {
|
|
||||||
assigned = p.value();
|
|
||||||
} else if ("ID".equalsIgnoreCase(p.key())) {
|
|
||||||
id = p.value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new LoginResult(assigned, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request the server for the list of available lobbies.
|
* Request the server for the list of available lobbies.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -60,12 +60,6 @@ public class ChatBoxController {
|
|||||||
usernameTabMap = new HashMap<>();
|
usernameTabMap = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUsername(String username) {
|
|
||||||
if (username != null && !username.isBlank()) {
|
|
||||||
this.username = username.trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the chat interface by creating the global chat model and adding the corresponding
|
* Initializes the chat interface by creating the global chat model and adding the corresponding
|
||||||
* "GLOBAL" tab to the interface. It also registers the global chat in the {@link
|
* "GLOBAL" tab to the interface. It also registers the global chat in the {@link
|
||||||
@@ -90,11 +84,6 @@ public class ChatBoxController {
|
|||||||
public void addWhisperUser(String targetUserName) {
|
public void addWhisperUser(String targetUserName) {
|
||||||
Platform.runLater(
|
Platform.runLater(
|
||||||
() -> {
|
() -> {
|
||||||
for (MenuItem existing : addWhisperChatButton.getItems()) {
|
|
||||||
if (targetUserName.equals(existing.getText())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MenuItem menuItem = new MenuItem(targetUserName);
|
MenuItem menuItem = new MenuItem(targetUserName);
|
||||||
addWhisperChatButton.getItems().add(menuItem);
|
addWhisperChatButton.getItems().add(menuItem);
|
||||||
menuItem.setOnAction(
|
menuItem.setOnAction(
|
||||||
@@ -109,54 +98,6 @@ public class ChatBoxController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeWhisperUser(String targetUserName) {
|
|
||||||
Platform.runLater(
|
|
||||||
() ->
|
|
||||||
addWhisperChatButton
|
|
||||||
.getItems()
|
|
||||||
.removeIf(item -> targetUserName.equals(item.getText())));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void renameWhisperUser(String oldUsername, String newUsername) {
|
|
||||||
if (oldUsername == null
|
|
||||||
|| newUsername == null
|
|
||||||
|| oldUsername.isBlank()
|
|
||||||
|| newUsername.isBlank()
|
|
||||||
|| oldUsername.equals(newUsername)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Platform.runLater(
|
|
||||||
() -> {
|
|
||||||
for (MenuItem item : addWhisperChatButton.getItems()) {
|
|
||||||
if (oldUsername.equals(item.getText())) {
|
|
||||||
item.setText(newUsername);
|
|
||||||
item.setOnAction(
|
|
||||||
event ->
|
|
||||||
addWhisperChat(
|
|
||||||
newUsername,
|
|
||||||
new ChatModel(
|
|
||||||
ChatType.WHISPER,
|
|
||||||
username,
|
|
||||||
-1,
|
|
||||||
newUsername)));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Tab tab = usernameTabMap.remove(oldUsername);
|
|
||||||
if (tab != null) {
|
|
||||||
tab.setText(newUsername);
|
|
||||||
usernameTabMap.put(newUsername, tab);
|
|
||||||
}
|
|
||||||
|
|
||||||
int idx = activeWhisperChats.indexOf(oldUsername);
|
|
||||||
if (idx >= 0) {
|
|
||||||
activeWhisperChats.set(idx, newUsername);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new private (whisper) chat model for a specific target user, registers it within
|
* Creates a new private (whisper) chat model for a specific target user, registers it within
|
||||||
* the chat system, and opens a new chat tab.
|
* the chat system, and opens a new chat tab.
|
||||||
|
|||||||
+1
-2
@@ -68,12 +68,11 @@ public class ChatViewController implements Initializable {
|
|||||||
String message = inputField.getText().trim();
|
String message = inputField.getText().trim();
|
||||||
if (!message.isEmpty()) {
|
if (!message.isEmpty()) {
|
||||||
inputField.clear();
|
inputField.clear();
|
||||||
String currentUsername = controller.getCurrentUsername();
|
|
||||||
Message msg =
|
Message msg =
|
||||||
new Message(
|
new Message(
|
||||||
chatModel.getChattype(),
|
chatModel.getChattype(),
|
||||||
chatModel.lobbyId,
|
chatModel.lobbyId,
|
||||||
currentUsername,
|
username,
|
||||||
chatModel.getTarget(),
|
chatModel.getTarget(),
|
||||||
message);
|
message);
|
||||||
controller.onSendToNetwork(msg);
|
controller.onSendToNetwork(msg);
|
||||||
|
|||||||
+5
-63
@@ -104,13 +104,6 @@ public class CasinomainuiController {
|
|||||||
casinoTable.getChildren().add(gridManager.getGridPane());
|
casinoTable.getChildren().add(gridManager.getGridPane());
|
||||||
gridManager.renderLobbyButtons();
|
gridManager.renderLobbyButtons();
|
||||||
|
|
||||||
String sharedUsername = ClientApp.getSharedUsername();
|
|
||||||
updateUsernameFieldPresentation(sharedUsername);
|
|
||||||
if (loginButton != null) {
|
|
||||||
loginButton.setText(
|
|
||||||
sharedUsername != null && !sharedUsername.isBlank() ? "Change Name" : "Login");
|
|
||||||
}
|
|
||||||
|
|
||||||
initializeChat(clientService);
|
initializeChat(clientService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +156,7 @@ public class CasinomainuiController {
|
|||||||
/** Handles the login button action. Validates input and calls LobbyClient.login(). */
|
/** Handles the login button action. Validates input and calls LobbyClient.login(). */
|
||||||
@FXML
|
@FXML
|
||||||
public void handleLoginButton() {
|
public void handleLoginButton() {
|
||||||
String username = usernameField == null ? null : usernameField.getText();
|
String username = usernameField.getText();
|
||||||
if (username == null || username.isBlank()) {
|
if (username == null || username.isBlank()) {
|
||||||
showAlert("Please enter a username.");
|
showAlert("Please enter a username.");
|
||||||
return;
|
return;
|
||||||
@@ -177,63 +170,12 @@ public class CasinomainuiController {
|
|||||||
showAlert("Offline mode: cannot send login to server.");
|
showAlert("Offline mode: cannot send login to server.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String trimmed = username.trim();
|
|
||||||
try {
|
try {
|
||||||
var result = lobbyClient.login(trimmed);
|
lobbyClient.login(username);
|
||||||
String assigned = result != null ? result.getUsername() : trimmed;
|
showAlert("Login sent: " + username);
|
||||||
ClientApp.updateSharedUsername(assigned);
|
|
||||||
if (chatController != null) {
|
|
||||||
chatController.updateUsername(assigned);
|
|
||||||
}
|
|
||||||
updateUsernameFieldPresentation(assigned);
|
|
||||||
if (loginButton != null) {
|
|
||||||
loginButton.setText("Change Name");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} catch (RuntimeException loginError) {
|
|
||||||
if (!containsProtocolError(loginError, "ALREADY_LOGGED_IN")) {
|
|
||||||
LOGGER.error("Login failed: {}", loginError.getMessage());
|
|
||||||
showAlert("Login failed: " + loginError.getMessage());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LOGGER.info("Session already logged in, trying username change");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
var result = lobbyClient.changeUsername(trimmed);
|
|
||||||
String assigned = result != null ? result.getUsername() : trimmed;
|
|
||||||
ClientApp.updateSharedUsername(assigned);
|
|
||||||
if (chatController != null) {
|
|
||||||
chatController.updateUsername(assigned);
|
|
||||||
}
|
|
||||||
updateUsernameFieldPresentation(assigned);
|
|
||||||
if (loginButton != null) {
|
|
||||||
loginButton.setText("Change Name");
|
|
||||||
}
|
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
LOGGER.error("Change username failed: {}", e.getMessage());
|
LOGGER.error("Login failed: {}", e.getMessage());
|
||||||
showAlert("Change username failed: " + e.getMessage());
|
showAlert("Login failed: " + e.getMessage());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean containsProtocolError(RuntimeException error, String code) {
|
|
||||||
String msg = error.getMessage();
|
|
||||||
return msg != null && msg.contains(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateUsernameFieldPresentation(String username) {
|
|
||||||
if (usernameField == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (username != null && !username.isBlank()) {
|
|
||||||
usernameField.setText(username.trim());
|
|
||||||
usernameField.positionCaret(usernameField.getText().length());
|
|
||||||
usernameField.setPromptText("Username");
|
|
||||||
} else {
|
|
||||||
usernameField.clear();
|
|
||||||
usernameField.setPromptText("Username");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-6
@@ -9,7 +9,6 @@ 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.command.execution.CommandHandler;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.OkResponse;
|
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 ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class SendMessageHandler extends CommandHandler<SendMessageRequest> {
|
public class SendMessageHandler extends CommandHandler<SendMessageRequest> {
|
||||||
private final UserRegistry userRegistry;
|
private final UserRegistry userRegistry;
|
||||||
@@ -40,11 +39,6 @@ public class SendMessageHandler extends CommandHandler<SendMessageRequest> {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(SendMessageRequest request) {
|
public void execute(SendMessageRequest request) {
|
||||||
Message message = request.getMessage();
|
Message message = request.getMessage();
|
||||||
Optional<ch.unibas.dmi.dbis.cs108.casono.server.domain.user.User> senderUser =
|
|
||||||
userRegistry.getBySessionId(request.getSessionId());
|
|
||||||
if (senderUser.isPresent()) {
|
|
||||||
message.sender = senderUser.get().getName();
|
|
||||||
}
|
|
||||||
broadcast(request, message);
|
broadcast(request, message);
|
||||||
OkResponse response = new OkResponse(request.getContext());
|
OkResponse response = new OkResponse(request.getContext());
|
||||||
responseDispatcher.dispatch(response);
|
responseDispatcher.dispatch(response);
|
||||||
|
|||||||
@@ -61,35 +61,6 @@ public class GameController {
|
|||||||
engine.getState().addPlayer(name, chips);
|
engine.getState().addPlayer(name, chips);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Renames a player id in the controller list and underlying game state.
|
|
||||||
*
|
|
||||||
* @param oldId old player id
|
|
||||||
* @param newId new player id
|
|
||||||
* @return true if rename succeeded
|
|
||||||
*/
|
|
||||||
public boolean renamePlayer(PlayerId oldId, PlayerId newId) {
|
|
||||||
if (oldId == null || newId == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (oldId.equals(newId)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int idx = players.indexOf(oldId);
|
|
||||||
if (idx < 0 || players.contains(newId)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean stateRenamed = engine.getState().renamePlayerId(oldId, newId);
|
|
||||||
if (!stateRenamed) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
players.set(idx, newId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new hand by preparing the deck, setting the phase to PREFLOP, rotating the
|
* Initializes a new hand by preparing the deck, setting the phase to PREFLOP, rotating the
|
||||||
* dealer, dealing hole cards, posting blinds, and setting the first active player.
|
* dealer, dealing hole cards, posting blinds, and setting the first active player.
|
||||||
|
|||||||
@@ -49,16 +49,6 @@ public class Player {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the player's id. This is used when a username change is propagated into an already
|
|
||||||
* running game.
|
|
||||||
*
|
|
||||||
* @param id new player id
|
|
||||||
*/
|
|
||||||
public void setId(PlayerId id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the display name of the player. Currently identical to the player ID.
|
* Returns the display name of the player. Currently identical to the player ID.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -174,51 +174,6 @@ public class GameState {
|
|||||||
holeCards.computeIfAbsent(id, k -> new ArrayList<>());
|
holeCards.computeIfAbsent(id, k -> new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Renames a player id across all game-state structures.
|
|
||||||
*
|
|
||||||
* @param oldId existing player id
|
|
||||||
* @param newId new player id
|
|
||||||
* @return true if the rename was applied, false otherwise
|
|
||||||
*/
|
|
||||||
public synchronized boolean renamePlayerId(PlayerId oldId, PlayerId newId) {
|
|
||||||
if (oldId == null || newId == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!players.containsKey(oldId)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (oldId.equals(newId)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (players.containsKey(newId)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player player = players.remove(oldId);
|
|
||||||
if (player == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
player.setId(newId);
|
|
||||||
players.put(newId, player);
|
|
||||||
|
|
||||||
int idx = playerOrder.indexOf(oldId);
|
|
||||||
if (idx >= 0) {
|
|
||||||
playerOrder.set(idx, newId);
|
|
||||||
}
|
|
||||||
|
|
||||||
moveMapEntry(currentBets, oldId, newId, 0);
|
|
||||||
moveMapEntry(playerBetCommitments, oldId, newId, 0);
|
|
||||||
moveMapEntry(holeCards, oldId, newId, new ArrayList<>());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> void moveMapEntry(
|
|
||||||
Map<PlayerId, T> map, PlayerId oldId, PlayerId newId, T fallback) {
|
|
||||||
T value = map.remove(oldId);
|
|
||||||
map.put(newId, value != null ? value : fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Betting
|
// Betting
|
||||||
public int getCurrentBet(PlayerId playerId) {
|
public int getCurrentBet(PlayerId playerId) {
|
||||||
return currentBets.getOrDefault(playerId, 0);
|
return currentBets.getOrDefault(playerId, 0);
|
||||||
|
|||||||
@@ -70,30 +70,6 @@ public class Lobby {
|
|||||||
return playerNames.remove(playerName);
|
return playerNames.remove(playerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Renames a player in this lobby's player list.
|
|
||||||
*
|
|
||||||
* @param oldName old username
|
|
||||||
* @param newName new username
|
|
||||||
* @return true if renamed successfully
|
|
||||||
*/
|
|
||||||
public boolean renamePlayer(String oldName, String newName) {
|
|
||||||
if (oldName == null || newName == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
synchronized (playerNames) {
|
|
||||||
if (oldName.equals(newName)) {
|
|
||||||
return playerNames.contains(oldName);
|
|
||||||
}
|
|
||||||
int idx = playerNames.indexOf(oldName);
|
|
||||||
if (idx < 0 || playerNames.contains(newName)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
playerNames.set(idx, newName);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initGame(GameController controller) {
|
public void initGame(GameController controller) {
|
||||||
this.gameController = controller;
|
this.gameController = controller;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby;
|
package ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby;
|
||||||
|
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.player.PlayerId;
|
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.Lobby.AddResult;
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.Lobby.AddResult;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
@@ -171,56 +170,6 @@ public class LobbyManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Renames a player across lobby mapping, lobby player list and running game ids.
|
|
||||||
*
|
|
||||||
* @param oldUsername old username
|
|
||||||
* @param newUsername new username
|
|
||||||
* @return true if rename was applied
|
|
||||||
*/
|
|
||||||
public synchronized boolean renamePlayer(String oldUsername, String newUsername) {
|
|
||||||
if (oldUsername == null || newUsername == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (oldUsername.equals(newUsername)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
LobbyId lobbyId = playerToLobby.get(oldUsername);
|
|
||||||
if (lobbyId == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (playerToLobby.containsKey(newUsername)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Lobby lobby = activeLobbies.get(lobbyId);
|
|
||||||
if (lobby == null) {
|
|
||||||
playerToLobby.remove(oldUsername);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean lobbyRenamed = lobby.renamePlayer(oldUsername, newUsername);
|
|
||||||
if (!lobbyRenamed) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lobby.getGameController() != null) {
|
|
||||||
boolean gameRenamed =
|
|
||||||
lobby.getGameController()
|
|
||||||
.renamePlayer(PlayerId.of(oldUsername), PlayerId.of(newUsername));
|
|
||||||
if (!gameRenamed) {
|
|
||||||
// Best-effort rollback to keep structures consistent.
|
|
||||||
lobby.renamePlayer(newUsername, oldUsername);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
playerToLobby.remove(oldUsername);
|
|
||||||
playerToLobby.put(newUsername, lobbyId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply the given action to every player username in the lobby identified by {@code lobbyId}.
|
* Apply the given action to every player username in the lobby identified by {@code lobbyId}.
|
||||||
* This is a small helper that keeps iteration logic centralized and avoids leaking internal
|
* This is a small helper that keeps iteration logic centralized and avoids leaking internal
|
||||||
|
|||||||
@@ -200,10 +200,6 @@ public class UserRegistry {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.getName().equals(newName)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (byName.containsKey(newName)) {
|
if (byName.containsKey(newName)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,24 +81,25 @@
|
|||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<!-- Username input and login/change button -->
|
<!-- Username input and login button -->
|
||||||
<HBox alignment="CENTER_LEFT" spacing="10"
|
<!-- <HBox alignment="CENTER_LEFT" spacing="10"-->
|
||||||
GridPane.rowIndex="0"
|
<!-- GridPane.rowIndex="0"-->
|
||||||
GridPane.columnIndex="0"
|
<!-- GridPane.columnIndex="0"-->
|
||||||
GridPane.halignment="LEFT"
|
<!-- GridPane.halignment="LEFT"-->
|
||||||
GridPane.valignment="TOP">
|
<!-- GridPane.valignment="TOP">-->
|
||||||
<GridPane.margin>
|
<!-- <GridPane.margin>-->
|
||||||
<Insets top="100" left="20" />
|
<!-- <!– place below the 'CREATE A LOBBY' button –>-->
|
||||||
</GridPane.margin>
|
<!-- <Insets top="100" left="20" />-->
|
||||||
<TextField fx:id="usernameField"
|
<!-- </GridPane.margin>-->
|
||||||
promptText="Username"
|
<!-- <TextField fx:id="usernameField"-->
|
||||||
styleClass="gray-input-field"
|
<!-- promptText="Username"-->
|
||||||
maxWidth="180" />
|
<!-- styleClass="gray-input-field"-->
|
||||||
<Button text="Apply Name"
|
<!-- maxWidth="180" />-->
|
||||||
fx:id="loginButton"
|
<!-- <Button text="Login"-->
|
||||||
onAction="#handleLoginButton"
|
<!-- fx:id="loginButton"-->
|
||||||
styleClass="button-create-lobby" />
|
<!-- onAction="#handleLoginButton"-->
|
||||||
</HBox>
|
<!-- styleClass="button-create-lobby" />-->
|
||||||
|
<!-- </HBox>-->
|
||||||
|
|
||||||
<VBox fx:id="casinoTable"
|
<VBox fx:id="casinoTable"
|
||||||
alignment="CENTER"
|
alignment="CENTER"
|
||||||
|
|||||||
Reference in New Issue
Block a user