From f1fc88511bb8b57b69a106b18cef93e036a7e3f2 Mon Sep 17 00:00:00 2001 From: Simon Bussmann Date: Thu, 18 Mar 2021 03:47:40 +0100 Subject: [PATCH] Implemented threading in Client - GUI doesn't get blocked anymore - Implemented client side protocol based control - Client is now ready for player versus player --- .idea/artifacts/Client_jar.xml | 21 +-- Client/src/Launcher.java | 7 - Client/src/META-INF/MANIFEST.MF | 2 +- Client/src/TicTacToe_Client.java | 131 ++++++++++++++++ Client/src/game/TicTacToe_Client.java | 135 ----------------- Client/src/networking/Client.java | 58 +++++-- Client/src/render/Engine.java | 141 ++++++++++++++++++ Client/src/{game => res}/TicTacToe_Client.css | 0 Client/src/{game => res}/TicTacToe_Grid.png | Bin Server/src/networking/MultiPlayerServer.java | 131 ++++++++++------ Server/src/networking/SinglePlayerServer.java | 100 +++++++++---- .../src/{game => res}/TicTacToe_Server.java | 4 +- out/production/Client/META-INF/MANIFEST.MF | 2 +- .../Client/{game => res}/TicTacToe_Client.css | 0 .../Client/{game => res}/TicTacToe_Grid.png | Bin 15 files changed, 494 insertions(+), 238 deletions(-) delete mode 100644 Client/src/Launcher.java create mode 100644 Client/src/TicTacToe_Client.java delete mode 100644 Client/src/game/TicTacToe_Client.java create mode 100644 Client/src/render/Engine.java rename Client/src/{game => res}/TicTacToe_Client.css (100%) rename Client/src/{game => res}/TicTacToe_Grid.png (100%) rename Server/src/{game => res}/TicTacToe_Server.java (98%) rename out/production/Client/{game => res}/TicTacToe_Client.css (100%) rename out/production/Client/{game => res}/TicTacToe_Grid.png (100%) diff --git a/.idea/artifacts/Client_jar.xml b/.idea/artifacts/Client_jar.xml index defd9ad..114e9cc 100644 --- a/.idea/artifacts/Client_jar.xml +++ b/.idea/artifacts/Client_jar.xml @@ -1,14 +1,17 @@ - + $PROJECT_DIR$/out/artifacts/Client_jar - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/Client/src/Launcher.java b/Client/src/Launcher.java deleted file mode 100644 index b2ca47e..0000000 --- a/Client/src/Launcher.java +++ /dev/null @@ -1,7 +0,0 @@ -import game.TicTacToe_Client; - -public class Launcher { - public static void main(String[] args) { - TicTacToe_Client.main(args); - } -} \ No newline at end of file diff --git a/Client/src/META-INF/MANIFEST.MF b/Client/src/META-INF/MANIFEST.MF index b851779..eee92a3 100644 --- a/Client/src/META-INF/MANIFEST.MF +++ b/Client/src/META-INF/MANIFEST.MF @@ -1,3 +1,3 @@ Manifest-Version: 1.0 -Main-Class: game.TicTacToe_Client +Main-Class: TicTacToe_Client diff --git a/Client/src/TicTacToe_Client.java b/Client/src/TicTacToe_Client.java new file mode 100644 index 0000000..4de2390 --- /dev/null +++ b/Client/src/TicTacToe_Client.java @@ -0,0 +1,131 @@ +import javafx.application.Platform; +import networking.Client; +import render.Engine; + +import java.util.Arrays; +import java.util.LinkedList; + +public class TicTacToe_Client { + + private Engine renderEngine; + private Client client; + private boolean isSingleServer; + + public TicTacToe_Client(){ + renderEngine = Engine.waitForEngine(); + } + + private void ticTacToe_gameloop(){ + //Setup + client = new Client("server", 2589, "second"); + client.handshake(); + isSingleServer = client.getServerType(); + if (isSingleServer){ + this.setWindowTitle(client.isPlayerOne()); + client.sendToServer("ready"); + while (client.isConnected()) { + String message = client.getResponse(); + //Check if message is gamestate + if (message.charAt(0) == 'x' || message.charAt(0) == '-' || message.charAt(0) == 'o') { + this.drawBoard(message); + this.gameFlow("userInput"); + } + //Handle everything else + else { + this.gameFlow(message); + } + } + } else { + this.setWindowTitle(client.isPlayerOne()); + } + } + + private void gameFlow(String input){ + switch (input) { + case "userInput": + while(!renderEngine.isMouseClicked()){ + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + renderEngine.setMouseClicked(false); + this.userInput(); + break; + } + } + + + + + private void userInput(){ + //Send command + client.sendToServer("clientMove"); + //Send position + client.sendToServer(String.format("%f|%f", renderEngine.getCoordinates().getX(), renderEngine.getCoordinates().getY())); + //Get gameState + String gameState = client.getResponse(); + if (gameState.length() == 9) { + this.drawBoard(gameState); + //Send command + if (!client.getGameEnded()) { + client.sendToServer("computerMove"); + this.drawBoard(client.getResponse()); + } else { + LinkedList winCoordinates = new LinkedList<>(); + //Get winning fields + String response = client.getResponse(); + for (String s : Arrays.copyOfRange(response.split(";"), 0, 4)) { + winCoordinates.add(Integer.valueOf(s) * 300); + } + //this.drawWinningLine(winCoordinates); + client.exitProcess(); + System.exit(0); + } + } else { + int column = (int) renderEngine.getCoordinates().getX() / 300; + int row = (int) renderEngine.getCoordinates().getY() / 300; + System.err.printf("You are not allowed to place at %d|%d%n", column, row); + } + } + + private void drawBoard(String gameState) { + Platform.runLater(new Runnable() { + @Override + public void run() { + renderEngine.drawBoard(gameState); + } + }); + } + + private void setWindowTitle(boolean isClientOne){ + if (isClientOne){ + Platform.runLater(new Runnable() { + @Override + public void run() { + renderEngine.updateTitle("Client One"); + } + }); + } else { + Platform.runLater(new Runnable() { + @Override + public void run() { + renderEngine.updateTitle("Client Two"); + } + }); + } + } + + public static void main(String[] args) { + new Thread(){ + @Override + public void run(){ + javafx.application.Application.launch(Engine.class); + } + }.start(); + TicTacToe_Client test = new TicTacToe_Client(); + test.ticTacToe_gameloop(); + } + +} diff --git a/Client/src/game/TicTacToe_Client.java b/Client/src/game/TicTacToe_Client.java deleted file mode 100644 index d88b917..0000000 --- a/Client/src/game/TicTacToe_Client.java +++ /dev/null @@ -1,135 +0,0 @@ -package game; - -import javafx.application.Application; -import javafx.event.EventHandler; -import javafx.geometry.Pos; -import javafx.scene.Scene; -import javafx.scene.input.MouseEvent; -import javafx.scene.layout.GridPane; -import javafx.scene.paint.Color; -import javafx.scene.shape.Line; -import javafx.scene.text.Font; -import javafx.scene.text.FontWeight; -import javafx.scene.text.Text; -import javafx.stage.Stage; -import networking.Client; - -import java.util.Arrays; -import java.util.LinkedList; - -public class TicTacToe_Client extends Application { - - GridPane grid; - Client client; - Scene scene; - - private void initializeGrid() { - grid = new GridPane(); - grid.setMinSize(900, 900); - grid.setAlignment(Pos.CENTER); - grid.setHgap(150); - grid.setVgap(75); - } - - private void drawCross(int column, int row) { - Text cross = new Text("X"); - cross.setFont(Font.font("Tahoma", FontWeight.NORMAL, 200)); - grid.add(cross, column, row); - } - - private void drawCircle(int column, int row) { - Text circle = new Text("O"); - circle.setFont(Font.font("Tahoma", FontWeight.NORMAL, 200)); - grid.add(circle, column, row); - } - - private void drawEmptyField(int column, int row) { - Text emptyField = new Text(" "); - emptyField.setFont(Font.font("Tahoma", FontWeight.NORMAL, 220)); - grid.add(emptyField, column, row); - } - - private void drawBoard(String gameState) { - if (gameState.length() != 9) { - System.err.println("Wrong length of gameState string"); - return; - } - for (int i = 0; i < gameState.length(); i++) { - int column = i / 3; - int row = i % 3; - if (gameState.charAt(i) == 'x') { - this.drawCross(column, row); - } else if (gameState.charAt(i) == 'o') { - this.drawCircle(column, row); - } else { - this.drawEmptyField(column, row); - } - - } - } - - private Scene setScene() { - scene = new Scene(grid, 900, 900); - scene.getStylesheets().add - (TicTacToe_Client.class.getResource("TicTacToe_Client.css").toExternalForm()); - scene.setOnMousePressed(new EventHandler() { - @Override - public void handle(MouseEvent event) { - onMouseClick(event); - } - }); - return scene; - } - - private void onMouseClick(MouseEvent event) { - client.sendToServer("update"); - client.sendToServer(String.format("%f|%f", event.getX(), event.getY())); - String gameState = client.getResponse(); - System.out.println(gameState); - if (gameState.length() == 9) { - drawBoard(gameState); - if (!client.getGameEnded()) { - gameState = client.getResponse(); - drawBoard(gameState); - } else { - LinkedList winCoordinates = new LinkedList<>(); - String response = client.getResponse(); - for (String s : Arrays.copyOfRange(response.split(";"), 0, 4)) { - winCoordinates.add(Integer.valueOf(s) * 300); - } - this.drawWinningLine(winCoordinates); - client.exitProcess(); - } - } else { - int column = (int) event.getX() / 300; - int row = (int) event.getY() / 300; - System.err.printf("You are not allowed to place at %d|%d%n", column, row); - } - } - - private void drawWinningLine(LinkedList winCoordinates) { - Line winningLine = new Line(winCoordinates.get(0), winCoordinates.get(1), winCoordinates.get(2), winCoordinates.get(3)); - winningLine.setFill(Color.RED); - grid.add(winningLine, winCoordinates.get(0) / 300, winCoordinates.get(1) / 300, 3, 3); - } - - @Override - public void start(Stage primaryStage) { - client = new Client("server", 2589, "Cato"); - client.handshake(); - - primaryStage.setTitle("TicTacToe"); - primaryStage.setResizable(false); - - this.initializeGrid(); - primaryStage.setScene(this.setScene()); - primaryStage.show(); - - this.drawBoard(client.getGameState()); - } - - public static void main(String[] args) { - launch(args); - } - -} diff --git a/Client/src/networking/Client.java b/Client/src/networking/Client.java index a2bc568..7d95fec 100644 --- a/Client/src/networking/Client.java +++ b/Client/src/networking/Client.java @@ -10,6 +10,7 @@ import java.net.Socket; import java.util.Scanner; public class Client { + private Socket serverSocket; private DataOutputStream out; private DataInputStream in; private static Scanner scanner; @@ -21,7 +22,8 @@ public class Client { public Client(String ip, int port, String name) { try { scanner = new Scanner(System.in); - Socket serverSocket = new Socket(ip, port); + serverSocket = new Socket(ip, port); + serverName = serverSocket.getRemoteSocketAddress().toString(); out = new DataOutputStream(serverSocket.getOutputStream()); in = new DataInputStream(serverSocket.getInputStream()); clientLogger = new ClientLogger(); @@ -41,7 +43,6 @@ public class Client { if (success) { out.writeUTF(name); out.flush(); - serverName = in.readUTF(); clientLogger.printLog("You successfully connected to me", serverName, success, LogType.Log); } else { clientLogger.printLog("Connection failed try again", success, LogType.Log); @@ -63,10 +64,20 @@ public class Client { } } + public void sendConfirmation(){ + try { + out.writeInt(200); + out.flush(); + clientLogger.printLog("Sent verification code", serverName, true, LogType.Log); + } catch (IOException e) { + e.printStackTrace(); + } + } + public String getResponse() { try { String message = in.readUTF(); - clientLogger.printLog(String.format("Message recieved: %s", message), serverName, success, LogType.Log); + clientLogger.printLog(String.format("Message recieved: %s", message), serverName, true, LogType.Log); return message; } catch (IOException e) { e.printStackTrace(); @@ -74,17 +85,29 @@ public class Client { return ""; } - public boolean getBooleanResponse(String value){ + public boolean getBooleanResponse(String message) { try { - boolean booleanResponse = in.readBoolean(); - clientLogger.printLog(String.format(value + ": %b", booleanResponse), serverName, booleanResponse, LogType.Log); - return booleanResponse; + boolean state = in.readBoolean(); + clientLogger.printLog(String.format("%s: %b", message, state), serverName, true, LogType.Log); + return state; } catch (IOException e) { e.printStackTrace(); } return false; } + public boolean isPlayerOne(){ + this.sendToServer("isClientOne"); + boolean isClientOne = this.getBooleanResponse("isClientOne"); + return isClientOne; + } + + public boolean getServerType(){ + this.sendToServer("serverType"); + boolean serverType = this.getBooleanResponse("isSingleServer"); + return serverType; + } + public String getGameState() { this.sendToServer("gameState"); String gameState = this.getResponse(); @@ -93,10 +116,20 @@ public class Client { public boolean getGameEnded() { this.sendToServer("gameEnded"); - boolean gameEnded = this.getBooleanResponse("Game ended"); + boolean gameEnded = false; + try { + gameEnded = in.readBoolean(); + clientLogger.printLog(String.format("Game ended: %b", gameEnded), serverName, gameEnded, LogType.Log); + } catch (IOException e) { + e.printStackTrace(); + } return gameEnded; } + public void waitForInput() { + + } + public void exitProcess(){ try { out.writeUTF("exit()"); @@ -108,12 +141,13 @@ public class Client { } } - public boolean hasSucceeded() { - return success; - } - public String getName() { return name; } + public boolean isConnected(){ + return serverSocket.isConnected(); + } + + } \ No newline at end of file diff --git a/Client/src/render/Engine.java b/Client/src/render/Engine.java new file mode 100644 index 0000000..9b811b1 --- /dev/null +++ b/Client/src/render/Engine.java @@ -0,0 +1,141 @@ +package render; + +import javafx.application.Application; +import javafx.event.EventHandler; +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.GridPane; +import javafx.scene.text.Font; +import javafx.scene.text.FontWeight; +import javafx.scene.text.Text; +import javafx.stage.Stage; + +import java.awt.*; +import java.util.concurrent.CountDownLatch; + +public class Engine extends Application { + + private GridPane grid; + private Scene scene; + private static final CountDownLatch latch = new CountDownLatch(1); + private static Engine engine = null; + private boolean mouseClicked = false; + private Point coordinates = new Point(); + private Stage primaryStage; + private MouseEvent mouseEvent; + + public Engine() { + setEngine(this); + } + + private void initializeGrid() { + grid = new GridPane(); + grid.setPrefSize(900, 900); + grid.setAlignment(Pos.CENTER); + grid.setHgap(150); + grid.setVgap(75); + } + + private Scene setScene() { + scene = new Scene(grid, 900, 900); + scene.getStylesheets().add("res/TicTacToe_Client.css"); + scene.setOnMousePressed(new EventHandler() { + @Override + public void handle(MouseEvent event) { + onMouseClick(event); + } + }); + return scene; + } + + public static Engine waitForEngine() { + try { + latch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return engine; + } + + public static void setEngine(Engine new_engine) { + engine = new_engine; + latch.countDown(); + } + + public void updateTitle(String title){ + System.out.println("title: " + title); + primaryStage.setTitle(title); + } + + public void drawCross(int column, int row) { + Text cross = new Text("X"); + cross.setFont(Font.font("Tahoma", FontWeight.NORMAL, 200)); + grid.add(cross, column, row); + } + + public void drawCircle(int column, int row) { + Text circle = new Text("O"); + circle.setFont(Font.font("Tahoma", FontWeight.NORMAL, 200)); + grid.add(circle, column, row); + } + + public void drawEmptyField(int column, int row) { + Text emptyField = new Text(" "); + emptyField.setFont(Font.font("Tahoma", FontWeight.NORMAL, 220)); + grid.add(emptyField, column, row); + } + + public void drawBoard(String gameState) { + if (gameState.length() != 9) { + System.err.println("Wrong length of gameState string"); + return; + } + for (int i = 0; i < gameState.length(); i++) { + int column = i / 3; + int row = i % 3; + if (gameState.charAt(i) == 'x') { + this.drawCross(column, row); + } else if (gameState.charAt(i) == 'o') { + this.drawCircle(column, row); + } else { + this.drawEmptyField(column, row); + } + + } + } + + private void onMouseClick(MouseEvent event) { + mouseClicked = true; + coordinates.setLocation(event.getX(), event.getY()); + System.out.println(coordinates.getX() + ":" + coordinates.getY()); + } + + public boolean isMouseClicked() { + return mouseClicked; + } + + public void setMouseClicked(boolean mouseClicked) { + this.mouseClicked = mouseClicked; + } + + public Point getCoordinates() { + return coordinates; + } + + @Override + public void start(Stage primaryStage) throws Exception { + //initialize window + this.primaryStage = primaryStage; + primaryStage.setTitle("Test"); + primaryStage.setResizable(true); + this.initializeGrid(); + primaryStage.setScene(this.setScene()); + primaryStage.sizeToScene(); + primaryStage.show(); + } + + public static void main(String[] args) { + launch(args); + } +} diff --git a/Client/src/game/TicTacToe_Client.css b/Client/src/res/TicTacToe_Client.css similarity index 100% rename from Client/src/game/TicTacToe_Client.css rename to Client/src/res/TicTacToe_Client.css diff --git a/Client/src/game/TicTacToe_Grid.png b/Client/src/res/TicTacToe_Grid.png similarity index 100% rename from Client/src/game/TicTacToe_Grid.png rename to Client/src/res/TicTacToe_Grid.png diff --git a/Server/src/networking/MultiPlayerServer.java b/Server/src/networking/MultiPlayerServer.java index 7cab212..9a1be17 100644 --- a/Server/src/networking/MultiPlayerServer.java +++ b/Server/src/networking/MultiPlayerServer.java @@ -1,6 +1,6 @@ package networking; -import game.TicTacToe_Server; +import res.TicTacToe_Server; import logging.LogType; import logging.ServerLogger; @@ -11,6 +11,8 @@ import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; +import java.util.Map; +import java.util.Objects; import java.util.Scanner; public class MultiPlayerServer { @@ -35,6 +37,7 @@ public class MultiPlayerServer { scanner = new Scanner(System.in); serverLogger = new ServerLogger(); requiredConnections = 2; + serverLogger.printLog(ticTacToe_server.getGameState(), this.getClass().getName(), LogType.Log); serverLogger.printLog("Server started successfully", LogType.Log); } catch (IOException e) { @@ -66,8 +69,6 @@ public class MultiPlayerServer { outstreams.get(client).writeInt(200); outstreams.get(client).flush(); clientNames.put(client, instreams.get(client).readUTF()); - outstreams.get(client).writeUTF(serverSocket.getInetAddress().getHostAddress() + ":" + serverSocket.getLocalPort()); - outstreams.get(client).flush(); serverLogger.printLog(String.format("%s got connected", clientNames.get(client)), LogType.Log); } else { outstreams.get(client).writeInt(403); @@ -81,15 +82,15 @@ public class MultiPlayerServer { } public void ticTacToe_gameloop() { - while(clients.size() == 2) { + while (clients.size() == 2) { for (Socket client : clients.values()) { try { - String message = instreams.get(client).readUTF(); - serverLogger.printLog(message, clientNames.get(client), LogType.Message); - outstreams.get(client).writeInt(200); - outstreams.get(client).flush(); - serverLogger.printLog("Sent verification code", clientNames.get(client), LogType.Log); - this.gameFlow(message, client); + String message = instreams.get(client).readUTF(); + serverLogger.printLog(message, clientNames.get(client), LogType.Message); + outstreams.get(client).writeInt(200); + outstreams.get(client).flush(); + serverLogger.printLog("Sent verification code", clientNames.get(client), LogType.Log); + this.gameFlow(message, client); } catch (IOException e) { e.printStackTrace(); try { @@ -102,64 +103,110 @@ public class MultiPlayerServer { } } - public void gameFlow(String input, Socket client) { - switch (input) { - case "gameState": - try { - outstreams.get(client).writeUTF(ticTacToe_server.getGameState()); - outstreams.get(client).flush(); - serverLogger.printLog("Sent gameState", clientNames.get(client), LogType.Log); - break; - } catch (IOException e) { - e.printStackTrace(); - } + public void sendGameState(){ + try { + int index = 0; + for (DataOutputStream outstream: outstreams.values()) { + outstream.writeUTF(ticTacToe_server.getGameState()); + outstream.flush(); + serverLogger.printLog("Sent gameState", clientNames.get(index), LogType.Log); + index++; + } - case "update": + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void gameFlow(String input, Socket client){ + switch (input){ + case "ready": + gameFlow("gameState", client); + break; + + case "gameState": + sendGameState(); + break; + + case "clientMove": try { + //Get position (X|Y) String position = instreams.get(client).readUTF(); serverLogger.printLog(position, clientNames.get(client), LogType.Message); + //Send confirmation (2ßß) outstreams.get(client).writeInt(200); outstreams.get(client).flush(); serverLogger.printLog("Sent verification code", clientNames.get(client), LogType.Log); - boolean isAllowed = ticTacToe_server.makeClientMove(position); - if (isAllowed) { - String gameState = ticTacToe_server.getGameState(); - outstreams.get(client).writeUTF(gameState); - outstreams.get(client).flush(); - serverLogger.printLog(String.format("Sent gameState: %s", gameState), clientNames.get(client), LogType.Log); - break; + boolean moveAllowed = ticTacToe_server.makeClientMove(position); + if (moveAllowed) { + sendGameState(); } else { - outstreams.get(client).writeUTF(" "); + //send " " + outstreams.get(client).writeUTF("userInput"); outstreams.get(client).flush(); + serverLogger.printLog("Requested userInput", LogType.Log); serverLogger.printLog(String.format("Move is not allowed!"), clientNames.get(client), LogType.Error); - break; } } catch (IOException e) { e.printStackTrace(); } + break; + + case "computerMove": + ticTacToe_server.makeComputerMove(); + sendGameState(); + try { + outstreams.get(client).writeUTF("userInput"); + outstreams.get(client).flush(); + serverLogger.printLog("Requested userInput", LogType.Log); + } catch (IOException e) { + e.printStackTrace(); + } + break; + + case "serverType": + try { + outstreams.get(client).writeBoolean(true); + outstreams.get(client).flush(); + serverLogger.printLog("Sent serverType", clientNames.get(client), LogType.Log); + } catch (IOException e) { + e.printStackTrace(); + } + break; + + case "isClientOne": + for (Map.Entry entry : clients.entrySet()) { + if (Objects.equals(client, entry.getValue())) { + try { + outstreams.get(client).writeBoolean(entry.getKey() == 0); + outstreams.get(client).flush(); + serverLogger.printLog("Sent isPlayerOne", clientNames.get(client), LogType.Log); + } catch (IOException e) { + e.printStackTrace(); + } + } else { + serverLogger.printLog("Current client not in clients!", LogType.Error); + } + } + break; case "gameEnded": try { boolean gameEnded = ticTacToe_server.gameEnded(); outstreams.get(client).writeBoolean(gameEnded); if (gameEnded) { + //send coordinates String coordinates = ""; - for (Point point : ticTacToe_server.getWinCoordinates()) { + for (Point point: ticTacToe_server.getWinCoordinates()) { coordinates += point.x + ";" + point.y + ";"; } + //send winning fields outstreams.get(client).writeUTF(coordinates); - break; - } else { - ticTacToe_server.makeServerMove(); - String gameState = ticTacToe_server.getGameState(); - outstreams.get(client).writeUTF(gameState); - outstreams.get(client).flush(); - serverLogger.printLog(String.format("Sent gameState: %s", gameState), clientNames.get(client), LogType.Log); - break; } } catch (IOException e) { e.printStackTrace(); } + break; case "exit()": try { @@ -168,11 +215,11 @@ public class MultiPlayerServer { outstreams.get(client).close(); instreams.get(client).close(); client.close(); - serverLogger.printLog(String.format("%s closed the connection", clientNames.get(client)), LogType.Log); - break; + serverLogger.printLog(String.format("%s closed the connection",clientNames.get(client)), LogType.Log); } catch (IOException e) { e.printStackTrace(); } + break; } } diff --git a/Server/src/networking/SinglePlayerServer.java b/Server/src/networking/SinglePlayerServer.java index 3c12f99..087c429 100644 --- a/Server/src/networking/SinglePlayerServer.java +++ b/Server/src/networking/SinglePlayerServer.java @@ -1,6 +1,6 @@ package networking; -import game.TicTacToe_Server; +import res.TicTacToe_Server; import logging.LogType; import logging.ServerLogger; @@ -11,6 +11,8 @@ import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; +import java.util.Map; +import java.util.Objects; import java.util.Scanner; public class SinglePlayerServer { @@ -66,8 +68,6 @@ public class SinglePlayerServer { outstreams.get(client).writeInt(200); outstreams.get(client).flush(); clientNames.put(client, instreams.get(client).readUTF()); - outstreams.get(client).writeUTF(serverSocket.getInetAddress().getHostAddress()+":"+serverSocket.getLocalPort()); - outstreams.get(client).flush(); serverLogger.printLog(String.format("%s got connected", clientNames.get(client)), LogType.Log); } else { outstreams.get(client).writeInt(403); @@ -84,6 +84,7 @@ public class SinglePlayerServer { for (Socket client: clients.values()) { try { while (!client.isClosed()) { + //Get instruction String message = instreams.get(client).readUTF(); serverLogger.printLog(message, clientNames.get(client), LogType.Message); outstreams.get(client).writeInt(200); @@ -102,64 +103,105 @@ public class SinglePlayerServer { } } + public void sendGameState(Socket client){ + try { + outstreams.get(client).writeUTF(ticTacToe_server.getGameState()); + outstreams.get(client).flush(); + serverLogger.printLog("Sent gameState", clientNames.get(client), LogType.Log); + } catch (IOException e) { + e.printStackTrace(); + } + } + public void gameFlow(String input, Socket client){ switch (input){ - case "gameState": - try { - outstreams.get(client).writeUTF(ticTacToe_server.getGameState()); - outstreams.get(client).flush(); - serverLogger.printLog("Sent gameState", clientNames.get(client), LogType.Log); - break; - } catch (IOException e) { - e.printStackTrace(); - } + case "ready": + gameFlow("gameState", client); + break; - case "update": + case "gameState": + sendGameState(client); + break; + + case "clientMove": try { + //Get position (X|Y) String position = instreams.get(client).readUTF(); serverLogger.printLog(position, clientNames.get(client), LogType.Message); + //Send confirmation (2ßß) outstreams.get(client).writeInt(200); outstreams.get(client).flush(); serverLogger.printLog("Sent verification code", clientNames.get(client), LogType.Log); boolean moveAllowed = ticTacToe_server.makeClientMove(position); if (moveAllowed) { - String gameState = ticTacToe_server.getGameState(); - outstreams.get(client).writeUTF(gameState); - outstreams.get(client).flush(); - serverLogger.printLog(String.format("Sent gameState: %s", gameState), clientNames.get(client), LogType.Log); - break; + sendGameState(client); } else { - outstreams.get(client).writeUTF(" "); + //send " " + outstreams.get(client).writeUTF("userInput"); outstreams.get(client).flush(); + serverLogger.printLog("Requested userInput", LogType.Log); serverLogger.printLog(String.format("Move is not allowed!"), clientNames.get(client), LogType.Error); - break; } } catch (IOException e) { e.printStackTrace(); } + break; + + case "computerMove": + ticTacToe_server.makeComputerMove(); + sendGameState(client); + try { + outstreams.get(client).writeUTF("userInput"); + outstreams.get(client).flush(); + serverLogger.printLog("Requested userInput", LogType.Log); + } catch (IOException e) { + e.printStackTrace(); + } + break; + + case "serverType": + try { + outstreams.get(client).writeBoolean(true); + outstreams.get(client).flush(); + serverLogger.printLog("Sent serverType", clientNames.get(client), LogType.Log); + } catch (IOException e) { + e.printStackTrace(); + } + break; + + case "isClientOne": + for (Map.Entry entry : clients.entrySet()) { + if (Objects.equals(client, entry.getValue())) { + try { + outstreams.get(client).writeBoolean(entry.getKey() == 0); + outstreams.get(client).flush(); + serverLogger.printLog("Sent isPlayerOne", clientNames.get(client), LogType.Log); + } catch (IOException e) { + e.printStackTrace(); + } + } else { + serverLogger.printLog("Current client not in clients!", LogType.Error); + } + } + break; case "gameEnded": try { boolean gameEnded = ticTacToe_server.gameEnded(); outstreams.get(client).writeBoolean(gameEnded); if (gameEnded) { + //send coordinates String coordinates = ""; for (Point point: ticTacToe_server.getWinCoordinates()) { coordinates += point.x + ";" + point.y + ";"; } + //send winning fields outstreams.get(client).writeUTF(coordinates); - break; - } else { - ticTacToe_server.makeServerMove(); - String gameState = ticTacToe_server.getGameState(); - outstreams.get(client).writeUTF(gameState); - outstreams.get(client).flush(); - serverLogger.printLog(String.format("Sent gameState: %s", gameState), clientNames.get(client), LogType.Log); - break; } } catch (IOException e) { e.printStackTrace(); } + break; case "exit()": try { @@ -169,10 +211,10 @@ public class SinglePlayerServer { instreams.get(client).close(); client.close(); serverLogger.printLog(String.format("%s closed the connection",clientNames.get(client)), LogType.Log); - break; } catch (IOException e) { e.printStackTrace(); } + break; } } diff --git a/Server/src/game/TicTacToe_Server.java b/Server/src/res/TicTacToe_Server.java similarity index 98% rename from Server/src/game/TicTacToe_Server.java rename to Server/src/res/TicTacToe_Server.java index ab30ef6..dfaf859 100644 --- a/Server/src/game/TicTacToe_Server.java +++ b/Server/src/res/TicTacToe_Server.java @@ -1,4 +1,4 @@ -package game; +package res; import java.awt.*; import java.nio.charset.StandardCharsets; @@ -47,7 +47,7 @@ public class TicTacToe_Server { } } - public void makeServerMove(){ + public void makeComputerMove(){ LinkedList emptySpaces = getEmptySpaces(); if (emptySpaces.size() > 0) { Random random = new Random(); diff --git a/out/production/Client/META-INF/MANIFEST.MF b/out/production/Client/META-INF/MANIFEST.MF index b851779..eee92a3 100644 --- a/out/production/Client/META-INF/MANIFEST.MF +++ b/out/production/Client/META-INF/MANIFEST.MF @@ -1,3 +1,3 @@ Manifest-Version: 1.0 -Main-Class: game.TicTacToe_Client +Main-Class: TicTacToe_Client diff --git a/out/production/Client/game/TicTacToe_Client.css b/out/production/Client/res/TicTacToe_Client.css similarity index 100% rename from out/production/Client/game/TicTacToe_Client.css rename to out/production/Client/res/TicTacToe_Client.css diff --git a/out/production/Client/game/TicTacToe_Grid.png b/out/production/Client/res/TicTacToe_Grid.png similarity index 100% rename from out/production/Client/game/TicTacToe_Grid.png rename to out/production/Client/res/TicTacToe_Grid.png