diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityClass.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityClass.java new file mode 100644 index 0000000000000000000000000000000000000000..03b800acd74ad72318dee1df4dbf6528c53bf6d6 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityClass.java @@ -0,0 +1,8 @@ +package de.hdm_stuttgart.battlearena.Model.Entity; + +public enum EntityClass { + HUMAN, + HIGH_BORN, + LOW_BORN, + SENTINELS +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityDirection.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityDirection.java new file mode 100644 index 0000000000000000000000000000000000000000..c86d3e0e25d51cf090cede9ef3a3167745be7d0a --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityDirection.java @@ -0,0 +1,8 @@ +package de.hdm_stuttgart.battlearena.Model.Entity; + +public enum EntityDirection { + UP, + DOWN, + LEFT, + RIGHT +} 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 index 95967c90b0b30ad5c9832df6cb003e38f1463a3f..ec33d875df97fe74ee69a806c5842c00bc416414 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/ConnectionHandler.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/ConnectionHandler.java @@ -1,10 +1,255 @@ package de.hdm_stuttgart.battlearena.Model.Multiplayer; -import org.apache.logging.log4j.Logger; +import de.hdm_stuttgart.battlearena.Model.Entity.EntityClass; +import de.hdm_stuttgart.battlearena.Model.Entity.EntityDirection; 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 playerAttacking = 1; + private static int enemyAttacking = 0; + private static int playerClass = 0; + private static int enemyClass = 0; + private static int playerWalkDirection = 2; + private static int enemyWalkDirection = 0; + private static int playerHealth = 10; + private static int enemyHealth = 10; + private static int[] coordinates = {pX,pY,playerID,playerAttacking,playerClass,playerWalkDirection,playerHealth}; + 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]; + playerID = cords[2]; + enemyAttacking = cords[3]; + enemyClass = cords[4]; + enemyWalkDirection = cords[5]; + enemyHealth = cords[6]; + // Assign the Values to the message to send: + coordinates[0] = pX; + coordinates[1] = pY; + coordinates[2] = playerID; + coordinates[3] = playerAttacking; + coordinates[4] = playerClass; + coordinates[5] = playerWalkDirection; + coordinates[6] = playerHealth; + Thread.sleep(50); + } + } 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; + } + + //Getters and Setter for all other information that are not coordinates: + + public static boolean getPlayerAttacking() { + if (playerAttacking == 1){ + return true; + } else { + return false; + } + } + + public static void setPlayerAttacking(boolean attack) { + if (attack){ + ConnectionHandler.playerAttacking = 1; + } else { + ConnectionHandler.playerAttacking = 0; + } + } + + public static boolean getEnemyAttacking() { + if (enemyAttacking == 1){ + return true; + } else { + return false; + } + } + + public static void setEnemyAttacking(boolean attack) { + if (attack){ + ConnectionHandler.enemyAttacking = 1; + } else { + ConnectionHandler.enemyAttacking = 0; + } + } + + public static EntityClass getPlayerClass() { + if (playerClass == 1) { + return EntityClass.HIGH_BORN; + } else if (playerClass == 2) { + return EntityClass.LOW_BORN; + } else if (playerClass == 3) { + return EntityClass.SENTINELS; + } else { + return EntityClass.HUMAN; + } + } + + public static void setPlayerClass(EntityClass player) { + if (player == EntityClass.HUMAN){ + ConnectionHandler.playerClass = 0; + } else if (player == EntityClass.HIGH_BORN) { + ConnectionHandler.playerClass = 1; + } else if (player == EntityClass.LOW_BORN){ + ConnectionHandler.playerClass = 2; + } else { + ConnectionHandler.playerClass = 3; + } + } + + public static EntityClass getEnemyClass() { + if (enemyClass == 1) { + return EntityClass.HIGH_BORN; + } else if (enemyClass == 2) { + return EntityClass.LOW_BORN; + } else if (enemyClass == 3) { + return EntityClass.SENTINELS; + } else { + return EntityClass.HUMAN; + } + } + + public static void setEnemyClass(EntityClass player) { + if (player == EntityClass.HUMAN){ + ConnectionHandler.enemyClass = 0; + } else if (player == EntityClass.HIGH_BORN) { + ConnectionHandler.enemyClass = 1; + } else if (player == EntityClass.LOW_BORN){ + ConnectionHandler.enemyClass = 2; + } else { + ConnectionHandler.enemyClass = 3; + } + } + + public static EntityDirection getPlayerWalkDirection() { + if (playerWalkDirection == 1){ + return EntityDirection.RIGHT; + } else if (playerWalkDirection == 2){ + return EntityDirection.DOWN; + } else if (playerWalkDirection == 3){ + return EntityDirection.LEFT; + } else { + return EntityDirection.UP; + } + } + + public static void setPlayerWalkDirection(EntityDirection walk) { + if (walk == EntityDirection.RIGHT) { + ConnectionHandler.playerWalkDirection = 1; + } else if (walk == EntityDirection.DOWN) { + ConnectionHandler.playerWalkDirection = 2; + } else if (walk == EntityDirection.LEFT) { + ConnectionHandler.playerWalkDirection = 3; + } else { + ConnectionHandler.playerWalkDirection = 0; + } + } + + public static EntityDirection getEnemyWalkDirection() { + if (enemyWalkDirection == 1){ + return EntityDirection.RIGHT; + } else if (enemyWalkDirection == 2){ + return EntityDirection.DOWN; + } else if (enemyWalkDirection == 3){ + return EntityDirection.LEFT; + } else { + return EntityDirection.UP; + } + } + + public static void setEnemyWalkDirection(EntityDirection walk) { + if (walk == EntityDirection.RIGHT) { + ConnectionHandler.enemyWalkDirection = 1; + } else if (walk == EntityDirection.DOWN) { + ConnectionHandler.enemyWalkDirection = 2; + } else if (walk == EntityDirection.LEFT) { + ConnectionHandler.enemyWalkDirection = 3; + } else { + ConnectionHandler.enemyWalkDirection = 0; + } + } + + public static int getPlayerHealth() { + return playerHealth; + } + + public static void setPlayerHealth(int playerHealth) { + ConnectionHandler.playerHealth = playerHealth; + } + + public static int getEnemyHealth() { + return enemyHealth; + } + + public static void setEnemyHealth(int enemyHealth) { + ConnectionHandler.enemyHealth = enemyHealth; + } + + public static void setIpaddress(String ipaddress) { + ConnectionHandler.ipaddress = ipaddress; + } } + diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/GameServer.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/GameServer.java deleted file mode 100644 index 6a4e74cfa64ea68224b76119f3943de4ee62457d..0000000000000000000000000000000000000000 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/GameServer.java +++ /dev/null @@ -1,10 +0,0 @@ -package de.hdm_stuttgart.battlearena.Model.Multiplayer; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; - -public class GameServer { - - private static final Logger log = LogManager.getLogger(GameServer.class); - -} 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..bec0adea4bc85347f21693500d5235490147e268 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Server.java @@ -0,0 +1,197 @@ +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 playerAttacking = 0; + private static int enemyAttacking = 0; + private static int playerClass = 0; + private static int enemyClass = 0; + private static int playerWalkDirection = 0; + private static int enemyWalkDirection = 0; + private static int playerHealth = 0; + private static int enemyHealth = 0; + private static int playercount = 0; + private static int[] cords; + private static int[] returncords = {enemyx,enemyy,playerID,enemyAttacking,enemyClass,enemyWalkDirection,enemyHealth}; + private boolean started = false; + + + public static void main(String[] args) throws IOException { //main method for testing purposes + Server server = new Server(); + log.info("server starting..."); + server.start( 4444); + } + + public void startServer() throws IOException { + Server server = new Server(); + log.info("server starting..."); + server.start(4444); + } + + public void start(int port) throws IOException { + serverSocket = new ServerSocket(port); + log.info("server started!"); + started = true; + + log.info("server accepting Thread starting..."); + Thread serverThread = new Thread(() -> { + while (true) { + try { + new ServerHandler(serverSocket.accept()).start(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + serverThread.start(); + log.info("requests accepting Thread started!"); + + } + + 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]; + playerAttacking = cords[3]; + playerClass = cords[4]; + playerWalkDirection = cords[5]; + playerHealth = cords[6]; + + //set the cords to return: + returncords[0] = enemyx; + returncords[1] = enemyy; + returncords[3] = enemyAttacking; + returncords[4] = enemyClass; + returncords[5] = enemyWalkDirection; + returncords[6] = enemyHealth; + + //set playerID: + returncords[2] = 1; + + } else if(cords[2] == 2) { + //enemy + enemyx = cords[0]; + enemyy = cords[1]; + enemyAttacking = cords[3]; + enemyClass = cords[4]; + enemyWalkDirection = cords[5]; + enemyHealth = cords[6]; + + //set the cords to return: + returncords[0] = px; + returncords[1] = py; + returncords[3] = playerAttacking; + returncords[4] = playerClass; + returncords[5] = playerWalkDirection; + returncords[6] = playerHealth; + + //set playerID: + returncords[2] = 2; + } + } + + localOut.println(Arrays.toString(returncords)); + localOut.flush(); + } + + log.info("Player (X Y) : " + px + " " + py + " Attacking : " + playerAttacking + " direction : " + playerWalkDirection + " HP: " + playerHealth); + log.info(" Enemy (X Y) : " + enemyx + " " + enemyy + " Attacking : " + enemyAttacking + " direction : " + enemyWalkDirection + " HP: " + enemyHealth); + + //check if server was shut down:W + 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; + } + + +} 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 c37776eeb147449e3fa1dbb6aaf650b8c5f12637..dc5aa99a6f9708a543fda0241559b51167db7e17 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -4,7 +4,9 @@ module gui { requires javafx.media; requires org.apache.logging.log4j; + opens de.hdm_stuttgart.battlearena to javafx.fxml; exports de.hdm_stuttgart.battlearena.Main; exports de.hdm_stuttgart.battlearena.Controller; + exports de.hdm_stuttgart.battlearena.Model.Multiplayer; }