From 6a2ba24afc93af4546edf4933a8c0db688c1efc9 Mon Sep 17 00:00:00 2001 From: Lorenzo <10797603@polimi.it> Date: Wed, 26 Jun 2024 14:16:00 +0200 Subject: [PATCH 1/5] Asking for local IPv4 address if RMI is selected in TUI --- .../ingsw/am32/client/view/tui/TextUI.java | 31 +++++++++++++ .../ingsw/am32/utilities/IPAddressFinder.java | 43 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/main/java/it/polimi/ingsw/am32/utilities/IPAddressFinder.java diff --git a/src/main/java/it/polimi/ingsw/am32/client/view/tui/TextUI.java b/src/main/java/it/polimi/ingsw/am32/client/view/tui/TextUI.java index 5d713032..94b7f686 100644 --- a/src/main/java/it/polimi/ingsw/am32/client/view/tui/TextUI.java +++ b/src/main/java/it/polimi/ingsw/am32/client/view/tui/TextUI.java @@ -1,6 +1,7 @@ package it.polimi.ingsw.am32.client.view.tui; import it.polimi.ingsw.am32.network.exceptions.ConnectionSetupFailedException; +import it.polimi.ingsw.am32.utilities.IPAddressFinder; import it.polimi.ingsw.am32.utilities.IsValid; import it.polimi.ingsw.am32.client.*; import it.polimi.ingsw.am32.message.ClientToServer.*; @@ -314,7 +315,10 @@ public void chooseConnection() { port = getInputInt(); // Ask the player to re-enter the port number } + String localIP = askForLocalIPAddress(); // Ask the player to choose the correct IPv4 address + try { + System.setProperty("java.rmi.server.hostname", localIP); // Workaround for RMI setRMIClient(serverIP, port); // Set the RMI client isConnected = true; // Set the connection status to true } catch (ConnectionSetupFailedException e) { @@ -337,6 +341,33 @@ public void chooseConnection() { } while (!isConnected); // Keep looping until the connection is established } + /** + * Method used to ask the player the correct IP address associated with the current machine. + * If the list of IPv4 addresses is empty, the method will return "127.0.0.1" aka localhost. + * @return The correct IPv4 address associated with the current machine + */ + private String askForLocalIPAddress() { + // We are going to use IPAddressFinder.getIPv4Addresses() to get the list of IPv4 addresses associated with the current machine + List ipv4Addresses = IPAddressFinder.getIPv4Addresses(); + // If the list is empty, we will return localhost aka "127.0.0.1" + if (ipv4Addresses.isEmpty()) { + return "127.0.0.1"; + } + // If the list is not empty, we will ask the user to choose one of the IPv4 addresses + out.println("Choose the correct IPv4 address associated with the current machine:"); + for (int i = 0; i < ipv4Addresses.size(); i++) { + out.println((i + 1) + ". " + ipv4Addresses.get(i)); + } + int choice = getInputInt(); + // We will keep asking the user to choose a valid number until they do so + while (choice < 1 || choice > ipv4Addresses.size()) { + out.println("Invalid choice, please select a number between 1 and " + ipv4Addresses.size()); + choice = getInputInt(); + } + // We will return the chosen IPv4 address + return ipv4Addresses.get(choice - 1); + } + /** * Method that sets the socket client with the server IP and the server port entered by the player and attempts to * establish the connection between the client and the server. diff --git a/src/main/java/it/polimi/ingsw/am32/utilities/IPAddressFinder.java b/src/main/java/it/polimi/ingsw/am32/utilities/IPAddressFinder.java new file mode 100644 index 00000000..19025f3c --- /dev/null +++ b/src/main/java/it/polimi/ingsw/am32/utilities/IPAddressFinder.java @@ -0,0 +1,43 @@ +package it.polimi.ingsw.am32.utilities; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * This class is used to find all IPv4 addresses of the current machine. + */ +public class IPAddressFinder { + + /** + * This method returns a list of all IPv4 addresses of the current machine. + * It iterates over all network interfaces and their associated addresses. + * If an address is an instance of Inet4Address, it is added to the list. + * + * @return A list of strings representing the IPv4 addresses. + */ + public static List getIPv4Addresses() { + // Create an empty list of strings to store the IPv4 addresses. + List ipv4Addresses = new ArrayList<>(); + try { + // Iterate over all network interfaces. + for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces())) { + // Iterate over all addresses associated with the current network interface. + for (InetAddress inetAddress : Collections.list(networkInterface.getInetAddresses())) { + // If the address is an instance of Inet4Address, add it to the list. + if (inetAddress instanceof Inet4Address) { + ipv4Addresses.add(inetAddress.getHostAddress()); + } + } + } + } catch (SocketException ignored) { + // If an exception occurs, the list of addresses will be empty. + } + return ipv4Addresses; + } + +} From 80362c83193e766786860279a597392a2ffea748 Mon Sep 17 00:00:00 2001 From: Lorenzo Date: Wed, 26 Jun 2024 15:44:19 +0200 Subject: [PATCH 2/5] Property set working in TUI --- src/main/java/it/polimi/ingsw/am32/client/view/tui/TextUI.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/it/polimi/ingsw/am32/client/view/tui/TextUI.java b/src/main/java/it/polimi/ingsw/am32/client/view/tui/TextUI.java index 94b7f686..336bc275 100644 --- a/src/main/java/it/polimi/ingsw/am32/client/view/tui/TextUI.java +++ b/src/main/java/it/polimi/ingsw/am32/client/view/tui/TextUI.java @@ -319,6 +319,7 @@ public void chooseConnection() { try { System.setProperty("java.rmi.server.hostname", localIP); // Workaround for RMI + out.println("Set RMI localIP to " + localIP); setRMIClient(serverIP, port); // Set the RMI client isConnected = true; // Set the connection status to true } catch (ConnectionSetupFailedException e) { From 9e915bf8cd19f7b57e3a59bf7cf2d0bf57fbbdfe Mon Sep 17 00:00:00 2001 From: Lorenzo <10797603@polimi.it> Date: Wed, 26 Jun 2024 17:23:46 +0200 Subject: [PATCH 3/5] Added needed GUI components in GraphicalUI.java --- .../am32/client/view/gui/GraphicalUI.java | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUI.java b/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUI.java index f031399e..68219cee 100644 --- a/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUI.java +++ b/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUI.java @@ -3,6 +3,7 @@ import it.polimi.ingsw.am32.client.*; import it.polimi.ingsw.am32.message.ClientToServer.*; import it.polimi.ingsw.am32.network.exceptions.ConnectionSetupFailedException; +import it.polimi.ingsw.am32.utilities.IPAddressFinder; import javafx.animation.*; import javafx.application.Application; import javafx.application.Platform; @@ -398,10 +399,11 @@ public void chooseConnection() { // create the RMI connection root StackPane RMIRoot = new StackPane(); Label labelRMIIP = createLabel("RMI", -80, -80); // add the title - TextField RMIIp = createTextField("Enter the IP", 35, 250, -50, -30); // create the text field asks the player to enter the IP address - TextField RMIPort = createTextField("Enter the port", 35, 250, -50, 50); // create the text field asks the player to enter the port number + TextField RMIIp = createTextField("Server IP", 30, 250, -50, -35); // create the text field asks the player to enter the IP address + TextField RMIPort = createTextField("Server Port", 30, 250, -50, 30); // create the text field asks the player to enter the port number Button OkRMIButton = createButton("[OK]", 160, 0); // create the button Ok to confirm the input. - RMIRoot.getChildren().addAll(OkRMIButton, labelRMIIP, RMIIp, RMIPort); // the view when the player choose the socket connection + ComboBox localIPAddress = createComboBox(IPAddressFinder.getIPv4Addresses(), "Select Client IP",25, 250, -50, 90); // ComboBox used to select the correct IPv4 address associated with the current machine + RMIRoot.getChildren().addAll(OkRMIButton, labelRMIIP, RMIIp, RMIPort, localIPAddress); // the view when the player choose the socket connection // set the action of the buttons (Socket) socketButton.setOnAction(e -> { @@ -1371,6 +1373,34 @@ private void createAlert(String reason) { }); } + /** + * Create a stylized ComboBox with the specified content, text, size and position. + * @implSpec GUI-NON-CORE + * @param content the content of the ComboBox + * @param text the text of the ComboBox + * @param MaxHeight the maximum height of the ComboBox + * @param MaxWidth the maximum width of the ComboBox + * @param X the X coordinate of the ComboBox + * @param Y the Y coordinate of the ComboBox + * @return The ComboBox created + */ + private ComboBox createComboBox(List content, String text, + int MaxHeight, int MaxWidth, int X, int Y){ + ComboBox newComboBox = new ComboBox<>(); + for(String string : content){ + newComboBox.getItems().add(string); + } + newComboBox.setStyle("-fx-background-color: #E6DEB3;-fx-text-fill: #3A2111;-fx-alignment: center;" + + "-fx-font-size: 20px;-fx-font-family: 'JejuHallasan';-fx-effect: dropshadow( gaussian , " + + "rgba(58,33,17,100,0.2) , 10,0,0,10 );-fx-border-color: #3A2111; -fx-border-width: 2px; " + + "-fx-border-radius: 5px; -fx-background-radius: 5px;"); + newComboBox.setPromptText(text); + newComboBox.setMaxSize(MaxWidth, MaxHeight); + newComboBox.setTranslateX(X); + newComboBox.setTranslateY(Y); + return newComboBox; + } + /** * Method used to show the field of the player whose nickname is passed as a parameter. * @implSpec GUI-NON-CORE From bb30bd46c5c6b3bf99db40613d8b34628728e91e Mon Sep 17 00:00:00 2001 From: Lorenzo <10797603@polimi.it> Date: Wed, 26 Jun 2024 17:32:58 +0200 Subject: [PATCH 4/5] Configured GUI to ask for local IPv4 address --- src/main/java/it/polimi/ingsw/am32/Client.java | 2 -- .../polimi/ingsw/am32/client/view/gui/GraphicalUI.java | 10 ++++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/am32/Client.java b/src/main/java/it/polimi/ingsw/am32/Client.java index 920a2071..344a06e8 100644 --- a/src/main/java/it/polimi/ingsw/am32/Client.java +++ b/src/main/java/it/polimi/ingsw/am32/Client.java @@ -32,8 +32,6 @@ public class Client { * @param args Command line arguments */ public static void main(String[] args){ - // FIXME: Set here the IP address of the Client in order to allow RMI to work - System.setProperty("java.rmi.server.hostname", "192.168.178.118"); // Configure log4j2 logger to log only warnings and above Log4J2ConfiguratorWrapper.setLogLevelAndConfigure(Level.WARN); out.println("Welcome to Codex Naturalis"); diff --git a/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUI.java b/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUI.java index 68219cee..6d643600 100644 --- a/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUI.java +++ b/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUI.java @@ -449,12 +449,14 @@ public void chooseConnection() { String ServerPort = RMIPort.getText(); try { int portNumber = Integer.parseInt(ServerPort); - if (isValid.isIpValid(ServerIP) && isValid.isPortValid(portNumber)) { // Check if the IP address is valid + if (isValid.isIpValid(ServerIP) && isValid.isPortValid(portNumber) + && localIPAddress.getValue() != null) { + System.setProperty("java.rmi.server.hostname", localIPAddress.getValue()); setRMIClient(ServerIP, portNumber); - selectionPane.getChildren().remove(RMIRoot); - askSelectGameMode(); + selectionPane.getChildren().remove(RMIRoot); + askSelectGameMode(); } else { - createAlert("Invalid IP/port number"); + createAlert("Check the configuration and try again!"); RMIIp.clear(); RMIPort.clear(); } From 91b0dd53e2be23379102d36f173aec0039251878 Mon Sep 17 00:00:00 2001 From: Lorenzo <10797603@polimi.it> Date: Wed, 26 Jun 2024 19:01:13 +0200 Subject: [PATCH 5/5] Updated README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index ae35b3bd..685d2168 100644 --- a/README.md +++ b/README.md @@ -28,12 +28,10 @@ The group members are: | Complete Rules + TUI + GUI + RMI or Socket + 1 FA (Chat) | 24 | ☑️ | | Complete Rules + TUI + GUI + RMI + Socket + 1 FA (Chat) | 27 | ☑️ | | Complete Rules + TUI + GUI + RMI + Socket + 2 FA (Chat & Multiple match) | 30 | ☑️ | -| Complete Rules + TUI + GUI + RMI + Socket + 3 FA (Chat & Multiple match & Disconnection resilience) | 30L | ⚠️ | +| Complete Rules + TUI + GUI + RMI + Socket + 3 FA (Chat & Multiple match & Disconnection resilience) | 30L | ☑️ | ### Currently Known Issues -- 🟥 The client must set its own IP address in the Client.java file in order to make RMI work. - ## Code Coverage The average code coverage, between Model and Controller, is 96% for methods and 85% for lines, all (known) edge cases are covered.