diff --git a/src/AiPlayer.java b/src/AiPlayer.java index d51e41e..f3ed2aa 100644 --- a/src/AiPlayer.java +++ b/src/AiPlayer.java @@ -69,6 +69,10 @@ public abstract class AiPlayer extends LocalPlayer implements Runnable { this.shootThreads.add(t); } + /** + * Closes past threads and tries firing a shot. + * @author Luca Conte + */ public void run() { Iterator i = this.shootThreads.iterator(); while(i.hasNext()) { @@ -95,6 +99,10 @@ public abstract class AiPlayer extends LocalPlayer implements Runnable { this.aiShoot(); } + /** + * Closes all running threads and does some cleanup work so the garbage collector will delete the player + * @author Luca Conte + */ @Override public void destroy() { super.destroy(); diff --git a/src/AsyncSocket.java b/src/AsyncSocket.java index a5aa22e..506309f 100644 --- a/src/AsyncSocket.java +++ b/src/AsyncSocket.java @@ -7,6 +7,10 @@ import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; +/** + * Provides an Interface to communicate using a socket asynchronously + * @author Luca Conte + */ public class AsyncSocket { private Socket socket; private Thread checkerThread; @@ -19,6 +23,12 @@ public class AsyncSocket { private BufferedReader in; private BufferedWriter out; + /** + * Creates a socket server and turns the first incoming connection into an AsyncSocket + * @param port the port to listen on for a connection + * @param handler the handler that will be called when a message is received + * @author Luca Conte + */ public AsyncSocket(int port, AsyncSocketListener handler) { this.setHandler(handler); @@ -45,6 +55,12 @@ public class AsyncSocket { this.connectorThread.start(); } + /** + * Connects to the address provided and turns the resulting socket into an AsyncSocket + * @param address the socket address to connect to + * @param handler the handler that will be called when a message is received + * @author Luca Conte + */ public AsyncSocket(InetSocketAddress address, AsyncSocketListener handler) { this.setHandler(handler); @@ -68,11 +84,22 @@ public class AsyncSocket { this.connectorThread.start(); } + /** + * @param socket the socket to be wrapped in an AsyncSocket + * @param handler the handler that will be called when a message is received + * @author Luca Conte + */ public AsyncSocket(Socket socket, AsyncSocketListener handler) throws IOException { this.setHandler(handler); this.initSocket(socket); } + /** + * creates input and ouput writer / readers as well as a checker thread to repeatedly check + * for incoming messages + * @param socket the socket to be wrapped + * @author Luca Conte + */ private void initSocket(Socket socket) throws IOException { System.out.println("Initialising sockets"); this.socket = socket; @@ -122,17 +149,39 @@ public class AsyncSocket { this.flushBuffer(); } + /** + * sets the message handler for the async socket + * @param handler the `AsyncSocketListener` to be set as the new handler + * @author Luca Conte + */ public void setHandler(AsyncSocketListener handler) { this.handler = handler; } + /** + * sends a message through the socket + * @param socketPackage the socket package to be sent + * @author Luca Conte + */ public synchronized void send(SocketPackage socketPackage) { this.sendLine(socketPackage.toString()); } + /** + * sends a message through the socket + * @param packageName the name of the package to be sent + * @author Luca Conte + */ public synchronized void send(String packageName) { this.send(packageName, ""); } + /** + * sends a message through the socket + * @param packageName the name of the package to be sent + * @param packageContent the content of the package to be sent. + * `packageName` and `packageContent` are joined with a space " " + * @author Luca Conte + */ public synchronized void send(String packageName, String packageContent) { if (packageContent.length() > 0) { packageContent = " " + packageContent; @@ -140,11 +189,19 @@ public class AsyncSocket { this.sendLine(packageName + packageContent); } + /** + * sends a string of text into the socket, concatenated with CRLF + * @author Luca Conte + */ public synchronized void sendLine(String message) { sendBuffer = sendBuffer + message + "\r\n"; this.flushBuffer(); } + /** + * flushes the buffers to send all pending messages + * @author Luca Conte + */ private synchronized void flushBuffer() { if (!this.sendBuffer.isEmpty() && this.out != null) { try { @@ -159,12 +216,16 @@ public class AsyncSocket { } } + /** + * closes the socket connection and removes the checker thread + * @author Luca Conte + */ public void close() { this.shouldStop = true; try { this.socket.close(); - this.checkerThread.join(); + if (this.checkerThread != null) this.checkerThread.join(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { diff --git a/src/AsyncSocketListener.java b/src/AsyncSocketListener.java index a8c78ba..af3594e 100644 --- a/src/AsyncSocketListener.java +++ b/src/AsyncSocketListener.java @@ -1,3 +1,6 @@ +/** + * @author Luca Conte + */ public interface AsyncSocketListener { public void receive(String message); } \ No newline at end of file diff --git a/src/Board.java b/src/Board.java index c91468c..1b7095b 100644 --- a/src/Board.java +++ b/src/Board.java @@ -42,6 +42,12 @@ public class Board { return response; } + /** + * finds adjacened hit responses and sets their type to SUNK if they are currently HIT + * this makes it so that all the points of the ship are marked as SUNK, not just the final hit + * @param p the Point from which to propate the SUNK type + * @author Luca Conte + */ private void propagateSunk(Point p) { HitResponse hit = this.getHitResponseOnPoint(p); diff --git a/src/GameController.java b/src/GameController.java index 35b0764..6a921c9 100644 --- a/src/GameController.java +++ b/src/GameController.java @@ -5,28 +5,63 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +/** + * The central Backend Component + * @author Luca Conte + */ public class GameController { private static MainFrame mainFrame; + /** + * @return the current MainFrame + * @author Luca Conte + */ public static MainFrame getMainFrame() { return GameController.mainFrame; } + /** + * @param mainFrame the current MainFrame + * @author Luca Conte + */ public static void setMainFrame(MainFrame mainFrame) { GameController.mainFrame = mainFrame; } + /** + * converts a semester to be played in into its respective board size + * @param semester the semester to be played in + * @author Luca Conte + */ public static int semesterToBoardSize(int semester) { return semester + 13; } + /** + * converts a board size into its respective semester + * @param size the board size to get the semester of + * @author Luca Conte + */ public static int boardSizeToSemester(int size) { return size - 13; } + /** + * the list of supported versions of the online protocol + * https://github.com/lgc-4/ProgProjekt-Netzwerkstandard + */ public static HashMap> supportedVersions = new HashMap<>(Map.of( "1.1.0", OnlinePlayer_1_1_0.class )); + /** + * Starts a game with one local player and one online player. + * @param localPlayerClass the class of the local player to be instantiated. must extend `LocalPlayer` + * @param localPlayerName the name of the local player. Only necessarry when localPlayerClass is `HumanPlayer` + * @param address the Address of the opposing player. If the hostname of the address is set to be 0.0.0.0, it + * is interpreted that this instance should instead listen on the defined port for incoming connections. + * @param size the board size that it is intended to be played in + * @author Luca Conte + */ public static void startOnlineGame(Class localPlayerClass, String localPlayerName, InetSocketAddress address, int size) throws IOException { AsyncSocket clientSocket; @@ -90,6 +125,7 @@ public class GameController { /** * finds the largest common version in two lists of version strings * @return null if no common versions are found + * @author Luca Conte */ public static String findMostRecentVersion(List versions1, List versions2) { if (versions1 == null || versions2 == null) return null; @@ -114,10 +150,13 @@ public class GameController { /** * compares two version strings + * @param version1 the first version to be compared + * @param version2 the second version to be compared * @return * 0 if versions are equal * 1 if version1 is more recent than version2 * -1 otherwise + * @author Luca Conte */ public static int compareVersions(String version1, String version2) { if (!checkVersionString(version1) || !checkVersionString(version2)) { @@ -143,11 +182,21 @@ public class GameController { /** * checks if a provided string matches the format of a version number + * @param versionString the version String to be checked + * @author Luca Conte */ public static boolean checkVersionString(String versionString) { return versionString != null && versionString.matches("\\d+\\.\\d+\\.\\d+"); } + /** + * Starts a game with two local players + * @param localPlayerClass the class of the local player to be instantiated. must extend `LocalPlayer` + * @param localPlayerName the name of the local player. Only necessarry when localPlayerClass is `HumanPlayer` + * @param enemyClass the class of the enemy player. Must extend `AiPlayer`. For Humans VS Human games use an online game instead. + * @param size the board size that it is intended to be played in + * @author Luca Conte + */ public static void startLocalGame(Class localPlayerClass, String localPlayerName, Class enemyClass, int size) { LocalPlayer localPlayer; @@ -175,6 +224,13 @@ public class GameController { startGameWithInstancedPlayers(localPlayer, aiPlayer, size); } + /** + * switches to the ingame screen + * @param p1 the first player. This player is always shown on the left side of the screen and is expected to be the Human player, if there is one. + * @param p2 the second player + * @param boardSize the board size to be played in + * @author Luca Conte + */ public static void startGameWithInstancedPlayers(LocalPlayer p1, Player p2, int boardSize) { mainFrame.showPanelSLG("GameBoard", boardSizeToSemester(boardSize), p1, p2);