diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Client.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Client.java new file mode 100644 index 0000000000000000000000000000000000000000..23b1c65ccd218152576cc9c7d366e68c65d1c591 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Client.java @@ -0,0 +1,49 @@ +package de.hdm_stuttgart.battlearena.Model.Multiplayer; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.net.*; +import java.io.*; +import java.util.Arrays; + +public class Client { + private Socket clientSocket; + private PrintWriter out; + private BufferedReader in; + + private static final Logger log = LogManager.getLogger(Client.class); + + public void startConnection(String ip, int port) throws IOException { + clientSocket = new Socket(ip, port); + out = new PrintWriter(clientSocket.getOutputStream(), true); + in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + } + + public int[] sendcords(int[] cords) throws IOException { + String message = String.join(",", Arrays.stream(cords).mapToObj(String::valueOf).toArray(String[]::new)); + out.println(message); + // log.info("Sent coordinates: " + message); + String resp = in.readLine(); + return convertStringToArray(resp); + } + + public static int[] convertStringToArray(String inputString) { + // Remove brackets and split by comma + String[] parts = inputString.substring(1, inputString.length() - 1).split(","); + + // Convert each part to integer + int[] result = new int[parts.length]; + for (int i = 0; i < parts.length; i++) { + result[i] = Integer.parseInt(parts[i].trim()); + } + + return result; + } + + public void stopConnection() throws IOException { + in.close(); + out.close(); + clientSocket.close(); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/ConnectionHandler.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/ConnectionHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..b47419daa11eea14e292ecab5dac7e0ae483f2b6 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/ConnectionHandler.java @@ -0,0 +1,92 @@ +package de.hdm_stuttgart.battlearena.Model.Multiplayer; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.IOException; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +public class ConnectionHandler { + + private static int pX = 0; + private static int pY = 0; + private static int enemyX = 0; + private static int enemyY = 0; + private static int playerID = 0; + private static int[] coordinates = {pX,pY,playerID}; + private static String ipaddress = "localhost"; + private static final Logger log = LogManager.getLogger(ConnectionHandler.class); + + public void startHandler() throws IOException, InterruptedException { + + Client client = new Client(); + client.startConnection(ipaddress, 4444); + + ConnectionThread connectionthread = new ConnectionThread(client); + connectionthread.start(); + + } + + private static class ConnectionThread extends Thread { + private final Client client; + + public ConnectionThread(Client client) { + this.client = client; + } + + public void run() { + try { + while (!Thread.interrupted()) { + int[] cords = client.sendcords(coordinates); + enemyX = cords[0]; + enemyY = cords[1]; + // System.out.println("Enemy X: " + enemyX); + // System.out.println("Enemy Y: " + enemyY); + // System.out.println("Your PlayerID is " + cords[2]); + playerID = cords[2]; + // Assign the Values to the message to send: + coordinates[0] = pX; + coordinates[1] = pY; + coordinates[2] = playerID; + + Thread.sleep(16); + } + } catch (InterruptedException | IOException e) { + e.printStackTrace(); // Handle the exception as needed + } + } + } + + public int getPlayerID() { + return playerID; + } + + public int getpX() { + return pX; + } + + public void setpX(int pX) { + this.pX = pX; + } + + public int getpY() { + return pY; + } + + public void setpY(int pY) { + this.pY = pY; + } + + public int getEnemyX() { + return enemyX; + } + public int getEnemyY() { + return enemyY; + } + + public static void setIpaddress(String ipaddress) { + ConnectionHandler.ipaddress = ipaddress; + } +} + diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Server.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Server.java new file mode 100644 index 0000000000000000000000000000000000000000..f3555e7b1f71b82a04f7bb75ebcd749f8bbe611a --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Server.java @@ -0,0 +1,163 @@ +package de.hdm_stuttgart.battlearena.Model.Multiplayer; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.net.*; +import java.io.*; +import java.util.Arrays; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class Server { + + private static final Logger log = LogManager.getLogger(Server.class); + private ServerSocket serverSocket; + private static boolean isServerRunning = true; + private static int px; + private static int py; + + private static int enemyx = 0; + private static int enemyy = 0; + private static int playerID; + private static int playercount = 0; + private static int[] cords; + private static int[] returncords = {enemyx,enemyy,playerID}; + private boolean started = false; + private static String ipaddress = "localhost"; + + + /* public static void main(String[] args) throws IOException { //main method for testing purposes + Server server = new Server(); + log.info("server starting..."); + server.start(ipaddress, 4444); + } */ + + public void startServer() throws IOException { + Server server = new Server(); + log.info("server starting..."); + server.start("localhost",4444); + } + + public void start(String host_ip, int port) throws IOException { + serverSocket = new ServerSocket(port); + log.info("server started!"); + started = true; + while (true){ + new ServerHandler(serverSocket.accept()).start(); + } + } + + private static class ServerHandler extends Thread { + private final Socket clientSocket; + private PrintWriter out; + private BufferedReader in; + + public ServerHandler(Socket socket) { + this.clientSocket = socket; + } + + public void run() { + ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + + executorService.scheduleAtFixedRate(() -> { + try { + BufferedReader localIn = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + PrintWriter localOut = new PrintWriter(clientSocket.getOutputStream(), true); + + String inputLine = localIn.readLine(); + + if (inputLine != null) { + // Assuming that the input line is a comma-separated list of integers + String[] coordinates = inputLine.split(","); + cords = new int[coordinates.length]; + for (int i = 0; i < coordinates.length; i++) { + cords[i] = Integer.parseInt(coordinates[i]); + } + + //first connect of a client: + if(playercount == 0){ + //first player to connect + playercount++; + returncords[2] = 1; + + } else if(playercount == 1){ + //second player to connect + if(cords[2] == 1){ + returncords[2] = 1; + } else { + playercount++; + returncords[2] = 2; + } + + } else if(playercount == 2){ + + //check which client has connected + if (cords[2] == 1) { //player + px = cords[0]; + py = cords[1]; + + //set the cords to return: + returncords[0] = enemyx; + returncords[1] = enemyy; + + //set playerID: + returncords[2] = 1; + + } else if(cords[2] == 2) { //enemy + enemyx = cords[0]; + enemyy = cords[1]; + + //set the cords to return: + returncords[0] = px; + returncords[1] = py; + + //set playerID: + returncords[2] = 2; + + } + } + + localOut.println(Arrays.toString(returncords)); + localOut.flush(); + } + + log.info("Player X / Y : " + px + " / " + py + " Enemy X / Y : " + enemyx + " / " + enemyy); + + + //check if server was shut down: + if (!isServerRunning) { + executorService.shutdown(); + try { + if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) { + executorService.shutdownNow(); + } + } catch (InterruptedException e) { + log.error("Error waiting for executor service termination: " + e.getMessage()); + } + } + + } catch (IOException e) { + throw new RuntimeException(e); + } + }, 0, 50, TimeUnit.MILLISECONDS); + } + } + + public void stopServer() { + isServerRunning = false; + try { + serverSocket.close(); // Close the server socket to break out of accept() in the main thread + } catch (IOException e) { + log.error("Error closing server socket: " + e.getMessage()); + } + } + + public boolean isStarted() { + return started; + } + public static void setIpaddress(String ipaddress) { + Server.ipaddress = ipaddress; + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/TestMap.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/TestMap.java new file mode 100644 index 0000000000000000000000000000000000000000..f6d7fdf0800d787b23fb6df532afdb898733d53c --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/TestMap.java @@ -0,0 +1,113 @@ +package de.hdm_stuttgart.battlearena.Model.Multiplayer; + +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.scene.input.KeyCode; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; +import javafx.stage.Stage; +import java.util.concurrent.TimeUnit; + +import java.io.IOException; + +public class TestMap extends Application { + private static final int SQUARE_SIZE = 50; + private static Rectangle square; + private static Rectangle enemy; + private Color color = Color.BLACK; + + @Override + public void start(Stage primaryStage) throws IOException, InterruptedException { + + ConnectionHandler handler = new ConnectionHandler(); + handler.startHandler(); + + TimeUnit.SECONDS.sleep(1); + + square = new Rectangle(SQUARE_SIZE, SQUARE_SIZE, color); + enemy = new Rectangle(SQUARE_SIZE, SQUARE_SIZE, color); + + Pane root = new Pane(); + root.getChildren().add(square); + root.getChildren().add(enemy); + + Scene scene = new Scene(root, 400, 400); + + scene.setOnKeyPressed(event -> handleKeyPress(event.getCode(), handler)); + + primaryStage.setTitle("Player #" + handler.getPlayerID()); + primaryStage.setScene(scene); + primaryStage.show(); + + if(handler.getPlayerID() == 1){ + square.setX(50); + square.setY(50); + enemy.setX(200); + enemy.setY(50); + } else if(handler.getPlayerID() == 2){ + square.setX(200); + square.setY(50); + enemy.setX(50); + enemy.setY(50); + } + + UpdateThread update = new UpdateThread(handler); + update.start(); + + } + + private void handleKeyPress(KeyCode code, ConnectionHandler handler) { + switch (code) { + case UP: + square.setY(square.getY() - 20); + handler.setpY(handler.getpY() - 20); + break; + case DOWN: + square.setY(square.getY() + 20); + handler.setpY(handler.getpY() + 20); + break; + case LEFT: + square.setX(square.getX() - 20); + handler.setpX(handler.getpX() - 20); + break; + case RIGHT: + square.setX(square.getX() + 20); + handler.setpX(handler.getpX() + 20); + break; + } + } + + private static class UpdateThread extends Thread { + private final ConnectionHandler handler; + + private UpdateThread(ConnectionHandler handler) { + this.handler = handler; + } + + public void run() { + while (true){ + + handler.setpX((int) square.getX()); + handler.setpY((int) square.getY()); + + //receive cords + enemy.setX(handler.getEnemyX()); + enemy.setY(handler.getEnemyY()); + + + try { + Thread.sleep(16); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + + } + } + + public static void main(String[] args) throws IOException { + launch(args); + } +} \ No newline at end of file diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 13a3d1d34ef25e809dd1dd1467218739070f8357..dc5aa99a6f9708a543fda0241559b51167db7e17 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -6,10 +6,7 @@ module gui { opens de.hdm_stuttgart.battlearena to javafx.fxml; - opens de.hdm_stuttgart.battlearena.Controller to javafx.fxml; exports de.hdm_stuttgart.battlearena.Main; exports de.hdm_stuttgart.battlearena.Controller; - exports de.hdm_stuttgart.battlearena.Model.Entity; - exports de.hdm_stuttgart.battlearena.Model.Inputs; - exports de.hdm_stuttgart.battlearena.Model.Map; -} \ No newline at end of file + exports de.hdm_stuttgart.battlearena.Model.Multiplayer; +}