Login remake
This commit is contained in:
@@ -3,29 +3,36 @@ package it.polimi.ingsw.gc14.View.GUI;
|
||||
import it.polimi.ingsw.gc14.Controller.ClientController;
|
||||
import it.polimi.ingsw.gc14.Network.RMI.Client.RMIClient;
|
||||
import it.polimi.ingsw.gc14.Network.TCP.Client.TCPClient;
|
||||
import javafx.animation.*;
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.geometry.Rectangle2D;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.stage.Screen;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.ArrayList;
|
||||
import java.net.*;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
public class LoginFXMLController {
|
||||
|
||||
@FXML private ImageView backgroundImage;
|
||||
@FXML private TextField campoNome;
|
||||
@FXML private TextField campoNumPlayers;
|
||||
@FXML private TextField campoIP;
|
||||
@FXML private RadioButton btnRMI;
|
||||
@FXML private RadioButton btnTCP;
|
||||
@FXML private Button btnAccedi;
|
||||
@FXML private Label labelErrore;
|
||||
@FXML private ComboBox<String> comboInterfaccia;
|
||||
@FXML private VBox formPanel;
|
||||
@FXML private StackPane protocolToggle;
|
||||
@FXML private Region toggleThumb;
|
||||
@FXML private Label labelRMI;
|
||||
@FXML private Label labelTCP;
|
||||
|
||||
private boolean isRMI = true;
|
||||
private ClientController controller;
|
||||
|
||||
public void setController(ClientController controller) {
|
||||
@@ -34,83 +41,155 @@ public class LoginFXMLController {
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
ToggleGroup group = new ToggleGroup();
|
||||
btnRMI.setToggleGroup(group);
|
||||
btnTCP.setToggleGroup(group);
|
||||
// Background
|
||||
Image img = new Image(getClass().getResourceAsStream("/GUIImages/Background.png"));
|
||||
backgroundImage.setImage(img);
|
||||
Rectangle2D screenBounds = Screen.getPrimary().getBounds();
|
||||
backgroundImage.setFitWidth(screenBounds.getWidth());
|
||||
backgroundImage.setFitHeight(screenBounds.getHeight());
|
||||
|
||||
// Protocol toggle
|
||||
protocolToggle.setOnMouseClicked(e -> switchProtocol());
|
||||
protocolToggle.setStyle(protocolToggle.getStyle() + " -fx-cursor: hand;");
|
||||
|
||||
// Button hover
|
||||
final String BASE_BTN = btnAccedi.getStyle();
|
||||
btnAccedi.setOnMouseEntered(e -> btnAccedi.setStyle(BASE_BTN +
|
||||
"-fx-effect: dropshadow(gaussian, rgba(244,192,90,0.45), 18, 0, 0, 0);"));
|
||||
btnAccedi.setOnMouseExited(e -> btnAccedi.setStyle(BASE_BTN));
|
||||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
List<String> ips = new ArrayList<>();
|
||||
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
|
||||
while (interfaces.hasMoreElements()) {
|
||||
NetworkInterface ni = interfaces.nextElement();
|
||||
if (!ni.isUp() || ni.isLoopback() || ni.isVirtual()) continue;
|
||||
Enumeration<InetAddress> addresses = ni.getInetAddresses();
|
||||
while (addresses.hasMoreElements()) {
|
||||
InetAddress addr = addresses.nextElement();
|
||||
if (addr instanceof Inet4Address)
|
||||
ips.add(ni.getDisplayName() + " -> " + addr.getHostAddress());
|
||||
}
|
||||
}
|
||||
Platform.runLater(() -> {
|
||||
comboInterfaccia.getItems().addAll(ips);
|
||||
if (!ips.isEmpty()) comboInterfaccia.getSelectionModel().selectFirst();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Platform.runLater(() -> labelErrore.setText("Errore nel rilevare le interfacce."));
|
||||
}
|
||||
}).start();
|
||||
btnAccedi.setOnAction(e -> onAccediClick());
|
||||
}
|
||||
|
||||
private void switchProtocol() {
|
||||
isRMI = !isRMI;
|
||||
|
||||
TranslateTransition tt = new TranslateTransition(Duration.millis(200), toggleThumb);
|
||||
tt.setToX(isRMI ? 0 : 110);
|
||||
tt.play();
|
||||
|
||||
labelRMI.setStyle("-fx-font-family: 'Cinzel'; -fx-font-size: 11; -fx-font-weight: bold;" +
|
||||
"-fx-text-fill: " + (isRMI ? "#0c0601" : "rgba(244,192,90,0.55)") + ";");
|
||||
labelTCP.setStyle("-fx-font-family: 'Cinzel'; -fx-font-size: 11; -fx-font-weight: bold;" +
|
||||
"-fx-text-fill: " + (isRMI ? "rgba(244,192,90,0.55)" : "#0c0601") + ";");
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void onAccediClick() {
|
||||
String nome = campoNome.getText().trim();
|
||||
controller.setMyUsername(nome);
|
||||
String ip = campoIP.getText().trim();
|
||||
|
||||
if (nome.isEmpty()) {
|
||||
showError("Please select a name.");
|
||||
return;
|
||||
}
|
||||
|
||||
int numPlayers;
|
||||
try {
|
||||
numPlayers = Integer.parseInt(campoNumPlayers.getText().trim());
|
||||
} catch (NumberFormatException e) {
|
||||
labelErrore.setText("Numero giocatori non valido.");
|
||||
showError("Invalid number of players.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nome.isEmpty() || ip.isEmpty()) {
|
||||
labelErrore.setText("Compila tutti i campi.");
|
||||
return;
|
||||
}
|
||||
System.setProperty("java.rmi.server.hostname", ip);
|
||||
controller.setMyUsername(nome);
|
||||
|
||||
int networkType = btnRMI.isSelected() ? 0 : 1;
|
||||
String interfaccia = getInterfaccia();
|
||||
|
||||
// Stesso thread di rete che era in ClientLauncher
|
||||
// Resolve the local interface to use, then connect
|
||||
new Thread(() -> {
|
||||
if (networkType == 0) {
|
||||
RMIClient client = new RMIClient(controller, ip, 1099, interfaccia);
|
||||
if (client.connect(nome, numPlayers)) {
|
||||
controller.setClient(client);
|
||||
Platform.runLater(() ->{ labelErrore.setTextFill(Color.GREEN); labelErrore.setText("Connected successfully! Waiting other players");});
|
||||
} else {
|
||||
Platform.runLater(() ->{ labelErrore.setTextFill(Color.RED); labelErrore.setText("Connection RMI failed.");});
|
||||
}
|
||||
} else {
|
||||
TCPClient client = new TCPClient(controller, ip, 8080, 8081);
|
||||
if (client.connect(nome, numPlayers)) {
|
||||
controller.setClient(client);
|
||||
Platform.runLater(() ->{ labelErrore.setTextFill(Color.GREEN); labelErrore.setText("Connected successfully! Waiting other players");});
|
||||
} else {
|
||||
Platform.runLater(() ->{ labelErrore.setTextFill(Color.RED); labelErrore.setText("Connection TCP failed.");});
|
||||
}
|
||||
try {
|
||||
String localInterface = resolveLocalInterface(ip);
|
||||
System.setProperty("java.rmi.server.hostname", localInterface);
|
||||
connect(nome, ip, numPlayers, localInterface);
|
||||
} catch (Exception ex) {
|
||||
Platform.runLater(() -> showError("Network error: " + ex.getMessage()));
|
||||
}
|
||||
}).start();
|
||||
|
||||
}
|
||||
|
||||
private String getInterfaccia() {
|
||||
String selected = comboInterfaccia.getValue();
|
||||
if (selected == null) return "";
|
||||
return selected.contains("->") ? selected.split("->")[1].trim() : selected;
|
||||
/**
|
||||
* Given the server IP, finds the local network interface whose subnet
|
||||
* contains that IP. Falls back to the default route for non-LAN addresses.
|
||||
* Handles "localhost" and "127.x.x.x" explicitly.
|
||||
*/
|
||||
private String resolveLocalInterface(String serverIp) throws Exception {
|
||||
// localhost shortcut
|
||||
if (serverIp.equalsIgnoreCase("localhost") ||
|
||||
serverIp.startsWith("127.") || serverIp.isEmpty()) {
|
||||
return "127.0.0.1";
|
||||
}
|
||||
|
||||
InetAddress serverAddr = InetAddress.getByName(serverIp);
|
||||
|
||||
// Walk every local interface and check if serverAddr is in its subnet
|
||||
Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
|
||||
while (ifaces.hasMoreElements()) {
|
||||
NetworkInterface ni = ifaces.nextElement();
|
||||
if (!ni.isUp() || ni.isLoopback()) continue;
|
||||
|
||||
for (InterfaceAddress ia : ni.getInterfaceAddresses()) {
|
||||
InetAddress localAddr = ia.getAddress();
|
||||
if (!(localAddr instanceof Inet4Address)) continue;
|
||||
|
||||
int prefix = ia.getNetworkPrefixLength();
|
||||
if (sameSubnet(localAddr, serverAddr, prefix)) {
|
||||
return localAddr.getHostAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No subnet match — use the address the OS would naturally pick
|
||||
// by opening a UDP socket toward the server (no data is sent)
|
||||
try (DatagramSocket socket = new DatagramSocket()) {
|
||||
socket.connect(serverAddr, 9); // port 9 = discard, never actually used
|
||||
return socket.getLocalAddress().getHostAddress();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@code a} and {@code b} are in the same /prefix subnet.
|
||||
*/
|
||||
private boolean sameSubnet(InetAddress a, InetAddress b, int prefix) {
|
||||
if (prefix < 0 || prefix > 32) return false;
|
||||
int maskBits = prefix == 0 ? 0 : (0xFFFFFFFF << (32 - prefix));
|
||||
int addrA = toInt(a.getAddress()) & maskBits;
|
||||
int addrB = toInt(b.getAddress()) & maskBits;
|
||||
return addrA == addrB;
|
||||
}
|
||||
|
||||
private int toInt(byte[] bytes) {
|
||||
return ((bytes[0] & 0xFF) << 24) |
|
||||
((bytes[1] & 0xFF) << 16) |
|
||||
((bytes[2] & 0xFF) << 8) |
|
||||
(bytes[3] & 0xFF);
|
||||
}
|
||||
|
||||
private void connect(String nome, String ip, int numPlayers, String localInterface) {
|
||||
if (isRMI) {
|
||||
RMIClient client = new RMIClient(controller, ip, 1099, localInterface);
|
||||
if (client.connect(nome, numPlayers)) {
|
||||
controller.setClient(client);
|
||||
Platform.runLater(() -> showSuccess("Connected! Waiting for other players…"));
|
||||
} else {
|
||||
Platform.runLater(() -> showError("RMI connection failed."));
|
||||
}
|
||||
} else {
|
||||
TCPClient client = new TCPClient(controller, ip, 8080, 8081);
|
||||
if (client.connect(nome, numPlayers)) {
|
||||
controller.setClient(client);
|
||||
Platform.runLater(() -> showSuccess("Connected! Waiting for other players…"));
|
||||
} else {
|
||||
Platform.runLater(() -> showError("TCP connection failed."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showError(String msg) {
|
||||
labelErrore.setTextFill(Color.web("#e05050"));
|
||||
labelErrore.setText(msg);
|
||||
}
|
||||
|
||||
private void showSuccess(String msg) {
|
||||
labelErrore.setTextFill(Color.web("#6fcf8a"));
|
||||
labelErrore.setText(msg);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user