209 lines
8.4 KiB
Java
209 lines
8.4 KiB
Java
package it.polimi.ingsw.gc14;
|
|
import it.polimi.ingsw.gc14.Controller.ClientController;
|
|
import it.polimi.ingsw.gc14.Network.NetworkEvent;
|
|
import it.polimi.ingsw.gc14.Network.RMI.Client.RMIClient;
|
|
import it.polimi.ingsw.gc14.Network.TCP.Client.TCPClient;
|
|
import it.polimi.ingsw.gc14.View.TUI.TUI;
|
|
|
|
import java.net.Inet4Address;
|
|
import java.net.InetAddress;
|
|
import java.net.NetworkInterface;
|
|
import java.util.ArrayList;
|
|
import java.util.Enumeration;
|
|
import java.util.List;
|
|
import java.util.Scanner;
|
|
|
|
/**
|
|
* Entry point for the TUI-based game client.
|
|
* Handles the initial setup by asking the user for a username, the desired number of players,
|
|
* and the preferred network protocol (RMI or TCP).
|
|
* Once connected to the server, it continuously reads and dispatches user input to the controller.
|
|
*/
|
|
public class ClientLauncherTUI {
|
|
|
|
List<String> admissibleChar=new ArrayList<>();
|
|
|
|
/**
|
|
* The TUI view associated with this client.
|
|
*/
|
|
TUI view;
|
|
|
|
/**
|
|
* Starts the TUI client.
|
|
* Prompts the user for a username, the desired number of players, and the network protocol.
|
|
* Attempts to connect to the server using either RMI or TCP depending on the selection.
|
|
* If the connection is successful, enters a loop to continuously read and process user input.
|
|
*
|
|
* @throws InterruptedException if the thread is interrupted while waiting.
|
|
*/
|
|
public void main() throws InterruptedException {
|
|
view = new TUI(null);
|
|
admissibleChar.add("1");
|
|
admissibleChar.add("2");
|
|
admissibleChar.add("3");
|
|
admissibleChar.add("4");
|
|
admissibleChar.add("5");
|
|
admissibleChar.add("6");
|
|
admissibleChar.add("7");
|
|
admissibleChar.add("A");
|
|
admissibleChar.add("B");
|
|
admissibleChar.add("C");
|
|
admissibleChar.add("a");
|
|
admissibleChar.add("b");
|
|
admissibleChar.add("c");
|
|
|
|
ClientController controller = new ClientController(view);
|
|
Scanner scanner = new Scanner(System.in);
|
|
System.out.println("Insert username: ");
|
|
String username = scanner.next();
|
|
view.setUsername(username);
|
|
System.out.println("Insert preferred number of players: ");
|
|
int proposedNumPlayers = scanner.nextInt();
|
|
System.out.println("Select RMI[0] o TCP[1]: ");
|
|
int networkType = scanner.nextInt();
|
|
System.out.println("Insert server IP: ");
|
|
String IP = scanner.next();
|
|
|
|
// RMI
|
|
if (networkType == 0) {
|
|
// Connect
|
|
String myIP;
|
|
try {
|
|
myIP = chooseNetworkInterface(scanner);
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
System.setProperty("java.rmi.server.hostname", myIP);
|
|
RMIClient client = new RMIClient(controller, IP, 1099, myIP);
|
|
if (client.connect(username, proposedNumPlayers)) {
|
|
System.out.println("Succesfully connected to RMI server\n\n");
|
|
} else {
|
|
System.out.println("RMI connection refused\n\n");
|
|
return;
|
|
}
|
|
controller.setClient(client);
|
|
while (true) {
|
|
getInput(scanner, controller, username);
|
|
}
|
|
// TCP
|
|
} else if (networkType == 1) {
|
|
// Connect
|
|
TCPClient client = new TCPClient(controller, IP, 8080,8081);
|
|
if (client.connect(username, proposedNumPlayers)) {
|
|
System.out.println("Succesfully connected to TCP server\n\n");
|
|
} else {
|
|
System.out.println("TCP connection refused\n\n");
|
|
return;
|
|
}
|
|
controller.setClient(client);
|
|
// Play
|
|
while (true) {
|
|
getInput(scanner, controller, username);
|
|
}
|
|
}
|
|
scanner.close();
|
|
}
|
|
|
|
/**
|
|
* Reads a single action from the user and dispatches it to the controller.
|
|
* The action is identified by a string code. Most actions also require a position index
|
|
* (e.g. the index of the card to draw from a list), which is read as a second input.
|
|
* Actions that do not require a position (7, 8, 9, A, B, C) skip the position prompt.
|
|
* <p>
|
|
* Available actions:
|
|
* <ul>
|
|
* <li>{@code 0} - Choose a slot by index.</li>
|
|
* <li>{@code 1} - Draw an upper building card by index.</li>
|
|
* <li>{@code 2} - Draw an upper tribe card by index.</li>
|
|
* <li>{@code 3} - Draw a lower building card by index.</li>
|
|
* <li>{@code 4} - Draw a lower tribe card by index.</li>
|
|
* <li>{@code 5} - Pick an optional tribe card by index.</li>
|
|
* <li>{@code 6} - Pick an optional building card by index.</li>
|
|
* <li>{@code 7} - Skip the optional card choice.</li>
|
|
* <li>{@code 8} - Skip the upper draw.</li>
|
|
* <li>{@code 9} - Skip the lower draw.</li>
|
|
* <li>{@code A} - Render the full game view.</li>
|
|
* <li>{@code B} - Render the board view.</li>
|
|
* <li>{@code C} - Render the player view.</li>
|
|
* </ul>
|
|
*
|
|
* @param scanner the scanner used to read user input.
|
|
* @param controller the client controller to which actions are dispatched.
|
|
* @param username the username of the current player.
|
|
*/
|
|
private void getInput(Scanner scanner, ClientController controller, String username) {
|
|
String action = scanner.next();
|
|
int pos = -1;
|
|
|
|
if(admissibleChar.contains(action))
|
|
{
|
|
if (!action.equals("6") && !action.equals("A") && !action.equals("B") && !action.equals("C")&&!action.equals("a") && !action.equals("b") && !action.equals("c")) {
|
|
try {
|
|
System.out.println("Insert the required position:");
|
|
pos = scanner.nextInt();
|
|
} catch (Exception e) {
|
|
view.showError("ERROR: Invalid input(expected number)");
|
|
return;
|
|
}
|
|
}
|
|
switch (action) {
|
|
case "1" -> controller.slotChoice(username, pos);
|
|
case "2" -> controller.drawUpperTribeCard(username, pos);
|
|
case "3" -> controller.drawUpperBuildingCard(username, pos);
|
|
case "4" -> controller.drawLowerTribeCard(username, pos);
|
|
case "5" -> controller.drawLowerBuildingCard(username, pos);
|
|
case "6" -> controller.skipTurn(username);
|
|
case "7" -> controller.totemChoice(username,pos);
|
|
case "A", "a" -> view.fullRender();
|
|
case "B", "b" -> view.renderBoard();
|
|
case "C", "c" -> view.renderPlayer();
|
|
default -> {}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
view.showError("ERROR: Invalid input(action not valid)");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Lets the user choose one of the available active IPv4 network interfaces.
|
|
*
|
|
* <p>The method lists all active, non-loopback and non-virtual network
|
|
* interfaces with an IPv4 address. If only one interface is available, it is
|
|
* selected automatically.
|
|
*
|
|
* @param scanner the scanner used to read the user's choice.
|
|
* @return the selected IPv4 address as a string.
|
|
* @throws Exception if no valid network interface is available.
|
|
*/
|
|
public static String chooseNetworkInterface(Scanner scanner) throws Exception {
|
|
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) {
|
|
System.out.println("[" + ips.size() + "] " + ni.getDisplayName() + " -> " + addr.getHostAddress());
|
|
ips.add(addr.getHostAddress());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ips.isEmpty()) throw new Exception("No interface available");
|
|
if (ips.size() == 1) {
|
|
System.out.println("Only one interface found, used: " + ips.get(0));
|
|
return ips.get(0);
|
|
}
|
|
|
|
System.out.print("Choose the interface: ");
|
|
int choice = scanner.nextInt();
|
|
return ips.get(choice);
|
|
}
|
|
} |