From 5cabd5325a358c40a247685565807a516820c2fe Mon Sep 17 00:00:00 2001 From: Kaver Date: Tue, 26 Nov 2024 16:42:00 +0100 Subject: [PATCH 01/25] Umstrukturierung von MainFrame, sodass beim druecken eines Buttons parameter an die Funktion uebergeben werden welche das naechste Panel stellt (showPanelExtra) --- src/JoinGame.java | 14 ++++++++++---- src/MainFrame.java | 26 ++++++++++++++++++++++++-- src/startMultiplayerGame.java | 6 ++++-- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/JoinGame.java b/src/JoinGame.java index e980b58..0c66aa3 100644 --- a/src/JoinGame.java +++ b/src/JoinGame.java @@ -4,7 +4,7 @@ import javax.swing.JFrame; import javax.swing.*; public class JoinGame extends JPanel { - JLabel spielBeitretenLabel= new JLabel("Spiel beitreten"); + JLabel spielBeitretenLabel; JLabel ipLabel = new JLabel("IP-Adresse"); JLabel portLabel = new JLabel("Port"); @@ -15,12 +15,18 @@ public class JoinGame extends JPanel { Font robotoFont = new Font("Roboto", Font.BOLD, 45); - public JoinGame(MainFrame frame) { + public JoinGame(MainFrame frame,int g) { setLayout(null); - buildPanel(frame); + buildPanel(frame,g); } - private void buildPanel(MainFrame frame) { + private void buildPanel(MainFrame frame,int g) { + if(g==1){ + spielBeitretenLabel= new JLabel("Spiel beitreten"); + }else{ + spielBeitretenLabel= new JLabel("Spiel erstellen"); + } + spielBeitretenLabel.setBounds(20,20,700, 100); losButton.setBounds(320, 225, 100, 50); diff --git a/src/MainFrame.java b/src/MainFrame.java index f8a5204..567505f 100644 --- a/src/MainFrame.java +++ b/src/MainFrame.java @@ -5,6 +5,7 @@ public class MainFrame extends JFrame { private CardLayout cardLayout; private JPanel mainPanel; + int localMult; public MainFrame() { setTitle("Studium Versenken"); @@ -27,13 +28,13 @@ public class MainFrame extends JFrame { startLocalGame localGame = new startLocalGame(this); startMultiplayerGame multiplayerGame = new startMultiplayerGame(this); coinToss coinToss = new coinToss(this); - JoinGame joinGame = new JoinGame(this); + //JoinGame joinGame = new JoinGame(this,localMult); mainPanel.add(mainMenuView, "MainMenu"); mainPanel.add(localGame, "LocalGame"); mainPanel.add(multiplayerGame, "MultiplayerGame"); mainPanel.add(coinToss, "coinToss"); - mainPanel.add(joinGame, "JoinGame"); + //mainPanel.add(joinGame, "JoinGame"); // Hauptpanel in JFrame hinzufügen add(mainPanel); @@ -46,6 +47,27 @@ public class MainFrame extends JFrame { cardLayout.show(mainPanel, panelName); } + public void showPanelExtra(String panelName,int num) { + this.localMult = num; + + if (!isPanelPresent(panelName)) { + JoinGame joinGame = new JoinGame(this, localMult); + mainPanel.add(joinGame, panelName); // Dynamically add the panel + mainPanel.revalidate(); // Refresh the layout + mainPanel.repaint(); + } + + cardLayout.show(mainPanel, panelName); // Show the panel + } + private boolean isPanelPresent(String panelName) { + for (Component component : mainPanel.getComponents()) { + if (panelName.equals(mainPanel.getClientProperty("name"))) { + return true; + } + } + return false; + } + public static void main(String[] args) { SwingUtilities.invokeLater(() -> { MainFrame frame = new MainFrame(); diff --git a/src/startMultiplayerGame.java b/src/startMultiplayerGame.java index 4598994..abc7d67 100644 --- a/src/startMultiplayerGame.java +++ b/src/startMultiplayerGame.java @@ -6,7 +6,8 @@ public class startMultiplayerGame extends JPanel { // Funktionshilfen int semesterCounter = 1; // Semester Counter Label String PlayerNickname = "Spieler 1"; - + int multlocal; + String test; // Grafiken ImageIcon backButtonIcon = new ImageIcon("graphics/backButton.png"); ImageIcon humanPlayerIcon = new ImageIcon("graphics/humanPlayer.png"); @@ -109,7 +110,8 @@ public class startMultiplayerGame extends JPanel { // ActionListener für den "Back" Button, um zum vorherigen Panel zurückzukehren backButton.addActionListener(e -> frame.showPanel("MainMenu")); - joinGameButton.addActionListener(e -> frame.showPanel("JoinGame")); + joinGameButton.addActionListener(e -> frame.showPanelExtra("JoinGame",1)); + createGameButton.addActionListener(e -> frame.showPanelExtra("JoinGame",0)); } // TOGGLE METHODEN From 88d016ed9986062df023062f22e67b0afc31e17c Mon Sep 17 00:00:00 2001 From: Kaver Date: Tue, 26 Nov 2024 16:43:14 +0100 Subject: [PATCH 02/25] Umstrukturierung von MainFrame, sodass beim druecken eines Buttons parameter an die Funktion uebergeben werden welche das naechste Panel stellt (showPanelExtra) --- src/JoinGame.java | 2 -- src/startMultiplayerGame.java | 4 ---- 2 files changed, 6 deletions(-) diff --git a/src/JoinGame.java b/src/JoinGame.java index 0c66aa3..fdacd3a 100644 --- a/src/JoinGame.java +++ b/src/JoinGame.java @@ -1,6 +1,4 @@ import java.awt.*; -import java.awt.event.ActionEvent; -import javax.swing.JFrame; import javax.swing.*; public class JoinGame extends JPanel { diff --git a/src/startMultiplayerGame.java b/src/startMultiplayerGame.java index abc7d67..ad73f7c 100644 --- a/src/startMultiplayerGame.java +++ b/src/startMultiplayerGame.java @@ -1,13 +1,9 @@ import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; public class startMultiplayerGame extends JPanel { // Funktionshilfen int semesterCounter = 1; // Semester Counter Label String PlayerNickname = "Spieler 1"; - int multlocal; - String test; // Grafiken ImageIcon backButtonIcon = new ImageIcon("graphics/backButton.png"); ImageIcon humanPlayerIcon = new ImageIcon("graphics/humanPlayer.png"); From 2274a1e558184a31eea5f4d586d2f0f2ced69b0a Mon Sep 17 00:00:00 2001 From: Joshua Date: Tue, 26 Nov 2024 17:15:21 +0100 Subject: [PATCH 03/25] Created GameBoard. Added showPanel methods to pass parameters between methods. --- graphics/gameboardempty.png | Bin 0 -> 84 bytes graphics/gameboardx.png | Bin 0 -> 171 bytes src/GameBoard.java | 112 +++++++++++++++++++++++++++++++++- src/MainFrame.java | 36 +++++++++-- src/startLocalGame.java | 2 +- src/startMultiplayerGame.java | 4 +- 6 files changed, 145 insertions(+), 9 deletions(-) create mode 100644 graphics/gameboardempty.png create mode 100644 graphics/gameboardx.png diff --git a/graphics/gameboardempty.png b/graphics/gameboardempty.png new file mode 100644 index 0000000000000000000000000000000000000000..366ceab3b13ec07b4d599d4ffe961e697fb8c3d1 GIT binary patch literal 84 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf67>k44ofy`glX(f`@Oip8hGJeE~TVv85N*!KA0mS1O1 zY;We-B2*uFwrImSuf1+h0uBgwHvPTtsNH-`B&zyDsW4-Rs=L!=!%+WUoz{$#j~Q_- T;96%7w2;Bm)z4*}Q$iB}F|Iw) literal 0 HcmV?d00001 diff --git a/src/GameBoard.java b/src/GameBoard.java index 61bdb72..c4dda52 100644 --- a/src/GameBoard.java +++ b/src/GameBoard.java @@ -1,3 +1,113 @@ -public class GameBoard { +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +public class GameBoard extends JPanel { + // Funktionshilfen + //int semesterCounter = 1; //TODO: ersetzen durch param von vorpanel + + // Grafiken + ImageIcon backButtonIcon = new ImageIcon("graphics/backButton.png"); + ImageIcon gameBoardEmtpy = new ImageIcon("graphics/gameboardempty.png"); + ImageIcon gameBoardX = new ImageIcon("graphics/gameboardx.png"); + + // Labels + JLabel frameTitle = new JLabel("GameBoard"); + JLabel kontextText = new JLabel("Beispielhafter Kontext-Text"); + //kontextText.setFont(new Font("Roboto", Font.BOLD, 24)); //TODO setFont fixen + + JButton backButton = new JButton(backButtonIcon); + // Eigene ModulButtons + JButton leftPlayerModul1 = new JButton("Modul 1"); //TODO: Dynamische Namen durch abgleich mit Semester + JButton leftPlayerModul2 = new JButton("Modul 2"); + JButton leftPlayerModul3 = new JButton("Modul 3"); + JButton leftPlayerModul4 = new JButton("Modul 4"); + JButton leftPlayerModul5 = new JButton("Modul 5"); + JButton leftPlayerModul6 = new JButton("Modul 6"); + JButton leftPlayerModul7 = new JButton("Reset"); + // Gegnerische ModulButtons + JButton rightPlayerModul1 = new JButton("Modul 1"); + JButton rightPlayerModul2 = new JButton("Modul 2"); + JButton rightPlayerModul3 = new JButton("Modul 3"); + JButton rightPlayerModul4 = new JButton("Modul 4"); + JButton rightPlayerModul5 = new JButton("Modul 5"); + JButton rightPlayerModul6 = new JButton("Modul 6"); + JButton rightPlayerModul7 = new JButton("Bereit"); + + public void buildPanel(MainFrame frame, int semesterCounter) { + // Hauptlayout - BorderLayout für die Anordnung der Komponenten + setLayout(new BorderLayout()); + + // Panel für das Kontext-Text-Feld + JPanel headerPanel = new JPanel(); + headerPanel.setLayout(new BorderLayout()); + headerPanel.add(kontextText, BorderLayout.WEST); + headerPanel.add(backButton, BorderLayout.EAST); + + // Panel für die Buttons des linken Spielers (ganz links) + JPanel leftButtonsPanel = new JPanel(); + leftButtonsPanel.setLayout(new GridLayout(7, 1)); // 6 Buttons untereinander + leftButtonsPanel.add(leftPlayerModul1); + leftButtonsPanel.add(leftPlayerModul2); + leftButtonsPanel.add(leftPlayerModul3); + leftButtonsPanel.add(leftPlayerModul4); + leftButtonsPanel.add(leftPlayerModul5); + leftButtonsPanel.add(leftPlayerModul6); + leftButtonsPanel.add(leftPlayerModul7); + + // Panel für die Buttons des rechten Spielers (ganz rechts) + JPanel rightButtonsPanel = new JPanel(); + rightButtonsPanel.setLayout(new GridLayout(7, 1)); // 6 Buttons untereinander + rightButtonsPanel.add(rightPlayerModul1); + rightButtonsPanel.add(rightPlayerModul2); + rightButtonsPanel.add(rightPlayerModul3); + rightButtonsPanel.add(rightPlayerModul4); + rightButtonsPanel.add(rightPlayerModul5); + rightButtonsPanel.add(rightPlayerModul6); + rightButtonsPanel.add(rightPlayerModul7); + + // Spielfelder erstellen (eigenes und gegnerisches) + int gridSize = 13 + semesterCounter; // Größe des Spielfelds + JPanel ownBoardPanel = new JPanel(new GridLayout(gridSize, gridSize)); + JPanel opponentBoardPanel = new JPanel(new GridLayout(gridSize, gridSize)); + + // Buttons für das eigene Spielfeld hinzufügen + for (int i = 0; i < gridSize; i++) { + for (int j = 0; j < gridSize; j++) { + ownBoardPanel.add(new JButton(gameBoardEmtpy)); + } + } + + // Buttons für das gegnerische Spielfeld hinzufügen + for (int i = 0; i < gridSize; i++) { + for (int j = 0; j < gridSize; j++) { + opponentBoardPanel.add(new JButton(gameBoardEmtpy)); + } + } + + // Panel für beide Spielfelder (nebeneinander in der Mitte) + JPanel centerPanel = new JPanel(); + centerPanel.setLayout(new GridLayout(1, 2, 20, 0)); // 2 Spielfelder nebeneinander, mit Abstand von 20 Pixeln + centerPanel.add(ownBoardPanel); + centerPanel.add(opponentBoardPanel); + + // Panels dem Hauptlayout hinzufügen + add(leftButtonsPanel, BorderLayout.WEST); + add(rightButtonsPanel, BorderLayout.EAST); + add(headerPanel, BorderLayout.NORTH); + add(centerPanel, BorderLayout.CENTER); + } + + GameBoard(MainFrame frame,int semesterCounter) { + buildPanel(frame, semesterCounter); + /* + rightPlayerRightButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + toggleRightPlayerIcon(); + updateTextFields(); + } + }); */ + } } diff --git a/src/MainFrame.java b/src/MainFrame.java index 567505f..3c7ee8c 100644 --- a/src/MainFrame.java +++ b/src/MainFrame.java @@ -5,8 +5,17 @@ public class MainFrame extends JFrame { private CardLayout cardLayout; private JPanel mainPanel; + + // ---------- // + // Diverse Hilfsvariablen (für Parameterübergabe etc.) + // Von startMultiplayerGame an JoinGame int localMult; + // Von startLocalGame an GameBoard + int semesterCounter; + // ---------- // + + public MainFrame() { setTitle("Studium Versenken"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); @@ -29,12 +38,15 @@ public class MainFrame extends JFrame { startMultiplayerGame multiplayerGame = new startMultiplayerGame(this); coinToss coinToss = new coinToss(this); //JoinGame joinGame = new JoinGame(this,localMult); + //GameBoard gameBoard = new GameBoard(this, localMult); mainPanel.add(mainMenuView, "MainMenu"); mainPanel.add(localGame, "LocalGame"); mainPanel.add(multiplayerGame, "MultiplayerGame"); mainPanel.add(coinToss, "coinToss"); //mainPanel.add(joinGame, "JoinGame"); + //mainPanel.add(gameBoard, "GameBoard"); + // Hauptpanel in JFrame hinzufügen add(mainPanel); @@ -46,19 +58,33 @@ public class MainFrame extends JFrame { public void showPanel(String panelName) { cardLayout.show(mainPanel, panelName); } - - public void showPanelExtra(String panelName,int num) { + // --- ShowPanel der startMultiplayerGame Klasse + public void showPanelSMG(String panelName, int num) { this.localMult = num; - if (!isPanelPresent(panelName)) { + //if (!isPanelPresent(panelName)) { //TODO potentiell raus JoinGame joinGame = new JoinGame(this, localMult); mainPanel.add(joinGame, panelName); // Dynamically add the panel mainPanel.revalidate(); // Refresh the layout mainPanel.repaint(); - } + //} cardLayout.show(mainPanel, panelName); // Show the panel } + // --- ShowPanel der startLocalGame Klasse + public void showPanelSLG(String panelName,int semesterCounter) { + this.semesterCounter = semesterCounter; + + //if (!isPanelPresent(panelName)) { //TODO potentiell raus + GameBoard gameBoard = new GameBoard(this, semesterCounter); + mainPanel.add(gameBoard, panelName); // Dynamically add the panel + mainPanel.revalidate(); // Refresh the layout + mainPanel.repaint(); + //} + + cardLayout.show(mainPanel, panelName); // Show the panel + } + /* TODO ist dies unnötig? private boolean isPanelPresent(String panelName) { for (Component component : mainPanel.getComponents()) { if (panelName.equals(mainPanel.getClientProperty("name"))) { @@ -66,7 +92,7 @@ public class MainFrame extends JFrame { } } return false; - } + } */ public static void main(String[] args) { SwingUtilities.invokeLater(() -> { diff --git a/src/startLocalGame.java b/src/startLocalGame.java index 8dcc513..1dab9c1 100644 --- a/src/startLocalGame.java +++ b/src/startLocalGame.java @@ -143,7 +143,7 @@ public class startLocalGame extends JPanel { backButton.addActionListener(e -> frame.showPanel("MainMenu")); - startButton.addActionListener(e -> frame.showPanel("coinToss")); // TODO ECHTE FUNKTION EINFÜGEN + startButton.addActionListener(e -> frame.showPanelSLG("GameBoard", semesterCounter)); // TODO ECHTE FUNKTION EINFÜGEN } private void toggleLeftPlayerIcon() { diff --git a/src/startMultiplayerGame.java b/src/startMultiplayerGame.java index ad73f7c..e1d00be 100644 --- a/src/startMultiplayerGame.java +++ b/src/startMultiplayerGame.java @@ -106,8 +106,8 @@ public class startMultiplayerGame extends JPanel { // ActionListener für den "Back" Button, um zum vorherigen Panel zurückzukehren backButton.addActionListener(e -> frame.showPanel("MainMenu")); - joinGameButton.addActionListener(e -> frame.showPanelExtra("JoinGame",1)); - createGameButton.addActionListener(e -> frame.showPanelExtra("JoinGame",0)); + joinGameButton.addActionListener(e -> frame.showPanelSMG("JoinGame",1)); + createGameButton.addActionListener(e -> frame.showPanelSMG("JoinGame",0)); } // TOGGLE METHODEN From a381c8d6602dd65fc24891dd51448f1afb10b642 Mon Sep 17 00:00:00 2001 From: Ole Wachtel Date: Sat, 30 Nov 2024 13:25:42 +0100 Subject: [PATCH 04/25] add OnlinePlayer Konstructer --- src/OnlinePlayer.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/OnlinePlayer.java b/src/OnlinePlayer.java index 66316d6..023bebb 100644 --- a/src/OnlinePlayer.java +++ b/src/OnlinePlayer.java @@ -1,11 +1,20 @@ +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; import java.net.Socket; public abstract class OnlinePlayer extends Player{ private Socket socket; + private BufferedReader netIn; + private PrintWriter netOut; - public OnlinePlayer(int size, Socket socket) { + public OnlinePlayer(int size, Socket socket, BufferedReader netIn) throws IOException { super(size); this.socket = socket; + this.netIn = netIn; + this.netOut = new PrintWriter(socket.getOutputStream(), true); //TODO Auto-generated constructor stub } } From c92b3b355164336e54c54fccfe986b52d44eb5a9 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 13:45:06 +0100 Subject: [PATCH 05/25] networking basis --- src/AsyncSocket.java | 80 ++++++++++++++++++++++++++++++++++++ src/AsyncSocketListener.java | 3 ++ src/GameController.java | 42 +++++++++++++++++-- src/OnlinePlayer.java | 11 ++--- src/OnlinePlayer_1_1_0.java | 13 ++++++ src/SocketPackage.java | 55 +++++++++++++++++++++++++ 6 files changed, 195 insertions(+), 9 deletions(-) create mode 100644 src/AsyncSocket.java create mode 100644 src/AsyncSocketListener.java create mode 100644 src/OnlinePlayer_1_1_0.java create mode 100644 src/SocketPackage.java diff --git a/src/AsyncSocket.java b/src/AsyncSocket.java new file mode 100644 index 0000000..e91019d --- /dev/null +++ b/src/AsyncSocket.java @@ -0,0 +1,80 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.Socket; + +public class AsyncSocket { + private Socket socket; + private Thread checkerThread; + private AsyncSocketListener handler; + private boolean shouldStop = false; + + private BufferedReader in; + private PrintWriter out; + + public AsyncSocket(Socket socket, AsyncSocketListener handler) throws IOException { + this.socket = socket; + + this.in = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); + this.out = new PrintWriter(new OutputStreamWriter(this.socket.getOutputStream())); + + this.handler = handler; + + this.checkerThread = new Thread(() -> { + while (!this.shouldStop) { + try { + if (!this.in.ready()) continue; + if (this.handler == null) continue; + + String message = this.in.readLine(); + if (message.length() <= 0) continue; + + this.handler.receive(message); + } catch (IOException e) { + e.printStackTrace(); + } + + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }); + this.checkerThread.start(); + } + + public void setHandler(AsyncSocketListener handler) { + this.handler = handler; + } + + + public void send(SocketPackage socketPackage) { + this.sendLine(socketPackage.toString()); + } + public void send(String packageName) { + this.send(packageName, ""); + } + public void send(String packageName, String packageContent) { + if (packageContent.length() > 0) { + packageContent = " " + packageContent; + } + this.sendLine(packageName + packageContent); + } + + public void sendLine(String message) { + this.out.print(message + "\r\n"); + } + + public void close() { + this.shouldStop = true; + + try { + this.socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/AsyncSocketListener.java b/src/AsyncSocketListener.java new file mode 100644 index 0000000..a8c78ba --- /dev/null +++ b/src/AsyncSocketListener.java @@ -0,0 +1,3 @@ +public interface AsyncSocketListener { + public void receive(String message); +} \ No newline at end of file diff --git a/src/GameController.java b/src/GameController.java index 1d562eb..5b3aa88 100644 --- a/src/GameController.java +++ b/src/GameController.java @@ -1,11 +1,45 @@ +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.util.Arrays; +import java.util.HashMap; + public class GameController { + // TODO: fix syntax i guess + public HashMap> supportedVersions = [{ "1.1.0" : OnlinePlayer_1_1_0.class }]; - public void startOnlineGame() { - // fuck you Luca and Ole von Florian und nicht von Florian - } + public void startOnlineGame(Class localPlayerClass, InetSocketAddress address) { + if (address.getHostName() == null) { + // SERVER MODE + try { + ServerSocket serverSocket = new ServerSocket(address.getPort()); - public void startLocalGame(Class localPlayerClass, Class enemyClass, int size) throws InstantiationException, IllegalAccessException { + System.out.println("Waiting for client connection..."); + + AsyncSocket clientSocket = new AsyncSocket(serverSocket.accept(), null); + clientSocket.send("VERSION", "Gruppe03 1.1.0"); // TODO: adjust versioning list + clientSocket.setHandler((message) -> { + + new OnlinePlayer_1_1_0(0, clientSocket); + + try { + serverSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + + } catch (IOException e) { + e.printStackTrace(); + return; + } + } else { + // CLIENT MODE + } + } + + public void startLocalGame(Class localPlayerClass, Class enemyClass, int size) { LocalPlayer localPlayer; AiPlayer aiPlayer; diff --git a/src/OnlinePlayer.java b/src/OnlinePlayer.java index 66316d6..f3aaaf8 100644 --- a/src/OnlinePlayer.java +++ b/src/OnlinePlayer.java @@ -1,11 +1,12 @@ -import java.net.Socket; +public abstract class OnlinePlayer extends Player implements AsyncSocketListener{ + private AsyncSocket socket; -public abstract class OnlinePlayer extends Player{ - private Socket socket; - - public OnlinePlayer(int size, Socket socket) { + public OnlinePlayer(int size, AsyncSocket socket) { super(size); this.socket = socket; //TODO Auto-generated constructor stub } + + public abstract void receive(String message); + } diff --git a/src/OnlinePlayer_1_1_0.java b/src/OnlinePlayer_1_1_0.java new file mode 100644 index 0000000..916b294 --- /dev/null +++ b/src/OnlinePlayer_1_1_0.java @@ -0,0 +1,13 @@ +public class OnlinePlayer_1_1_0 extends OnlinePlayer { + public OnlinePlayer_1_1_0(int size, AsyncSocket socket) { + super(size, socket); + } + + @Override + public void receive(String message) { + SocketPackage p = new SocketPackage(message); + + // TODO: parse package + } + +} \ No newline at end of file diff --git a/src/SocketPackage.java b/src/SocketPackage.java new file mode 100644 index 0000000..8f7e6ca --- /dev/null +++ b/src/SocketPackage.java @@ -0,0 +1,55 @@ +import java.util.Arrays; +import java.util.List; +public class SocketPackage { + + private String name; + private String data; + + public SocketPackage(String name, String data) { + this.setName(name); + this.setData(data); + } + public SocketPackage() { + this("",""); + } + public SocketPackage(String message) { + if (message.length() <= 0) { + throw new IllegalArgumentException("Socket message cannot be empty."); + } + String[] components = message.split(" "); + this.setName(components[0]); + if (components.length > 1) { + this.data = message.substring(components[0].length() + 1); + } else { + this.data = null; + } + } + + public void setName(String name) { + this.name = name.toUpperCase(); + } + + public void setData(String data) { + this.data = data; + } + + public String getName() { + return this.name; + } + + public String getData() { + return this.data; + } + + public String toString() { + if (this.data == null || this.data.length() == 0) { + return this.name; + } else { + return this.name + " " + this.data; + } + } + + public List splitData() { + return Arrays.asList(this.data.split(" ")); + } +} From 48a5958414ac703dba32c8b8d02ba7e1a2201c04 Mon Sep 17 00:00:00 2001 From: ole Date: Sat, 30 Nov 2024 13:48:50 +0100 Subject: [PATCH 06/25] add Thread safety for Player --- src/Board.java | 6 +++--- src/Player.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Board.java b/src/Board.java index 5cec0cd..99b1723 100644 --- a/src/Board.java +++ b/src/Board.java @@ -13,7 +13,7 @@ public class Board { this.createShip(size - 13); } - public HitResponse hit (Point point){ + public synchronized HitResponse hit (Point point){ HitResponse response = new HitResponse(HitResponseType.MISS,point); for (int i = 0; i < this.ships.size(); i++) { HitResponseType type = this.ships.get(i).shootOnShip(point); @@ -50,7 +50,7 @@ public class Board { return ships; } - public boolean addHits(HitResponse hitResponse) { + public synchronized boolean addHits(HitResponse hitResponse) { if (this.getHitResponsOnPoint(hitResponse.getPoint()) == null){ this.hits.add(hitResponse); return true; @@ -58,7 +58,7 @@ public class Board { return false; } - public HitResponse getHitResponsOnPoint(Point point) { + public synchronized HitResponse getHitResponsOnPoint(Point point) { for (int i = 0; i < this.hits.size(); i++){ if (this.hits.get(i).getPoint().equals(point)){ return this.hits.get(i); diff --git a/src/Player.java b/src/Player.java index 192b3f4..5eff33b 100644 --- a/src/Player.java +++ b/src/Player.java @@ -13,7 +13,7 @@ public abstract class Player { this.board = new Board(size); } - public void receiveShoot(Point point) { + public synchronized void receiveShoot(Point point) { HitResponse hitResponse = board.getHitResponsOnPoint(point); if (!(hitResponse == null)){ enemy.receiveHit(hitResponse); @@ -22,7 +22,7 @@ public abstract class Player { } } - public void receiveHit(HitResponse hitResponse) { + public synchronized void receiveHit(HitResponse hitResponse) { enemy.board.addHits(hitResponse); } From 7303f49d0d84a3ad31eda65f5b6be7da7537332d Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 14:13:01 +0100 Subject: [PATCH 07/25] avoid nulls --- src/SocketPackage.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/SocketPackage.java b/src/SocketPackage.java index 8f7e6ca..0dabd58 100644 --- a/src/SocketPackage.java +++ b/src/SocketPackage.java @@ -2,8 +2,8 @@ import java.util.Arrays; import java.util.List; public class SocketPackage { - private String name; - private String data; + private String name = ""; + private String data = ""; public SocketPackage(String name, String data) { this.setName(name); @@ -19,17 +19,19 @@ public class SocketPackage { String[] components = message.split(" "); this.setName(components[0]); if (components.length > 1) { - this.data = message.substring(components[0].length() + 1); + this.setData(message.substring(components[0].length() + 1)); } else { - this.data = null; + this.setData(""); } } public void setName(String name) { + if (name == null) name = ""; this.name = name.toUpperCase(); } public void setData(String data) { + if (data == null) data = ""; this.data = data; } From ff9ffbd628434320700f99884808aa542bc0cc17 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 14:13:15 +0100 Subject: [PATCH 08/25] sleep first in loop to avoid skipping sleep with continue --- src/AsyncSocket.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/AsyncSocket.java b/src/AsyncSocket.java index e91019d..7f1c535 100644 --- a/src/AsyncSocket.java +++ b/src/AsyncSocket.java @@ -24,6 +24,11 @@ public class AsyncSocket { this.checkerThread = new Thread(() -> { while (!this.shouldStop) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } try { if (!this.in.ready()) continue; if (this.handler == null) continue; @@ -31,16 +36,11 @@ public class AsyncSocket { String message = this.in.readLine(); if (message.length() <= 0) continue; + // TODO: remove \r\n this.handler.receive(message); } catch (IOException e) { e.printStackTrace(); } - - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } } }); this.checkerThread.start(); From 8bc64bd9ba4a7150be26434ab2f1d760fe036bd6 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 14:14:29 +0100 Subject: [PATCH 09/25] move joined logic out of if statement --- src/GameController.java | 52 ++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/GameController.java b/src/GameController.java index 5b3aa88..dfa6803 100644 --- a/src/GameController.java +++ b/src/GameController.java @@ -1,42 +1,46 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; -import java.util.Arrays; +import java.net.Socket; import java.util.HashMap; +import java.util.Map; public class GameController { - // TODO: fix syntax i guess - public HashMap> supportedVersions = [{ "1.1.0" : OnlinePlayer_1_1_0.class }]; + public HashMap> supportedVersions = new HashMap<>(Map.of( + "1.1.0", OnlinePlayer_1_1_0.class + )); - public void startOnlineGame(Class localPlayerClass, InetSocketAddress address) { + public void startOnlineGame(Class localPlayerClass, InetSocketAddress address) throws IOException { + AsyncSocket clientSocket; if (address.getHostName() == null) { // SERVER MODE - try { - ServerSocket serverSocket = new ServerSocket(address.getPort()); + ServerSocket serverSocket = new ServerSocket(address.getPort()); - System.out.println("Waiting for client connection..."); + System.out.println("Waiting for client connection..."); - AsyncSocket clientSocket = new AsyncSocket(serverSocket.accept(), null); - clientSocket.send("VERSION", "Gruppe03 1.1.0"); // TODO: adjust versioning list - clientSocket.setHandler((message) -> { + clientSocket = new AsyncSocket(serverSocket.accept(), null); - new OnlinePlayer_1_1_0(0, clientSocket); - - try { - serverSocket.close(); - } catch (IOException e) { - e.printStackTrace(); - } - }); - - } catch (IOException e) { - e.printStackTrace(); - return; - } + serverSocket.close(); } else { - // CLIENT MODE + Socket socket = new Socket(); + socket.connect(address); + + clientSocket = new AsyncSocket(socket, null); } + + clientSocket.send("VERSION", "Gruppe03 " + String.join(" ", supportedVersions.keySet())); + clientSocket.setHandler((message) -> { + + SocketPackage socketPackage = new SocketPackage(message); + if (socketPackage.getName().equals("VERSION")) { + // TODO: check version matches - instantiate online player + } else { + // TODO: received invalid package / package out of order + } + }); + // TODO: instantiate local player, set server / client roles + } public void startLocalGame(Class localPlayerClass, Class enemyClass, int size) { From c2ca83c71872328d3d207f3d961f91659ea57f14 Mon Sep 17 00:00:00 2001 From: ole Date: Sat, 30 Nov 2024 17:04:29 +0100 Subject: [PATCH 10/25] chore: remove all unjust imports --- src/AiPlayer.java | 1 - src/Board.java | 2 +- src/HitResponse.java | 2 +- src/OnlinePlayer_1_1_0.java | 2 ++ src/Player.java | 2 -- src/Ship.java | 2 -- src/SoundHandler.java | 1 - src/SpecificAiPlayerMedium.java | 1 - src/startMultiplayerGame.java | 1 - 9 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/AiPlayer.java b/src/AiPlayer.java index ca8c82d..f3f3870 100644 --- a/src/AiPlayer.java +++ b/src/AiPlayer.java @@ -1,5 +1,4 @@ import java.util.Random; -import java.awt.Point; public abstract class AiPlayer extends Player { diff --git a/src/Board.java b/src/Board.java index 16a1277..eaf8d41 100644 --- a/src/Board.java +++ b/src/Board.java @@ -1,4 +1,4 @@ -import java.awt.*; + import java.util.List; public class Board { diff --git a/src/HitResponse.java b/src/HitResponse.java index bc9fca0..8f1d8ad 100644 --- a/src/HitResponse.java +++ b/src/HitResponse.java @@ -1,4 +1,4 @@ -import java.awt.*; + public class HitResponse { private HitResponseType type; diff --git a/src/OnlinePlayer_1_1_0.java b/src/OnlinePlayer_1_1_0.java index 916b294..b199952 100644 --- a/src/OnlinePlayer_1_1_0.java +++ b/src/OnlinePlayer_1_1_0.java @@ -1,3 +1,5 @@ +import java.util.List; + public class OnlinePlayer_1_1_0 extends OnlinePlayer { public OnlinePlayer_1_1_0(int size, AsyncSocket socket) { super(size, socket); diff --git a/src/Player.java b/src/Player.java index 5eff33b..9e6985e 100644 --- a/src/Player.java +++ b/src/Player.java @@ -1,5 +1,3 @@ -import java.awt.*; -import java.util.List; public abstract class Player { protected boolean myTurn; diff --git a/src/Ship.java b/src/Ship.java index de6cbff..dd2006d 100644 --- a/src/Ship.java +++ b/src/Ship.java @@ -1,6 +1,4 @@ - -import java.awt.Point; import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/src/SoundHandler.java b/src/SoundHandler.java index d7b385b..f9d04a3 100644 --- a/src/SoundHandler.java +++ b/src/SoundHandler.java @@ -3,7 +3,6 @@ import javazoom.jl.player.Player; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.util.ArrayList; import java.util.HashMap; import java.util.Map; diff --git a/src/SpecificAiPlayerMedium.java b/src/SpecificAiPlayerMedium.java index c122f43..78cdae0 100644 --- a/src/SpecificAiPlayerMedium.java +++ b/src/SpecificAiPlayerMedium.java @@ -1,6 +1,5 @@ import java.util.ArrayList; import java.util.List; -import java.awt.Point; public class SpecificAiPlayerMedium extends AiPlayer{ diff --git a/src/startMultiplayerGame.java b/src/startMultiplayerGame.java index 4598994..472b62b 100644 --- a/src/startMultiplayerGame.java +++ b/src/startMultiplayerGame.java @@ -1,5 +1,4 @@ import javax.swing.*; -import java.awt.*; import java.awt.event.ActionEvent; public class startMultiplayerGame extends JPanel { From 058d069ff26de03a76dcedbea8bf2fbd1c54e6ca Mon Sep 17 00:00:00 2001 From: ole Date: Sat, 30 Nov 2024 17:06:25 +0100 Subject: [PATCH 11/25] change: all Points from java.awt.point too new Point.java --- src/Point.java | 45 +++++++++++++++++++++++++++++++++ src/Ship.java | 22 ++++++++-------- src/SpecificAiPlayerMedium.java | 8 +++--- src/startLocalGame.java | 1 - 4 files changed, 60 insertions(+), 16 deletions(-) create mode 100644 src/Point.java diff --git a/src/Point.java b/src/Point.java new file mode 100644 index 0000000..bf2b127 --- /dev/null +++ b/src/Point.java @@ -0,0 +1,45 @@ +public class Point { + private int x; + private int y; + + public Point (int x, int y) { + this.setX(x); + this.setY(y); + } + public Point (String str) { + if (Point.isValidSyntax(str)) { + this.setX(str.charAt(0)); + this.setY(Integer.parseInt(str.substring(1))); + } else { + throw new IllegalArgumentException("String ist keine gültige Koordinate"); + } + } + + @Override + public String toString() { + return (char) ('A' + this.x) + String.valueOf(this.y); + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public void setX(int x) { + this.x = x; + } + + public void setY(int y) { + this.y = y; + } + public void setX(char c) { + this.x = c - 'A'; + } + + public static boolean isValidSyntax(String str) { + return str.matches("^[A-Z]\\d+$"); + } +} diff --git a/src/Ship.java b/src/Ship.java index dd2006d..0c3c7f6 100644 --- a/src/Ship.java +++ b/src/Ship.java @@ -63,21 +63,21 @@ public class Ship { public boolean setPosition(Point pos, List shipsList, int boardSize) { // ueberpruefe boundaries - if (pos.x < 0 || pos.y < 0 || pos.x >= boardSize || pos.y >= boardSize) { + if (pos.getX() < 0 || pos.getY() < 0 || pos.getX() >= boardSize || pos.getY() >= boardSize) { return false; } // bestimme die Endposition anhand der Ausrichtung - int endX = pos.x; - int endY = pos.y; + int endX = pos.getX(); + int endY = pos.getY(); if (this.horizontal) { // rechts links - endX = pos.x + this.size - 1; + endX = pos.getX() + this.size - 1; if (endX >= boardSize) { return false; } } else { // oben unten - endY = pos.y + this.size - 1; + endY = pos.getY() + this.size - 1; if (endY >= boardSize) { return false; } @@ -86,8 +86,8 @@ public class Ship { // Liste an Punkten die das Schiff einnehmen wuerde List shipPoints = new ArrayList<>(); for (int i = 0; i < this.size; i++) { - int x = this.horizontal ? pos.x + i : pos.x; //falls horizontal dann pos.x + i ansonsten pos.x - int y = this.horizontal ? pos.y : pos.y + i; + int x = this.horizontal ? pos.getX() + i : pos.getX(); //falls horizontal dann pos.x + i ansonsten pos.x + int y = this.horizontal ? pos.getY() : pos.getY() + i; shipPoints.add(new Point(x, y)); } @@ -123,8 +123,8 @@ public class Ship { return points; } for (int i = 0; i < this.size; i++) { - int x = this.horizontal ? this.position.x + i : this.position.x; - int y = this.horizontal ? this.position.y : this.position.y + i; + int x = this.horizontal ? this.position.getX() + i : this.position.getX(); + int y = this.horizontal ? this.position.getY() : this.position.getY() + i; points.add(new Point(x, y)); } return points; @@ -135,8 +135,8 @@ public class Ship { } public boolean isShipOnPos(Point pos){ - if ((this.horizontal && pos.y == this.position.y && pos.x >= this.position.x && pos.x < this.position.x + size) || - (!(this.horizontal) && pos.x == this.position.x && pos.y >= this.position.y && pos.y < this.position.y + size)) { + if ((this.horizontal && pos.getY() == this.position.getY() && pos.getX() >= this.position.getX() && pos.getX() < this.position.getX() + size) || + (!(this.horizontal) && pos.getX() == this.position.getX() && pos.getY() >= this.position.getY() && pos.getY() < this.position.getY() + size)) { return true; } return false; diff --git a/src/SpecificAiPlayerMedium.java b/src/SpecificAiPlayerMedium.java index 78cdae0..1676eb4 100644 --- a/src/SpecificAiPlayerMedium.java +++ b/src/SpecificAiPlayerMedium.java @@ -42,8 +42,8 @@ public class SpecificAiPlayerMedium extends AiPlayer{ } private void addAdjacentPoints(Point point) { - int x = point.x; - int y = point.y; + int x = point.getX(); + int y = point.getY(); // Possible adjacent positions (up, down, left, right) Point[] adjacentPoints = { @@ -66,7 +66,7 @@ public class SpecificAiPlayerMedium extends AiPlayer{ } private boolean isValidPoint(Point point) { - return point.x >= 0 && point.x < board.getSize() && - point.y >= 0 && point.y < board.getSize(); + return point.getX() >= 0 && point.getX() < board.getSize() && + point.getY() >= 0 && point.getY() < board.getSize(); } } \ No newline at end of file diff --git a/src/startLocalGame.java b/src/startLocalGame.java index 8dcc513..ff3ca3c 100644 --- a/src/startLocalGame.java +++ b/src/startLocalGame.java @@ -1,5 +1,4 @@ import javax.swing.*; -import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; From 22950cd1558f41e641f3d8368094ae245a5c755c Mon Sep 17 00:00:00 2001 From: ole Date: Sat, 30 Nov 2024 17:07:11 +0100 Subject: [PATCH 12/25] add: Thread protection Player.java --- src/Player.java | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/Player.java b/src/Player.java index 9e6985e..525bbfc 100644 --- a/src/Player.java +++ b/src/Player.java @@ -11,18 +11,9 @@ public abstract class Player { this.board = new Board(size); } - public synchronized void receiveShoot(Point point) { - HitResponse hitResponse = board.getHitResponsOnPoint(point); - if (!(hitResponse == null)){ - enemy.receiveHit(hitResponse); - } else { - enemy.receiveHit(this.board.hit(point)); - } - } + public abstract void receiveShoot(Point point); - public synchronized void receiveHit(HitResponse hitResponse) { - enemy.board.addHits(hitResponse); - } + public abstract void receiveHit(HitResponse hitResponse); public void click(Point point) { From 6a4e157605299fa42b25b3fd5cffd1c6a5d4132b Mon Sep 17 00:00:00 2001 From: ole Date: Sat, 30 Nov 2024 17:09:44 +0100 Subject: [PATCH 13/25] add: Network implementation --- src/HitResponse.java | 14 ++++++++++++++ src/LocalPlayer.java | 16 +++++++++++++++- src/OnlinePlayer.java | 9 ++++++++- src/OnlinePlayer_1_1_0.java | 38 +++++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/HitResponse.java b/src/HitResponse.java index 8f1d8ad..89f713a 100644 --- a/src/HitResponse.java +++ b/src/HitResponse.java @@ -8,6 +8,15 @@ public class HitResponse { this.type = type; this.point = point; } + + public HitResponse (int typeIndex, Point point) { + if (typeIndex >= 0 && typeIndex < HitResponseType.values().length) { + this.type = HitResponseType.values()[typeIndex]; + this.point = point; + } else { + throw new IllegalArgumentException(); + } + } public HitResponseType getHitResponse() { return this.type; @@ -20,4 +29,9 @@ public class HitResponse { public void setType(HitResponseType type) { this.type = type; } + + @Override + public String toString() { + return this.getPoint().toString() + " " + this.type.ordinal(); + } } diff --git a/src/LocalPlayer.java b/src/LocalPlayer.java index cfa7cab..8e13a7a 100644 --- a/src/LocalPlayer.java +++ b/src/LocalPlayer.java @@ -3,6 +3,20 @@ public class LocalPlayer extends Player { LocalPlayer(int size) { super(size); } - + + @Override + public synchronized void receiveShoot(Point point) { + HitResponse hitResponse = board.getHitResponsOnPoint(point); + if (!(hitResponse == null)){ + enemy.receiveHit(hitResponse); + } else { + enemy.receiveHit(this.board.hit(point)); + } + } + + @Override + public synchronized void receiveHit(HitResponse hitResponse) { + enemy.board.addHits(hitResponse); + } } \ No newline at end of file diff --git a/src/OnlinePlayer.java b/src/OnlinePlayer.java index f3aaaf8..df62263 100644 --- a/src/OnlinePlayer.java +++ b/src/OnlinePlayer.java @@ -1,12 +1,19 @@ public abstract class OnlinePlayer extends Player implements AsyncSocketListener{ - private AsyncSocket socket; + protected AsyncSocket socket; public OnlinePlayer(int size, AsyncSocket socket) { super(size); this.socket = socket; + socket.setHandler(this); //TODO Auto-generated constructor stub } public abstract void receive(String message); + @Override + public abstract void receiveShoot(Point point); + + @Override + public abstract void receiveHit(HitResponse hitResponse); + } diff --git a/src/OnlinePlayer_1_1_0.java b/src/OnlinePlayer_1_1_0.java index b199952..d14e197 100644 --- a/src/OnlinePlayer_1_1_0.java +++ b/src/OnlinePlayer_1_1_0.java @@ -5,11 +5,49 @@ public class OnlinePlayer_1_1_0 extends OnlinePlayer { super(size, socket); } + + @Override public void receive(String message) { SocketPackage p = new SocketPackage(message); // TODO: parse package + switch (p.getName()) { + case "SHOOT": + if (Point.isValidSyntax(p.getData())){ + Point point = new Point(p.getData()); + this.enemy.receiveShoot(point); + } + break; + + case "HIT": + List data = p.splitData(); + if (data.size()==2){ + Point point = new Point(data.get(0)); + int typeIndex = Integer.parseInt(data.get(1)); + if (Point.isValidSyntax(data.get(0)) && typeIndex >= 0 && typeIndex < HitResponseType.values().length){ + this.enemy.receiveHit(new HitResponse(typeIndex, point)); + } + } + break; + + case "CHAT": + //TODO CHAT + break; + + default: + //nichts passier da Paket ungültig + break; + } } + @Override + public synchronized void receiveShoot(Point point){ + super.socket.send(new SocketPackage("SHOOT",point.toString())); + } + + @Override + public synchronized void receiveHit(HitResponse hitResponse) { + super.socket.send(new SocketPackage("HIT", hitResponse.toString())); + } } \ No newline at end of file From 3eeb4d25bd56dd896bad4c784c2f91de27c62f7e Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 17:58:24 +0100 Subject: [PATCH 14/25] start online game --- src/GameController.java | 131 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 122 insertions(+), 9 deletions(-) diff --git a/src/GameController.java b/src/GameController.java index dfa6803..381dfbe 100644 --- a/src/GameController.java +++ b/src/GameController.java @@ -2,10 +2,16 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; +import java.net.SocketTimeoutException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; public class GameController { + + // Connection timeout for client sockets in milliseconds + public static final int CONNECTION_TIMEOUT = 10 * 1000; public HashMap> supportedVersions = new HashMap<>(Map.of( "1.1.0", OnlinePlayer_1_1_0.class @@ -13,8 +19,12 @@ public class GameController { public void startOnlineGame(Class localPlayerClass, InetSocketAddress address) throws IOException { AsyncSocket clientSocket; - if (address.getHostName() == null) { + + boolean localPlayerIsServer = address.getHostName() == null; + + if (localPlayerIsServer) { // SERVER MODE + ServerSocket serverSocket = new ServerSocket(address.getPort()); System.out.println("Waiting for client connection..."); @@ -23,10 +33,21 @@ public class GameController { serverSocket.close(); } else { + // CLIENT MODE + Socket socket = new Socket(); - socket.connect(address); - clientSocket = new AsyncSocket(socket, null); + try { + socket.connect(address, CONNECTION_TIMEOUT); + + clientSocket = new AsyncSocket(socket, null); + } catch (SocketTimeoutException e) { + e.printStackTrace(); + throw new RuntimeException("Connection timed out"); + } finally { + socket.close(); + } + } clientSocket.send("VERSION", "Gruppe03 " + String.join(" ", supportedVersions.keySet())); @@ -34,15 +55,101 @@ public class GameController { SocketPackage socketPackage = new SocketPackage(message); if (socketPackage.getName().equals("VERSION")) { - // TODO: check version matches - instantiate online player + + List opponentSupportedVersions = socketPackage.splitData(); + + String usedVersion = findMostRecentVersion(new ArrayList(supportedVersions.keySet()), opponentSupportedVersions); + + if (usedVersion == null) { + throw new RuntimeException("No common versions found"); + } + + // instantiate players + Class onlinePlayerClass = supportedVersions.get(usedVersion); + + LocalPlayer localPlayer; + OnlinePlayer onlinePlayer; + try { + localPlayer = localPlayerClass.getDeclaredConstructor().newInstance(); + onlinePlayer = onlinePlayerClass.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Unable to instantiate players"); + } + + localPlayer.isServer = localPlayerIsServer; + onlinePlayer.isServer = !localPlayerIsServer; + + startGameWithInstancedPlayers(localPlayer, onlinePlayer); + } else { - // TODO: received invalid package / package out of order + throw new RuntimeException("Unexpected Package received before game initialisation"); } }); - // TODO: instantiate local player, set server / client roles } + /** + * finds the largest common version in two lists of version strings + * @return null if no common versions are found + */ + public String findMostRecentVersion(List versions1, List versions2) { + if (versions1 == null || versions2 == null) return null; + String largestCommonVersion = null; + for (String v1 : versions1) { + if (!checkVersionString(v1)) continue; + + for (String v2 : versions2) { + if (!checkVersionString(v2)) continue; + + // strings within the lists must be equal + // if no largest common version has been found or currently checked version is larger than + // previous largest common version, new largest version has been found + if (compareVersions(v1, v2) == 0 && (largestCommonVersion == null || compareVersions(v1, largestCommonVersion) >= 1)) { + largestCommonVersion = v1; + continue; + } + } + } + return largestCommonVersion; + } + + /** + * compares two version strings + * @return + * 0 if versions are equal + * 1 if version1 is more recent than version2 + * -1 otherwise + */ + public int compareVersions(String version1, String version2) { + if (!checkVersionString(version1) || !checkVersionString(version2)) { + throw new IllegalArgumentException("Version is not valid version string"); + } + + String[] version1Split = version1.split("\\."); + String[] version2Split = version2.split("\\."); + + for (int i = 0; i < version1Split.length; i++) { + int v1 = Integer.parseInt(version1Split[i]); + int v2 = Integer.parseInt(version2Split[i]); + + if (v1 == v2) continue; + if (v1 > v2) { + return 1; + } else { + return -1; + } + } + return 0; + } + + /** + * checks if a provided string matches the format of a version number + */ + public boolean checkVersionString(String versionString) { + return versionString != null && versionString.matches("\\d+\\.\\d+\\.\\d+"); + } + public void startLocalGame(Class localPlayerClass, Class enemyClass, int size) { LocalPlayer localPlayer; @@ -52,10 +159,16 @@ public class GameController { aiPlayer = enemyClass.getDeclaredConstructor().newInstance(); } catch (Exception e) { e.printStackTrace(); - return; + throw new RuntimeException("Unable to instantiate players"); } - localPlayer.setEnemy(aiPlayer); - aiPlayer.setEnemy(localPlayer); + startGameWithInstancedPlayers(localPlayer, aiPlayer); + } + + private void startGameWithInstancedPlayers(LocalPlayer p1, Player p2) { + p1.setEnemy(p2); + p2.setEnemy(p1); + + // TODO: frontend configuration } } \ No newline at end of file From 2c6f9adf54fc137672fb2f79e62ce68826b3b834 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 18:15:07 +0100 Subject: [PATCH 15/25] move board size out of player constructor --- src/GameController.java | 10 +++++++--- src/OnlinePlayer.java | 1 - src/Player.java | 5 +++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/GameController.java b/src/GameController.java index 381dfbe..ea735ef 100644 --- a/src/GameController.java +++ b/src/GameController.java @@ -17,7 +17,7 @@ public class GameController { "1.1.0", OnlinePlayer_1_1_0.class )); - public void startOnlineGame(Class localPlayerClass, InetSocketAddress address) throws IOException { + public void startOnlineGame(Class localPlayerClass, InetSocketAddress address, int size) throws IOException { AsyncSocket clientSocket; boolean localPlayerIsServer = address.getHostName() == null; @@ -34,7 +34,7 @@ public class GameController { serverSocket.close(); } else { // CLIENT MODE - + Socket socket = new Socket(); try { @@ -71,7 +71,7 @@ public class GameController { OnlinePlayer onlinePlayer; try { localPlayer = localPlayerClass.getDeclaredConstructor().newInstance(); - onlinePlayer = onlinePlayerClass.getDeclaredConstructor().newInstance(); + onlinePlayer = onlinePlayerClass.getDeclaredConstructor().newInstance((Integer)size, clientSocket); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("Unable to instantiate players"); @@ -161,6 +161,10 @@ public class GameController { e.printStackTrace(); throw new RuntimeException("Unable to instantiate players"); } + + localPlayer.createBoard(size); + aiPlayer.createBoard(size); + startGameWithInstancedPlayers(localPlayer, aiPlayer); } diff --git a/src/OnlinePlayer.java b/src/OnlinePlayer.java index f3aaaf8..ad757df 100644 --- a/src/OnlinePlayer.java +++ b/src/OnlinePlayer.java @@ -2,7 +2,6 @@ public abstract class OnlinePlayer extends Player implements AsyncSocketListener private AsyncSocket socket; public OnlinePlayer(int size, AsyncSocket socket) { - super(size); this.socket = socket; //TODO Auto-generated constructor stub } diff --git a/src/Player.java b/src/Player.java index 192b3f4..6fbd55c 100644 --- a/src/Player.java +++ b/src/Player.java @@ -1,5 +1,4 @@ import java.awt.*; -import java.util.List; public abstract class Player { protected boolean myTurn; @@ -9,7 +8,9 @@ public abstract class Player { protected String name; protected Board board; - public Player(int size) { + public Player() {} + + public void createBoard(int size) { this.board = new Board(size); } From cecc44abf4357006d167e666ab136ca0954655bb Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 18:28:05 +0100 Subject: [PATCH 16/25] fix: remove board size from constructor --- src/AiPlayer.java | 6 ++---- src/HumanPlayer.java | 3 --- src/LocalPlayer.java | 4 ---- src/SpecificAiPlayerEasy.java | 4 ---- src/SpecificAiPlayerHard.java | 4 ---- src/SpecificAiPlayerMedium.java | 4 ---- 6 files changed, 2 insertions(+), 23 deletions(-) diff --git a/src/AiPlayer.java b/src/AiPlayer.java index f3f3870..2d3ba33 100644 --- a/src/AiPlayer.java +++ b/src/AiPlayer.java @@ -1,10 +1,8 @@ import java.util.Random; -public abstract class AiPlayer extends Player { +public abstract class AiPlayer extends LocalPlayer { - public AiPlayer(int size) { - super(size); - } + public AiPlayer() {} public Point RandomPoint() { Random random = new Random(); // Pseudo Random für zufallszahlen int posx = random.nextInt(super.board.getSize()); // Generiert 0 - 13 diff --git a/src/HumanPlayer.java b/src/HumanPlayer.java index 6723e71..ae0e298 100644 --- a/src/HumanPlayer.java +++ b/src/HumanPlayer.java @@ -1,7 +1,4 @@ public class HumanPlayer extends LocalPlayer { - public HumanPlayer(int size) { - super(size); - } } diff --git a/src/LocalPlayer.java b/src/LocalPlayer.java index 8e13a7a..4c581f6 100644 --- a/src/LocalPlayer.java +++ b/src/LocalPlayer.java @@ -1,9 +1,5 @@ public class LocalPlayer extends Player { - LocalPlayer(int size) { - super(size); - } - @Override public synchronized void receiveShoot(Point point) { HitResponse hitResponse = board.getHitResponsOnPoint(point); diff --git a/src/SpecificAiPlayerEasy.java b/src/SpecificAiPlayerEasy.java index c3ac64f..2e4a62c 100644 --- a/src/SpecificAiPlayerEasy.java +++ b/src/SpecificAiPlayerEasy.java @@ -1,7 +1,3 @@ public class SpecificAiPlayerEasy extends AiPlayer{ - - public SpecificAiPlayerEasy(int size) { - super(size); - } } diff --git a/src/SpecificAiPlayerHard.java b/src/SpecificAiPlayerHard.java index a28fa6c..a8d5dd4 100644 --- a/src/SpecificAiPlayerHard.java +++ b/src/SpecificAiPlayerHard.java @@ -1,7 +1,3 @@ public class SpecificAiPlayerHard extends AiPlayer{ - - public SpecificAiPlayerHard(int size) { - super(size); - } } diff --git a/src/SpecificAiPlayerMedium.java b/src/SpecificAiPlayerMedium.java index 1676eb4..81561b2 100644 --- a/src/SpecificAiPlayerMedium.java +++ b/src/SpecificAiPlayerMedium.java @@ -5,10 +5,6 @@ public class SpecificAiPlayerMedium extends AiPlayer{ private List hitsQueue = new ArrayList<>(); - public SpecificAiPlayerMedium(int size) { - super(size); - } - @Override public void AiShoot() { Point nextShot = ComputeNextShot(); From ab1aae7798d260eb0668ed88ad169102545a8f91 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 18:39:41 +0100 Subject: [PATCH 17/25] add method to convert semester to board size --- src/GameController.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/GameController.java b/src/GameController.java index ea735ef..44b0444 100644 --- a/src/GameController.java +++ b/src/GameController.java @@ -12,6 +12,10 @@ public class GameController { // Connection timeout for client sockets in milliseconds public static final int CONNECTION_TIMEOUT = 10 * 1000; + + public static int semesterToBoardSize(int semester) { + return semester + 13; + } public HashMap> supportedVersions = new HashMap<>(Map.of( "1.1.0", OnlinePlayer_1_1_0.class From bdde2066f35554618c40fd777839316669a8a285 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 18:39:58 +0100 Subject: [PATCH 18/25] add getter and setter for name --- src/Player.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Player.java b/src/Player.java index 8d4eacd..5e5d83a 100644 --- a/src/Player.java +++ b/src/Player.java @@ -28,4 +28,11 @@ public abstract class Player { public void setEnemy(Player enemy) { this.enemy = enemy; } + + public void setName(String name) { + this.name = name; + } + public String getName() { + return this.name; + } } From 1fb284eb1a6b336bfad0f4d92d360708732da0a3 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 18:40:04 +0100 Subject: [PATCH 19/25] add IAM Package --- src/OnlinePlayer.java | 2 ++ src/OnlinePlayer_1_1_0.java | 23 +++++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/OnlinePlayer.java b/src/OnlinePlayer.java index 015e9be..90dc5cd 100644 --- a/src/OnlinePlayer.java +++ b/src/OnlinePlayer.java @@ -1,8 +1,10 @@ public abstract class OnlinePlayer extends Player implements AsyncSocketListener{ protected AsyncSocket socket; + protected int wantedBoardSize; public OnlinePlayer(int size, AsyncSocket socket) { this.socket = socket; + this.wantedBoardSize = size; socket.setHandler(this); //TODO Auto-generated constructor stub } diff --git a/src/OnlinePlayer_1_1_0.java b/src/OnlinePlayer_1_1_0.java index d14e197..6146796 100644 --- a/src/OnlinePlayer_1_1_0.java +++ b/src/OnlinePlayer_1_1_0.java @@ -11,8 +11,28 @@ public class OnlinePlayer_1_1_0 extends OnlinePlayer { public void receive(String message) { SocketPackage p = new SocketPackage(message); - // TODO: parse package + List data = p.splitData(); switch (p.getName()) { + case "IAM": + if (data.size() < 2) break; + if (this.board != null) break; + + int semester = Integer.parseInt(data.get(0)); + String username = p.getData().substring(data.get(0).length() + 1); + + int usedBoardSize = Math.min(GameController.semesterToBoardSize(semester), this.wantedBoardSize); + + this.setName(username); + this.createBoard(usedBoardSize); + this.enemy.createBoard(usedBoardSize); + + break; + + // TODO: IAMU + + // TODO: COIN + + case "SHOOT": if (Point.isValidSyntax(p.getData())){ Point point = new Point(p.getData()); @@ -21,7 +41,6 @@ public class OnlinePlayer_1_1_0 extends OnlinePlayer { break; case "HIT": - List data = p.splitData(); if (data.size()==2){ Point point = new Point(data.get(0)); int typeIndex = Integer.parseInt(data.get(1)); From addf542300811224c0e7689e0b1dbe4c8d3f0ce5 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Sat, 30 Nov 2024 18:43:04 +0100 Subject: [PATCH 20/25] strip string before passing to handler --- src/AsyncSocket.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AsyncSocket.java b/src/AsyncSocket.java index 7f1c535..0201e4e 100644 --- a/src/AsyncSocket.java +++ b/src/AsyncSocket.java @@ -36,7 +36,7 @@ public class AsyncSocket { String message = this.in.readLine(); if (message.length() <= 0) continue; - // TODO: remove \r\n + message = message.strip(); this.handler.receive(message); } catch (IOException e) { e.printStackTrace(); From 3b9b1eaebbcc46e186c11e58e79e612c876fe1db Mon Sep 17 00:00:00 2001 From: Kaver Date: Mon, 2 Dec 2024 19:04:34 +0100 Subject: [PATCH 21/25] Klasse fuer verbinden Panel erstellt(extrem grobes Beispiel) und Panel Weiterleitung eingefuegt Anpassungen an ActionListenern in MainMenuView Backbutton mit Funktion eingefuegt fuer joinGame Panel --- src/JoinGame.java | 9 ++++++++- src/MainFrame.java | 10 ++++++---- src/MainMenuView.java | 27 ++++++++++++++++++++++++--- src/Verbinden.java | 23 +++++++++++++++++++++++ 4 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 src/Verbinden.java diff --git a/src/JoinGame.java b/src/JoinGame.java index fdacd3a..b3ac5a0 100644 --- a/src/JoinGame.java +++ b/src/JoinGame.java @@ -2,6 +2,8 @@ import java.awt.*; import javax.swing.*; public class JoinGame extends JPanel { + ImageIcon backButtonIcon = new ImageIcon("graphics/backButton.png"); + JLabel spielBeitretenLabel; JLabel ipLabel = new JLabel("IP-Adresse"); JLabel portLabel = new JLabel("Port"); @@ -10,6 +12,7 @@ public class JoinGame extends JPanel { JTextField portTextField = new JTextField(20); JButton losButton = new JButton("Los!"); + JButton backButton = new JButton(backButtonIcon); Font robotoFont = new Font("Roboto", Font.BOLD, 45); @@ -27,6 +30,7 @@ public class JoinGame extends JPanel { spielBeitretenLabel.setBounds(20,20,700, 100); losButton.setBounds(320, 225, 100, 50); + backButton.setBounds(1380, 20, 80, 80); ipLabel.setBounds(50, 125, 200, 30); portLabel.setBounds(50, 200, 200, 30); @@ -43,6 +47,9 @@ public class JoinGame extends JPanel { add(losButton); add(ipTextField); add(portTextField); - } + add(backButton); + backButton.addActionListener(e -> frame.showPanel("MultiplayerGame")); + losButton.addActionListener(e -> frame.showPanel("Verbinden")); + } } diff --git a/src/MainFrame.java b/src/MainFrame.java index 3c7ee8c..2e53062 100644 --- a/src/MainFrame.java +++ b/src/MainFrame.java @@ -37,6 +37,7 @@ public class MainFrame extends JFrame { startLocalGame localGame = new startLocalGame(this); startMultiplayerGame multiplayerGame = new startMultiplayerGame(this); coinToss coinToss = new coinToss(this); + Verbinden verbinden = new Verbinden(this); //JoinGame joinGame = new JoinGame(this,localMult); //GameBoard gameBoard = new GameBoard(this, localMult); @@ -44,6 +45,7 @@ public class MainFrame extends JFrame { mainPanel.add(localGame, "LocalGame"); mainPanel.add(multiplayerGame, "MultiplayerGame"); mainPanel.add(coinToss, "coinToss"); + mainPanel.add(verbinden, "Verbinden"); //mainPanel.add(joinGame, "JoinGame"); //mainPanel.add(gameBoard, "GameBoard"); @@ -64,8 +66,8 @@ public class MainFrame extends JFrame { //if (!isPanelPresent(panelName)) { //TODO potentiell raus JoinGame joinGame = new JoinGame(this, localMult); - mainPanel.add(joinGame, panelName); // Dynamically add the panel - mainPanel.revalidate(); // Refresh the layout + mainPanel.add(joinGame, panelName); + mainPanel.revalidate(); // Refresh mainPanel.repaint(); //} @@ -77,8 +79,8 @@ public class MainFrame extends JFrame { //if (!isPanelPresent(panelName)) { //TODO potentiell raus GameBoard gameBoard = new GameBoard(this, semesterCounter); - mainPanel.add(gameBoard, panelName); // Dynamically add the panel - mainPanel.revalidate(); // Refresh the layout + mainPanel.add(gameBoard, panelName); + mainPanel.revalidate(); // Refresh mainPanel.repaint(); //} diff --git a/src/MainMenuView.java b/src/MainMenuView.java index 958d610..af862f3 100644 --- a/src/MainMenuView.java +++ b/src/MainMenuView.java @@ -1,5 +1,6 @@ import java.awt.*; import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import javax.swing.JFrame; import javax.swing.*; @@ -36,9 +37,29 @@ public class MainMenuView extends JPanel { add(soundButton); // Event Listener für Buttons - lokalButton.addActionListener(e -> frame.showPanel("LocalGame")); - multiButton.addActionListener(e -> frame.showPanel("MultiplayerGame")); - soundButton.addActionListener(e -> toggleMute()); + lokalButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + System.out.println("Lokales Spiel ausgewählt."); + frame.showPanel("LocalGame"); // Panel wechseln + } + }); + + multiButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + System.out.println("Multiplayer-Spiel ausgewählt."); + frame.showPanel("MultiplayerGame"); // Panel wechseln + } + }); + + soundButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + System.out.println("Soundbutton geklickt."); + toggleMute(); + } + }); } private void toggleMute() { diff --git a/src/Verbinden.java b/src/Verbinden.java new file mode 100644 index 0000000..ca4feb7 --- /dev/null +++ b/src/Verbinden.java @@ -0,0 +1,23 @@ +import javax.swing.*; +import java.awt.*; + +public class Verbinden extends JPanel{ + + ImageIcon backButtonIcon = new ImageIcon("graphics/backButton.png"); + + JLabel verbindenLabel = new JLabel("Verbinde . . .",SwingConstants.CENTER); + + Font robotoFont = new Font("Roboto", Font.BOLD, 45); + + public Verbinden(MainFrame frame) { + setLayout(null); + buildPanel(frame); + } + + private void buildPanel(MainFrame frame) { + setLayout(new BorderLayout()); + verbindenLabel.setFont(robotoFont.deriveFont(50f)); + add(verbindenLabel, BorderLayout.CENTER); + } + } + From 43545afb45ec75ccba8345571f646ce31ba4f8d0 Mon Sep 17 00:00:00 2001 From: Ole Wachtel Date: Tue, 3 Dec 2024 12:11:06 +0100 Subject: [PATCH 22/25] add coin flip and turn logic --- src/HitResponse.java | 4 ++++ src/LocalPlayer.java | 42 ++++++++++++++++++++++++++++++++++++- src/OnlinePlayer.java | 5 +++++ src/OnlinePlayer_1_1_0.java | 16 +++++++++++++- src/Player.java | 18 ++++++++++++---- 5 files changed, 79 insertions(+), 6 deletions(-) diff --git a/src/HitResponse.java b/src/HitResponse.java index 89f713a..2e5f0ca 100644 --- a/src/HitResponse.java +++ b/src/HitResponse.java @@ -34,4 +34,8 @@ public class HitResponse { public String toString() { return this.getPoint().toString() + " " + this.type.ordinal(); } + + public HitResponseType getType() { + return type; + } } diff --git a/src/LocalPlayer.java b/src/LocalPlayer.java index 4c581f6..5bc6dd9 100644 --- a/src/LocalPlayer.java +++ b/src/LocalPlayer.java @@ -1,18 +1,58 @@ +import java.util.Random; + public class LocalPlayer extends Player { + public LocalPlayer(){ + super(); + Random random = new Random(); + this.myCoin = random.nextBoolean(); + } + @Override public synchronized void receiveShoot(Point point) { HitResponse hitResponse = board.getHitResponsOnPoint(point); if (!(hitResponse == null)){ enemy.receiveHit(hitResponse); + } else { - enemy.receiveHit(this.board.hit(point)); + hitResponse = this.board.hit(point); + enemy.receiveHit(hitResponse); + } + + switch (hitResponse.getType()) { + case HIT, SUNK -> this.myTurn = false; + case MISS -> this.myTurn = true; + case VICTORY -> System.out.println("Game Over"); //TODO Was halt bei victory passiert ist hier wurder verloheren } } @Override public synchronized void receiveHit(HitResponse hitResponse) { enemy.board.addHits(hitResponse); + switch (hitResponse.getType()) { + case HIT, SUNK -> this.myTurn = true; + case MISS -> this.myTurn = false; + case VICTORY -> System.out.println("Win"); // TODO was halt beim victory passier ist hier wurde gewonnen + } + } + + @Override + public synchronized void receiveCoin(boolean coin) { + if (!this.haseReceivedCoin) { + boolean result = coin ^ this.myCoin; // XOR + this.myTurn = result == this.isServer; + this.haseReceivedCoin = true; + } + } + + public void sendCoin() { + enemy.receiveCoin(this.myCoin); + } + + @Override + public void shoot(Point point){ + this.myTurn = false; + enemy.receiveShoot(point); } } \ No newline at end of file diff --git a/src/OnlinePlayer.java b/src/OnlinePlayer.java index 90dc5cd..88ac476 100644 --- a/src/OnlinePlayer.java +++ b/src/OnlinePlayer.java @@ -2,6 +2,8 @@ public abstract class OnlinePlayer extends Player implements AsyncSocketListener protected AsyncSocket socket; protected int wantedBoardSize; + protected boolean hasReceivedCoinPackage; + public OnlinePlayer(int size, AsyncSocket socket) { this.socket = socket; this.wantedBoardSize = size; @@ -17,4 +19,7 @@ public abstract class OnlinePlayer extends Player implements AsyncSocketListener @Override public abstract void receiveHit(HitResponse hitResponse); + @Override + public abstract void receiveCoin(boolean coin); + } diff --git a/src/OnlinePlayer_1_1_0.java b/src/OnlinePlayer_1_1_0.java index 6146796..be1a678 100644 --- a/src/OnlinePlayer_1_1_0.java +++ b/src/OnlinePlayer_1_1_0.java @@ -30,7 +30,13 @@ public class OnlinePlayer_1_1_0 extends OnlinePlayer { // TODO: IAMU - // TODO: COIN + case "COIN": + if(!this.hasReceivedCoinPackage && (p.getData().equals("1") || p.getData().equals("0"))){ + this.myCoin = p.getData().equals("1"); + enemy.receiveCoin(this.myCoin); + this.hasReceivedCoinPackage = true; + } + break; case "SHOOT": @@ -69,4 +75,12 @@ public class OnlinePlayer_1_1_0 extends OnlinePlayer { public synchronized void receiveHit(HitResponse hitResponse) { super.socket.send(new SocketPackage("HIT", hitResponse.toString())); } + + @Override + public synchronized void receiveCoin(boolean coin) { + if (!this.haseReceivedCoin) { + super.socket.send(new SocketPackage("COIN", String.valueOf(coin ? 1 : 0))); + this.haseReceivedCoin = true; + } + } } \ No newline at end of file diff --git a/src/Player.java b/src/Player.java index 5e5d83a..faf9abb 100644 --- a/src/Player.java +++ b/src/Player.java @@ -1,3 +1,4 @@ +import java.util.Random; public abstract class Player { protected boolean myTurn; @@ -6,8 +7,16 @@ public abstract class Player { protected Player enemy; protected String name; protected Board board; + protected boolean myCoin; - public Player() {} + protected boolean sendCoin; + + protected boolean haseReceivedCoin; + + public Player() { + this.haseReceivedCoin = false; + this.sendCoin = false; + } public void createBoard(int size) { this.board = new Board(size); @@ -17,9 +26,7 @@ public abstract class Player { public abstract void receiveHit(HitResponse hitResponse); - public void click(Point point) { - - } + public abstract void shoot(Point point); public void beginTrun() { @@ -35,4 +42,7 @@ public abstract class Player { public String getName() { return this.name; } + + + public abstract void receiveCoin(boolean coin); } From 2160b5d41093abf9b14e6f03d5249aa3d94f023c Mon Sep 17 00:00:00 2001 From: ole Date: Tue, 3 Dec 2024 12:20:40 +0100 Subject: [PATCH 23/25] add shoot to OnlinePlayer_1_1_0.java --- src/OnlinePlayer_1_1_0.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/OnlinePlayer_1_1_0.java b/src/OnlinePlayer_1_1_0.java index be1a678..6c2a784 100644 --- a/src/OnlinePlayer_1_1_0.java +++ b/src/OnlinePlayer_1_1_0.java @@ -83,4 +83,9 @@ public class OnlinePlayer_1_1_0 extends OnlinePlayer { this.haseReceivedCoin = true; } } + + @Override + public synchronized void shoot(Point point) { + super.socket.send(new SocketPackage("SHOOT", point.toString())); + } } \ No newline at end of file From 772f2d45c635628159de834267cc456eb279b874 Mon Sep 17 00:00:00 2001 From: Joshua Date: Tue, 3 Dec 2024 12:23:46 +0100 Subject: [PATCH 24/25] Added Backbutton function to GameBoard --- src/GameBoard.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/GameBoard.java b/src/GameBoard.java index c4dda52..43c3974 100644 --- a/src/GameBoard.java +++ b/src/GameBoard.java @@ -109,5 +109,6 @@ public class GameBoard extends JPanel { updateTextFields(); } }); */ + backButton.addActionListener(e -> frame.showPanel("MainMenu")); } } From 175bb20345bc358583b58006f5fb4c9064989e1d Mon Sep 17 00:00:00 2001 From: ole Date: Tue, 3 Dec 2024 13:11:06 +0100 Subject: [PATCH 25/25] change idea settings --- .idea/libraries/jlayer_1_0_3.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.idea/libraries/jlayer_1_0_3.xml b/.idea/libraries/jlayer_1_0_3.xml index b09f4ed..1ff1dec 100644 --- a/.idea/libraries/jlayer_1_0_3.xml +++ b/.idea/libraries/jlayer_1_0_3.xml @@ -1,8 +1,7 @@ - - +