Merge pull request #44 from rubenpirreram/Server-Launcher

Server-Launcher
This commit is contained in:
rubenpirreram
2026-04-25 15:29:00 +02:00
committed by GitHub
9 changed files with 184 additions and 41 deletions
@@ -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;
}
}
}
@@ -0,0 +1,32 @@
package it.polimi.ingsw.gc14;
import java.util.ArrayList;
public class LimitedList<T> extends ArrayList<T> {
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;
}
}
@@ -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;
@@ -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;
}
@@ -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,32 +25,44 @@ public class RMIServer implements IGameServer {
private int nPort;
private final Map<String, IClientCallback> clients = new ConcurrentHashMap<>();
BlockingQueue<NetworkEvent> actionQueue;
private LimitedList<String> playerList;
// Costruttore
public RMIServer(GameController controller, int nPort, BlockingQueue<NetworkEvent> actionQueue) throws RemoteException {
public RMIServer(GameController controller, int nPort, BlockingQueue<NetworkEvent> actionQueue,LimitedList<String> 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))
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;
}
}
@Override
public boolean doEvent(NetworkEvent event) throws RemoteException {
return actionQueue.offer(event);
@@ -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;
}
@@ -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<ClientHandler> clientHandlers;
GameController gameController;
BlockingQueue<NetworkEvent> actionQueue;
private EventType eventType;
public Socket getClientSocket() {
return clientSocket;
}
public ClientHandler(Socket clientSocket, List<ClientHandler> clientHandlers, GameController gameController) {
public ClientHandler(Socket clientSocket, List<ClientHandler> clientHandlers, BlockingQueue<NetworkEvent> 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();
}
}
}
}
@@ -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<NetworkEvent> actionQueue;
private LimitedList<String> playerList;
private List<ClientHandler> clientHandlers;
@@ -42,24 +46,49 @@ public class TCPServer {
try{
clientSocket = serverTCP.accept();
if(!gameController.addPlayer(clientSocket.getInputStream().toString()) || ConnectedPlayers > gameController.getModel().getNPlayers()){
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){
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<NetworkEvent> actionQueue){
public TCPServer(GameController gameController, int port, BlockingQueue<NetworkEvent> actionQueue, LimitedList<String> 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));
}
}
@@ -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<NetworkEvent> actionQueue;
GameController gameController;
RMIServer serverRMI;
TCPServer serverTCP;
static LimitedList<String> 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<NetworkEvent> 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();
}
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;