cleanup-work #22
|
@ -69,6 +69,10 @@ public abstract class AiPlayer extends LocalPlayer implements Runnable {
|
||||||
this.shootThreads.add(t);
|
this.shootThreads.add(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes past threads and tries firing a shot.
|
||||||
|
* @author Luca Conte
|
||||||
|
*/
|
||||||
public void run() {
|
public void run() {
|
||||||
Iterator<Thread> i = this.shootThreads.iterator();
|
Iterator<Thread> i = this.shootThreads.iterator();
|
||||||
while(i.hasNext()) {
|
while(i.hasNext()) {
|
||||||
|
@ -95,6 +99,10 @@ public abstract class AiPlayer extends LocalPlayer implements Runnable {
|
||||||
this.aiShoot();
|
this.aiShoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes all running threads and does some cleanup work so the garbage collector will delete the player
|
||||||
|
* @author Luca Conte
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
super.destroy();
|
super.destroy();
|
||||||
|
|
|
@ -7,6 +7,10 @@ import java.net.InetSocketAddress;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides an Interface to communicate using a socket asynchronously
|
||||||
|
* @author Luca Conte
|
||||||
|
*/
|
||||||
public class AsyncSocket {
|
public class AsyncSocket {
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
private Thread checkerThread;
|
private Thread checkerThread;
|
||||||
|
@ -19,6 +23,12 @@ public class AsyncSocket {
|
||||||
private BufferedReader in;
|
private BufferedReader in;
|
||||||
private BufferedWriter out;
|
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) {
|
public AsyncSocket(int port, AsyncSocketListener handler) {
|
||||||
this.setHandler(handler);
|
this.setHandler(handler);
|
||||||
|
|
||||||
|
@ -45,6 +55,12 @@ public class AsyncSocket {
|
||||||
this.connectorThread.start();
|
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) {
|
public AsyncSocket(InetSocketAddress address, AsyncSocketListener handler) {
|
||||||
this.setHandler(handler);
|
this.setHandler(handler);
|
||||||
|
|
||||||
|
@ -68,11 +84,22 @@ public class AsyncSocket {
|
||||||
this.connectorThread.start();
|
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 {
|
public AsyncSocket(Socket socket, AsyncSocketListener handler) throws IOException {
|
||||||
this.setHandler(handler);
|
this.setHandler(handler);
|
||||||
this.initSocket(socket);
|
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 {
|
private void initSocket(Socket socket) throws IOException {
|
||||||
System.out.println("Initialising sockets");
|
System.out.println("Initialising sockets");
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
|
@ -122,17 +149,39 @@ public class AsyncSocket {
|
||||||
this.flushBuffer();
|
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) {
|
public void setHandler(AsyncSocketListener handler) {
|
||||||
this.handler = 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) {
|
public synchronized void send(SocketPackage socketPackage) {
|
||||||
this.sendLine(socketPackage.toString());
|
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) {
|
public synchronized void send(String packageName) {
|
||||||
this.send(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) {
|
public synchronized void send(String packageName, String packageContent) {
|
||||||
if (packageContent.length() > 0) {
|
if (packageContent.length() > 0) {
|
||||||
packageContent = " " + packageContent;
|
packageContent = " " + packageContent;
|
||||||
|
@ -140,11 +189,19 @@ public class AsyncSocket {
|
||||||
this.sendLine(packageName + packageContent);
|
this.sendLine(packageName + packageContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sends a string of text into the socket, concatenated with CRLF
|
||||||
|
* @author Luca Conte
|
||||||
|
*/
|
||||||
public synchronized void sendLine(String message) {
|
public synchronized void sendLine(String message) {
|
||||||
sendBuffer = sendBuffer + message + "\r\n";
|
sendBuffer = sendBuffer + message + "\r\n";
|
||||||
this.flushBuffer();
|
this.flushBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* flushes the buffers to send all pending messages
|
||||||
|
* @author Luca Conte
|
||||||
|
*/
|
||||||
private synchronized void flushBuffer() {
|
private synchronized void flushBuffer() {
|
||||||
if (!this.sendBuffer.isEmpty() && this.out != null) {
|
if (!this.sendBuffer.isEmpty() && this.out != null) {
|
||||||
try {
|
try {
|
||||||
|
@ -159,12 +216,16 @@ public class AsyncSocket {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* closes the socket connection and removes the checker thread
|
||||||
|
* @author Luca Conte
|
||||||
|
*/
|
||||||
public void close() {
|
public void close() {
|
||||||
this.shouldStop = true;
|
this.shouldStop = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.socket.close();
|
this.socket.close();
|
||||||
this.checkerThread.join();
|
if (this.checkerThread != null) this.checkerThread.join();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/**
|
||||||
|
* @author Luca Conte
|
||||||
|
*/
|
||||||
public interface AsyncSocketListener {
|
public interface AsyncSocketListener {
|
||||||
public void receive(String message);
|
public void receive(String message);
|
||||||
}
|
}
|
|
@ -42,6 +42,12 @@ public class Board {
|
||||||
return response;
|
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) {
|
private void propagateSunk(Point p) {
|
||||||
HitResponse hit = this.getHitResponseOnPoint(p);
|
HitResponse hit = this.getHitResponseOnPoint(p);
|
||||||
|
|
||||||
|
|
|
@ -5,28 +5,63 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The central Backend Component
|
||||||
|
* @author Luca Conte
|
||||||
|
*/
|
||||||
public class GameController {
|
public class GameController {
|
||||||
|
|
||||||
private static MainFrame mainFrame;
|
private static MainFrame mainFrame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the current MainFrame
|
||||||
|
* @author Luca Conte
|
||||||
|
*/
|
||||||
public static MainFrame getMainFrame() {
|
public static MainFrame getMainFrame() {
|
||||||
return GameController.mainFrame;
|
return GameController.mainFrame;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @param mainFrame the current MainFrame
|
||||||
|
* @author Luca Conte
|
||||||
|
*/
|
||||||
public static void setMainFrame(MainFrame mainFrame) {
|
public static void setMainFrame(MainFrame mainFrame) {
|
||||||
GameController.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) {
|
public static int semesterToBoardSize(int semester) {
|
||||||
return semester + 13;
|
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) {
|
public static int boardSizeToSemester(int size) {
|
||||||
return size - 13;
|
return size - 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the list of supported versions of the online protocol
|
||||||
|
* https://github.com/lgc-4/ProgProjekt-Netzwerkstandard
|
||||||
|
*/
|
||||||
public static HashMap<String, Class<? extends OnlinePlayer>> supportedVersions = new HashMap<>(Map.of(
|
public static HashMap<String, Class<? extends OnlinePlayer>> supportedVersions = new HashMap<>(Map.of(
|
||||||
"1.1.0", OnlinePlayer_1_1_0.class
|
"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<? extends LocalPlayer> localPlayerClass, String localPlayerName, InetSocketAddress address, int size) throws IOException {
|
public static void startOnlineGame(Class<? extends LocalPlayer> localPlayerClass, String localPlayerName, InetSocketAddress address, int size) throws IOException {
|
||||||
AsyncSocket clientSocket;
|
AsyncSocket clientSocket;
|
||||||
|
|
||||||
|
@ -90,6 +125,7 @@ public class GameController {
|
||||||
/**
|
/**
|
||||||
* finds the largest common version in two lists of version strings
|
* finds the largest common version in two lists of version strings
|
||||||
* @return null if no common versions are found
|
* @return null if no common versions are found
|
||||||
|
* @author Luca Conte
|
||||||
*/
|
*/
|
||||||
public static String findMostRecentVersion(List<String> versions1, List<String> versions2) {
|
public static String findMostRecentVersion(List<String> versions1, List<String> versions2) {
|
||||||
if (versions1 == null || versions2 == null) return null;
|
if (versions1 == null || versions2 == null) return null;
|
||||||
|
@ -114,10 +150,13 @@ public class GameController {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* compares two version strings
|
* compares two version strings
|
||||||
|
* @param version1 the first version to be compared
|
||||||
|
* @param version2 the second version to be compared
|
||||||
* @return
|
* @return
|
||||||
* 0 if versions are equal
|
* 0 if versions are equal
|
||||||
* 1 if version1 is more recent than version2
|
* 1 if version1 is more recent than version2
|
||||||
* -1 otherwise
|
* -1 otherwise
|
||||||
|
* @author Luca Conte
|
||||||
*/
|
*/
|
||||||
public static int compareVersions(String version1, String version2) {
|
public static int compareVersions(String version1, String version2) {
|
||||||
if (!checkVersionString(version1) || !checkVersionString(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
|
* 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) {
|
public static boolean checkVersionString(String versionString) {
|
||||||
return versionString != null && versionString.matches("\\d+\\.\\d+\\.\\d+");
|
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<? extends LocalPlayer> localPlayerClass, String localPlayerName, Class<? extends AiPlayer> enemyClass, int size) {
|
public static void startLocalGame(Class<? extends LocalPlayer> localPlayerClass, String localPlayerName, Class<? extends AiPlayer> enemyClass, int size) {
|
||||||
|
|
||||||
LocalPlayer localPlayer;
|
LocalPlayer localPlayer;
|
||||||
|
@ -175,6 +224,13 @@ public class GameController {
|
||||||
startGameWithInstancedPlayers(localPlayer, aiPlayer, size);
|
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) {
|
public static void startGameWithInstancedPlayers(LocalPlayer p1, Player p2, int boardSize) {
|
||||||
mainFrame.showPanelSLG("GameBoard", boardSizeToSemester(boardSize), p1, p2);
|
mainFrame.showPanelSLG("GameBoard", boardSizeToSemester(boardSize), p1, p2);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue