diff --git a/src/main/java/it/polimi/ingsw/gc14/ClientLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ClientLauncher.java new file mode 100644 index 0000000..fd8a3f8 --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/ClientLauncher.java @@ -0,0 +1,28 @@ +package it.polimi.ingsw.gc14; +import java.util.Scanner; + +public class ClientLauncher { + public void main() { + Scanner scanner = new Scanner(System.in); + + System.out.println("Selezionare nome utente: "); + String username = scanner.next(); + System.out.println(username); + + System.out.println("Selezionare numero di giocatori desiderato: "); + int proposedNumPlayers = scanner.nextInt(); + System.out.println(proposedNumPlayers); + + System.out.println("Selezionare RMI[0] o TCP[1]: "); + int networkType = scanner.nextInt(); + System.out.println(networkType); + + scanner.close(); // chiudi solo alla fine + + if (networkType == 0) { + return; + } else if (networkType == 1) { + return; + } + } +} \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/LimitedList.java b/src/main/java/it/polimi/ingsw/gc14/LimitedList.java new file mode 100644 index 0000000..6aa8cf9 --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/LimitedList.java @@ -0,0 +1,32 @@ +package it.polimi.ingsw.gc14; + +import java.util.ArrayList; + +public class LimitedList extends ArrayList { + private int limit; + private Runnable action; + + public LimitedList(int limit, Runnable action) { + this.limit = limit; + this.action = action; + } + + @Override + public boolean add(T element) { + boolean result = super.add(element); + if (size() >= limit) { + action.run(); + } + return result; + } + + public void setLimit(int num) { + this.limit=num; + } + + public int getLimit(){return limit;} + + public void setAction(Runnable action) { + this.action=action; + } +} \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java index ac0e14b..8d0721c 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java @@ -18,7 +18,7 @@ public class RMIClient { } - public boolean connect(String username,ClientController clientController) { + public boolean connect(String username,int preferredInt,ClientController clientController) { // 1. Connettiti al registry try { Registry registry = LocateRegistry.getRegistry(host, port); @@ -29,7 +29,7 @@ public class RMIClient { // 3. Crea il callback e registralo ClientCallbackImpl callback = new ClientCallbackImpl(clientController); - if (!stub.joinGame(username, callback)) + if (!stub.joinGame(username,preferredInt, callback)) { stub = null; return false; diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IGameServer.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IGameServer.java index 8bcaff6..7a1ef25 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IGameServer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IGameServer.java @@ -6,7 +6,7 @@ import java.rmi.*; public interface IGameServer extends Remote { - boolean joinGame(String username, IClientCallback callback) throws RemoteException; + boolean joinGame(String username,int preferredInt, IClientCallback callback) throws RemoteException; boolean doEvent(NetworkEvent event) throws RemoteException; } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java index d81eb96..fc74f3c 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java @@ -1,6 +1,7 @@ package it.polimi.ingsw.gc14.Network.RMI.Server; import it.polimi.ingsw.gc14.Controller.GameController; +import it.polimi.ingsw.gc14.LimitedList; import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.RMI.Common.IClientCallback; @@ -24,31 +25,43 @@ public class RMIServer implements IGameServer { private int nPort; private final Map clients = new ConcurrentHashMap<>(); BlockingQueue actionQueue; - + private LimitedList playerList; // Costruttore - public RMIServer(GameController controller, int nPort, BlockingQueue actionQueue) throws RemoteException { + public RMIServer(GameController controller, int nPort, BlockingQueue actionQueue,LimitedList playerList) throws RemoteException { this.controller = controller; this.nPort = nPort; this.actionQueue = actionQueue; + this.playerList = playerList; } + // Metodi esposti RMI public void setController (GameController controller) { this.controller = controller; } @Override - public boolean joinGame(String username, IClientCallback callback) { - if(controller.addPlayer(username)) - { - clients.put(username, callback); - return true; + public boolean joinGame(String username, int preferredInt,IClientCallback callback) { + synchronized (controller) { + if(playerList.size()==0 && (preferredInt<2||preferredInt>5)) + return false; + if (controller.addPlayer(username)) { + if(playerList.size()==0) + { + Game game= new Game(preferredInt); + controller.setModel(game); + playerList.setLimit(preferredInt); + } + playerList.add(username); + clients.put(username, callback); + return true; + } + return false; } - return false; } @Override public boolean doEvent(NetworkEvent event) throws RemoteException { diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java index 113cd2e..d29de4b 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java @@ -22,13 +22,13 @@ public class TCPClient implements Serializable{ this.port = port; } - public boolean start(String user){ + public boolean start(String user, int players){ try{ communicationSocket = new Socket(hostname, port); socketSend = new ObjectOutputStream(communicationSocket.getOutputStream()); socketReceive = new ObjectInputStream(communicationSocket.getInputStream()); - socketSend.writeObject(new AddPlayer(user)); + socketSend.writeObject(new AddPlayer(user, players)); if(communicationSocket.getInputStream().read() == -1){ return false; } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java index 97ea3c1..d471ab0 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java @@ -1,12 +1,14 @@ package it.polimi.ingsw.gc14.Network.TCP.Server; import it.polimi.ingsw.gc14.Controller.GameController; +import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.EventType; import java.io.*; import java.net.*; import java.util.List; +import java.util.concurrent.BlockingQueue; public class ClientHandler implements Runnable { private Socket clientSocket; @@ -14,17 +16,17 @@ public class ClientHandler implements Runnable { public ObjectInputStream in = null; public ObjectOutputStream out = null; List clientHandlers; - GameController gameController; + BlockingQueue actionQueue; private EventType eventType; public Socket getClientSocket() { return clientSocket; } - public ClientHandler(Socket clientSocket, List clientHandlers, GameController gameController) { + public ClientHandler(Socket clientSocket, List clientHandlers, BlockingQueue actionQueue) { this.clientSocket = clientSocket; this.clientHandlers = clientHandlers; - this.gameController = gameController; + this.actionQueue = actionQueue; } @Override @@ -41,7 +43,7 @@ public class ClientHandler implements Runnable { while(true){ try{ input = (NetworkEvent) (in.readObject()); - if(input.apply(gameController)){ + if(actionQueue.add(input)){ server.broadcastUpdate(input); } } @@ -64,13 +66,26 @@ public class ClientHandler implements Runnable { synchronized(out){ try{ out = new ObjectOutputStream(clientSocket.getOutputStream()); - out.writeObject(gameController.getModel()); + out.writeObject(event); } catch(IOException e){ e.printStackTrace(); } } } + + public void notifyModel(Game game){ + synchronized(out){ + try{ + out = new ObjectOutputStream(clientSocket.getOutputStream()); + out.writeObject(game); + } + catch(IOException e){ + e.printStackTrace(); + } + } + } + } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java index f7910a3..7c928c3 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java @@ -1,7 +1,10 @@ package it.polimi.ingsw.gc14.Network.TCP.Server; import it.polimi.ingsw.gc14.Controller.GameController; +import it.polimi.ingsw.gc14.LimitedList; +import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Network.NetworkEvent; +import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer; import java.io.*; import java.net.*; @@ -9,13 +12,14 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.BlockingQueue; + public class TCPServer { int port = -1; int ConnectedPlayers = 0; ServerSocket serverTCP = null; GameController gameController; BlockingQueue actionQueue; - + private LimitedList playerList; private List clientHandlers; @@ -42,24 +46,49 @@ public class TCPServer { try{ clientSocket = serverTCP.accept(); - if(!gameController.addPlayer(clientSocket.getInputStream().toString()) || ConnectedPlayers > gameController.getModel().getNPlayers()){ - clientSocket.getOutputStream().write((int)(-1)); - clientSocket.close(); - System.out.println("Invalid parameters. Connection terminated.\n"); - } - else{ - clientSocket.getOutputStream().write((int)(1)); + ObjectInputStream clientSocketObj = new ObjectInputStream(clientSocket.getInputStream()); + NetworkEvent event = (NetworkEvent) clientSocketObj.readObject(); + + synchronized (gameController){ + if(!(event instanceof AddPlayer) || (gameController.getModel() != null && gameController.getModel().getCurrentPlayerNumber() >= gameController.getModel().getNPlayers())){ + clientSocket.getOutputStream().write((int)(-1)); + clientSocket.close(); + System.out.println("Invalid parameters. Connection terminated.\n"); + } + else{ + synchronized (gameController) { + AddPlayer addPlayer = (AddPlayer) event; + if(playerList.isEmpty() && (addPlayer.getProposedNPlayer() < 2 || addPlayer.getProposedNPlayer() > 5)){ + clientSocket.getOutputStream().write((int)(-1)); + clientSocket.close(); + System.out.println("Invalid parameters. Connection terminated.\n"); + } + else if(gameController.addPlayer(addPlayer.getUsername())){ + if(playerList.isEmpty()){ + Game game = new Game(addPlayer.getProposedNPlayer()); + gameController.setModel(game); + playerList.setLimit(addPlayer.getProposedNPlayer()); + } + playerList.add(addPlayer.getUsername()); + clientSocket.getOutputStream().write((int)(1)); + } + } + + } } // gestione di ADD_PLAYER } - catch (IOException e){ + catch(IOException e){ e.printStackTrace(); } + catch(ClassNotFoundException e){ + throw new RuntimeException(e); + } System.out.println("Accepted player: " + gameController.getModel().getPlayerByUsername(clientSocket.getInetAddress().toString())); ConnectedPlayers++; - ClientHandler clientHandler = new ClientHandler(clientSocket, clientHandlers, gameController); + ClientHandler clientHandler = new ClientHandler(clientSocket, clientHandlers, actionQueue); clientHandlers.add(clientHandler); //Sending model to clients @@ -82,13 +111,18 @@ public class TCPServer { } } - public TCPServer(GameController gameController, int port, BlockingQueue actionQueue){ + public TCPServer(GameController gameController, int port, BlockingQueue actionQueue, LimitedList players){ this.port = port; this.gameController = gameController; this.actionQueue = actionQueue; + this.playerList = players; } public void broadcastUpdate(NetworkEvent event){ clientHandlers.forEach((x) -> x.notifyEvent(event)); } + + public void broadcastModel(Game model){ + clientHandlers.forEach((x) -> x.notifyModel(model)); + } } diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index b3c14d7..67d4dfd 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -4,6 +4,7 @@ package it.polimi.ingsw.gc14; import it.polimi.ingsw.gc14.Controller.GameController; import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Network.NetworkEvent; +import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer; import it.polimi.ingsw.gc14.Network.RMI.Server.RMIServer; import it.polimi.ingsw.gc14.Network.TCP.Server.TCPServer; @@ -12,10 +13,12 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class ServerLauncher { + BlockingQueue actionQueue; GameController gameController; RMIServer serverRMI; TCPServer serverTCP; + static LimitedList players; @@ -26,7 +29,7 @@ public class ServerLauncher { this.serverTCP = serverTCP; } - public boolean doFirstEvent() throws InterruptedException, RemoteException { + public boolean doFirstEven() throws InterruptedException, RemoteException { NetworkEvent event = actionQueue.take(); if(event.apply(gameController)) { serverRMI.notifyAll(event); @@ -40,24 +43,42 @@ public class ServerLauncher { } - public static void main() throws RemoteException { + public static void main() throws RemoteException, InterruptedException { + // TODO + // Deve avere una coda con gli eventi. + // Il server RMI e il server TCP quando ricevono un doEvent devono aggiungere l'evento alla coda condivisa + // Questa classe esegue gli eventi nella coda e chiama il notify all e notify error sia RMI che TCP + + players = new LimitedList<>(5, ()->{}); BlockingQueue actionQueue = new LinkedBlockingQueue<>(); - Game model = new Game(); - GameController gameController = new GameController(model); - RMIServer serverRMI = new RMIServer(gameController, 1099, actionQueue); - TCPServer serverTCP = new TCPServer(gameController, 8080, actionQueue); + GameController gameController = new GameController(); + RMIServer serverRMI = new RMIServer(gameController, 1099, actionQueue, players); + TCPServer serverTCP = new TCPServer(gameController, 8080, actionQueue, players); + ServerLauncher launcher = new ServerLauncher(actionQueue, gameController, serverRMI, serverTCP); + + players.setAction(()->{ + try { + launcher.run(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + }); serverRMI.start(); - new Thread (()->{serverTCP.start();}).start(); - - ServerLauncher launcher = new ServerLauncher(actionQueue, gameController, serverRMI, serverTCP); - launcher.run(); + new Thread(()->{serverTCP.start();}).start(); } - public void run() { + public void run() throws InterruptedException, RemoteException { + + serverRMI.notifyAll(gameController.getModel()); + serverTCP.broadcastModel(gameController.getModel()); + + while (true) { try { - this.doFirstEvent(); + this.doFirstEven(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break;