diff --git a/core/src/netwerkprog/game/client/Client.java b/core/src/netwerkprog/game/client/Client.java deleted file mode 100644 index 93d6d2a..0000000 --- a/core/src/netwerkprog/game/client/Client.java +++ /dev/null @@ -1,104 +0,0 @@ -package netwerkprog.game.client; - -import netwerkprog.game.util.application.Controller; -import netwerkprog.game.util.data.Data; -import netwerkprog.game.util.data.ParserCallback; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.net.Socket; -import java.util.Arrays; - -public class Client extends Controller implements ParserCallback { - private final int port; - private final String hostname; - private final Parser parser; - private boolean isConnected = true; - private Socket socket; - private Thread receiveThread; - private DataOutputStream outputStream; - - public Client(String hostname) { - this.port = Data.port(); - this.hostname = hostname; - this.parser = new Parser(this); - } - - /** - * Starts the client process. - */ - @Override - public void run() { - this.connect(); - this.receiveThread.start(); - } - - /** - * Connects the client to the server. - */ - public void connect() { - System.out.println("[CLIENT] connecting to server on port " + this.port); - try { - this.socket = new Socket(this.hostname, this.port); - DataInputStream in = new DataInputStream(socket.getInputStream()); - this.outputStream = new DataOutputStream(socket.getOutputStream()); - - this.receiveThread = new Thread( () -> receive(in)); - - } catch (IOException e) { - System.out.println("[CLIENT] there was an error connecting : " + e.getMessage()); - StringBuilder sb = new StringBuilder(" Stacktrace : "); - Arrays.stream(e.getStackTrace()).forEach(n -> sb.append("\t\t").append(n).append("\n")); - System.out.println(sb.toString()); - } - } - - /** - * Sends a message to the server. - * @param message The message to send. - */ - public void send(String message) { - try { - this.outputStream.writeUTF(message); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Receives a message from the server. - * @param in The inputStream - */ - public void receive(DataInputStream in) { - while (isConnected) { - try { - this.parser.parse(in.readUTF()); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - public void disconnect() { - this.isConnected = false; - try { - this.receiveThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - send("Disconnect"); - - try { - this.socket.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void onDataReceived(String data) { - System.out.println(data); - } -} diff --git a/core/src/netwerkprog/game/client/MainGame.java b/core/src/netwerkprog/game/client/MainGame.java index b22b32f..c812dd3 100644 --- a/core/src/netwerkprog/game/client/MainGame.java +++ b/core/src/netwerkprog/game/client/MainGame.java @@ -17,10 +17,13 @@ import netwerkprog.game.client.game.characters.Agent; import netwerkprog.game.client.game.characters.Hacker; import netwerkprog.game.client.game.characters.Team; import netwerkprog.game.client.game.characters.abilities.BodySwap; +import netwerkprog.game.client.game.connections.Client; import netwerkprog.game.client.game.map.GameInputProcessor; import netwerkprog.game.client.game.map.GameTile; import netwerkprog.game.client.game.map.Map; import netwerkprog.game.client.game.map.MapRenderer; +import netwerkprog.game.util.data.Data; +import netwerkprog.game.util.data.DataCallback; import netwerkprog.game.util.game.Faction; import netwerkprog.game.util.game.GameCharacter; import netwerkprog.game.util.graphics.FrameRate; @@ -28,7 +31,7 @@ import netwerkprog.game.util.graphics.TextRenderer; import java.awt.*; -public class MainGame extends ApplicationAdapter { +public class MainGame extends ApplicationAdapter implements DataCallback { SpriteBatch batch; float screenWidth; float screenHeight; @@ -104,7 +107,7 @@ public class MainGame extends ApplicationAdapter { // playSong(); -// connectToServer(); + connectToServer(); } public void initCharacters() { @@ -146,7 +149,7 @@ public class MainGame extends ApplicationAdapter { private void connectToServer() { - client = new Thread(new Client("localhost")); + client = new Thread(new Client("localhost", this)); try { client.start(); } catch (Exception e) { @@ -273,4 +276,8 @@ public class MainGame extends ApplicationAdapter { return team; } + @Override + public void onDataReceived(Data data) { + + } } diff --git a/core/src/netwerkprog/game/client/Parser.java b/core/src/netwerkprog/game/client/Parser.java deleted file mode 100644 index 79849cb..0000000 --- a/core/src/netwerkprog/game/client/Parser.java +++ /dev/null @@ -1,15 +0,0 @@ -package netwerkprog.game.client; - -import netwerkprog.game.util.data.ParserCallback; - -public class Parser { - private final ParserCallback callback; - - public Parser(ParserCallback callback) { - this.callback = callback; - } - - public void parse(String data) { - callback.onDataReceived(data); - } -} diff --git a/core/src/netwerkprog/game/client/game/connections/Client.java b/core/src/netwerkprog/game/client/game/connections/Client.java new file mode 100644 index 0000000..16167cd --- /dev/null +++ b/core/src/netwerkprog/game/client/game/connections/Client.java @@ -0,0 +1,127 @@ +package netwerkprog.game.client.game.connections; + +import netwerkprog.game.util.application.Controller; +import netwerkprog.game.util.data.ConnectionData; +import netwerkprog.game.util.data.Data; +import netwerkprog.game.util.data.DataCallback; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.Socket; +import java.util.Arrays; + +public class Client extends Controller { + private final int port; + private final String hostname; + private boolean isConnected; + private Socket socket; + private Thread receiveThread; + private DataCallback callback; + private ObjectOutputStream outputStream; + private boolean connecting; + + public Client(String hostname, DataCallback callback) { + this.port = Data.port(); + this.hostname = hostname; + this.callback = callback; + } + + /** + * Starts the client process. + */ + @Override + public void run() { + this.connect(); + this.receiveThread.start(); + } + + /** + * Connects the client to the server. + */ + public void connect() { + System.out.println("[CLIENT] connecting to server on port " + this.port); + this.connecting = true; + try { + this.socket = new Socket(this.hostname, this.port); + ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); + this.outputStream = new ObjectOutputStream(socket.getOutputStream()); + register(in); + this.receiveThread = new Thread( () -> receive(in)); + } catch (IOException e) { + this.connecting = false; + System.out.println("[CLIENT] there was an error connecting : " + e.getMessage()); + StringBuilder sb = new StringBuilder(" Stacktrace : "); + Arrays.stream(e.getStackTrace()).forEach(n -> sb.append("\t\t").append(n).append("\n")); + System.out.println(sb.toString()); + } + } + + public void register(ObjectInputStream in) { + while (connecting) { + String username = "DEV"; + send(new ConnectionData("Connect", username)); + try { + Object object = in.readObject(); + if (object instanceof Data) { + Data data = (Data) object; + if (data.getPayload() instanceof ConnectionData) { + ConnectionData connectionData = (ConnectionData) data.getPayload(); + if (connectionData.getAction().equals("Connect") && connectionData.getMessage().equals("Confirm")){ + this.connecting = false; + this.isConnected = true; + } + } + } + } catch (IOException | ClassNotFoundException e) { + e.printStackTrace(); + } + } + } + + /** + * Sends a message to the server. + * @param data The message to send. + */ + public void send(Data data) { + try { + this.outputStream.writeObject(data); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Receives a message from the server. + * @param in The inputStream + */ + public void receive(ObjectInputStream in) { + while (isConnected) { + try { + Object object = in.readObject(); + if (object instanceof Data) { + callback.onDataReceived((Data) object); + } + } catch (IOException | ClassNotFoundException e) { + e.printStackTrace(); + } + } + } + + public void disconnect() { + this.isConnected = false; + try { + this.receiveThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + send(new ConnectionData("Disconnect", "DEV")); + + try { + this.socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/core/src/netwerkprog/game/server/Parser.java b/core/src/netwerkprog/game/server/Parser.java deleted file mode 100644 index c4dcb44..0000000 --- a/core/src/netwerkprog/game/server/Parser.java +++ /dev/null @@ -1,43 +0,0 @@ -package netwerkprog.game.server; - -import netwerkprog.game.client.game.characters.DevTest1; -import netwerkprog.game.client.game.characters.DevTest2; -import netwerkprog.game.client.game.characters.DevTest3; -import netwerkprog.game.server.controllers.DataController; -import netwerkprog.game.util.data.ParserCallback; - -import java.util.Scanner; - -public class Parser { - private final ParserCallback callback; - private Scanner scanner; - - private final DataController dataController; - - public Parser(ParserCallback callback) { - this.callback = callback; - this.dataController = new DataController(); - - this.dataController.addAllCharacters(new DevTest1(), new DevTest2(), new DevTest3()); - } - - public void parse(String request) { - String data = ""; - this.scanner = new Scanner(request); - scanner.useDelimiter("~"); - String type = scanner.next(); - String name = scanner.next(); - - if (type.equals("character")) { - try { - data = dataController.getCharacter(name).toString(); - } catch (IllegalArgumentException ex) { - data = ex.getMessage(); - } - } - - - - callback.onDataReceived(data); - } -} diff --git a/core/src/netwerkprog/game/server/Server.java b/core/src/netwerkprog/game/server/Server.java index 1e48ddb..3326979 100644 --- a/core/src/netwerkprog/game/server/Server.java +++ b/core/src/netwerkprog/game/server/Server.java @@ -1,16 +1,19 @@ package netwerkprog.game.server; +import netwerkprog.game.server.controllers.DataController; import netwerkprog.game.server.controllers.SessionController; import java.util.HashMap; public class Server { private SessionController sessionController; + private DataController dataController; private Thread sessionThread; private HashMap gameThreads; public void start() { - this.sessionController = new SessionController(); + this.sessionController = new SessionController(this); + this.dataController = new DataController(); this.gameThreads = new HashMap<>(); this.sessionThread = new Thread(sessionController); @@ -32,4 +35,8 @@ public class Server { // gameThreads.get(game).start(); // } } + + public DataController getDataController() { + return dataController; + } } diff --git a/core/src/netwerkprog/game/server/ServerClient.java b/core/src/netwerkprog/game/server/ServerClient.java index f937bf4..804594e 100644 --- a/core/src/netwerkprog/game/server/ServerClient.java +++ b/core/src/netwerkprog/game/server/ServerClient.java @@ -1,38 +1,35 @@ package netwerkprog.game.server; +import netwerkprog.game.server.controllers.DataController; import netwerkprog.game.server.controllers.SessionController; -import netwerkprog.game.util.data.ParserCallback; +import netwerkprog.game.util.data.ConnectionData; +import netwerkprog.game.util.data.Data; +import netwerkprog.game.util.data.DataCallback; -import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.IOException; -import java.net.Socket; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; -public class ServerClient implements Runnable, ParserCallback { - private DataInputStream in; - private DataOutputStream out; +public class ServerClient implements Runnable { + private ObjectInputStream in; + private ObjectOutputStream out; private final String name; private final SessionController server; - private final Parser parser; + private final DataCallback callback; private boolean isConnected; - public ServerClient(String name, Socket socket, SessionController server) { + public ServerClient(String name, ObjectInputStream in, ObjectOutputStream out, SessionController server, DataController dataController) { this.name = name; this.server = server; - this.parser = new Parser(this); - try { - this.in = new DataInputStream(socket.getInputStream()); - this.out = new DataOutputStream(socket.getOutputStream()); - this.isConnected = true; - } catch (IOException e) { - this.isConnected = false; - e.printStackTrace(); - } + this.callback = dataController; + this.in = in; + this.out = out; + this.isConnected = true; } - public void writeUTF(String text) { + public void writeData(Data data) { try { - this.out.writeUTF(text); + this.out.writeObject(data); } catch (IOException e) { e.printStackTrace(); } @@ -42,14 +39,26 @@ public class ServerClient implements Runnable, ParserCallback { public void run() { while (this.isConnected) { try { - String received = this.in.readUTF(); - this.parser.parse(received); - + Object object = this.in.readObject(); + if (object instanceof Data) { + Data data = (Data) object; + if (data.getPayload() instanceof ConnectionData) { + ConnectionData connectionData = (ConnectionData) data.getPayload(); + if (connectionData.getAction().equals("Disconnect")) { + this.isConnected = false; + //todo properly remove thread. + } + } else { + callback.onDataReceived((Data) this.in.readObject()); + } + } } catch (IOException e) { System.out.println("[SERVERCLIENT] caught exception - " + e.getMessage()); System.out.println("[SERVERCLIENT] terminating failing connection..."); this.isConnected = false; System.out.println("[SERVERCLIENT] done!"); + } catch (ClassNotFoundException e) { + e.printStackTrace(); } } } @@ -57,9 +66,4 @@ public class ServerClient implements Runnable, ParserCallback { public String getName() { return this.name; } - - @Override - public void onDataReceived(String data) { - writeUTF(data); - } } diff --git a/core/src/netwerkprog/game/server/controllers/DataController.java b/core/src/netwerkprog/game/server/controllers/DataController.java index f1de4bc..ab097a5 100644 --- a/core/src/netwerkprog/game/server/controllers/DataController.java +++ b/core/src/netwerkprog/game/server/controllers/DataController.java @@ -1,11 +1,14 @@ package netwerkprog.game.server.controllers; +import netwerkprog.game.util.data.CharacterData; +import netwerkprog.game.util.data.Data; +import netwerkprog.game.util.data.DataCallback; import netwerkprog.game.util.game.GameCharacter; import java.util.Arrays; import java.util.HashSet; -public class DataController { +public class DataController implements DataCallback { private final HashSet gameCharacters; public DataController() { @@ -44,4 +47,15 @@ public class DataController { } throw new IllegalArgumentException("The character does not exist."); } + + @Override + public void onDataReceived(Data data) { + switch (data.getType()) { + case "Character" : + if (data.getPayload() instanceof CharacterData) { + + } + break; + } + } } diff --git a/core/src/netwerkprog/game/server/controllers/SessionController.java b/core/src/netwerkprog/game/server/controllers/SessionController.java index 94a7c0b..4014704 100644 --- a/core/src/netwerkprog/game/server/controllers/SessionController.java +++ b/core/src/netwerkprog/game/server/controllers/SessionController.java @@ -1,11 +1,13 @@ package netwerkprog.game.server.controllers; +import netwerkprog.game.server.Server; import netwerkprog.game.server.ServerClient; import netwerkprog.game.util.application.Controller; +import netwerkprog.game.util.data.ConnectionData; import netwerkprog.game.util.data.Data; -import java.io.DataInputStream; import java.io.IOException; +import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.ServerSocket; import java.net.Socket; @@ -17,12 +19,14 @@ import java.util.Set; * The sessionController manages any connections from new clients and assigns individual threads to said clients. */ public class SessionController extends Controller { + private Server server; private ServerSocket serverSocket; private final ArrayList clients = new ArrayList<>(); private final HashMap clientThreads = new HashMap<>(); private boolean listening; - public SessionController() { + public SessionController(Server server) { + this.server = server; this.listening = true; } @@ -59,43 +63,66 @@ public class SessionController extends Controller { try { System.out.println("[SERVER] got new client on " + socket.getInetAddress().getHostAddress()); ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream()); - DataInputStream inputStream = new DataInputStream(socket.getInputStream()); + ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream()); - outputStream.writeUTF("Enter username: "); - String username = inputStream.readUTF(); + String username = ""; + boolean registering = true; + + while (registering) { + outputStream.writeObject(new ConnectionData("Connect", "Please give a username")); + Object object = inputStream.readObject(); + + if (object instanceof Data) { + Data data = (Data) object; + if (data instanceof ConnectionData) { + ConnectionData connectionData = (ConnectionData) data.getPayload(); + if (connectionData.getAction().equals("Connect")) { + username = connectionData.getMessage(); + outputStream.writeObject(new ConnectionData("Connect", "Confirm")); + registering = false; + } else { + //todo error messaging. + } + } else { + //todo error messaging. + } + } else { + //todo error messaging. + } + } System.out.println("[SERVER] got username " + username); - ServerClient serverClient = new ServerClient(username, socket, this); + ServerClient serverClient = new ServerClient(username, inputStream, outputStream, this, server.getDataController()); Thread t = new Thread(serverClient); t.start(); this.clientThreads.put(username,t); this.clients.add(serverClient); - } catch (IOException ex) { + } catch (IOException | ClassNotFoundException ex) { ex.printStackTrace(); } } /** * Sends a server message to all connected clients. - * @param text message. + * @param data message. */ - public void serverMessage(String text) { + public void serverMessage(Data data) { for (ServerClient serverClient : clients) { - serverClient.writeUTF(text); + serverClient.writeData(data); } } /** * Sends a message to a specific user. * @param name user. - * @param text message. + * @param data message. */ - public void personalMessage(String name, String text) { + public void personalMessage(String name, Data data) { for (ServerClient serverClient : clients) { if (serverClient.getName().equals(name)) { - serverClient.writeUTF(text); + serverClient.writeData(data); break; } } @@ -113,7 +140,7 @@ public class SessionController extends Controller { e.printStackTrace(); } this.clientThreads.remove(serverClient.getName()); - this.serverMessage(serverClient.getName() + " left!"); + //this.serverMessage(serverClient.getName() + " left!"); } /** diff --git a/core/src/netwerkprog/game/util/data/CharacterData.java b/core/src/netwerkprog/game/util/data/CharacterData.java new file mode 100644 index 0000000..b89862a --- /dev/null +++ b/core/src/netwerkprog/game/util/data/CharacterData.java @@ -0,0 +1,17 @@ +package netwerkprog.game.util.data; + +import netwerkprog.game.util.game.GameCharacter; + +import java.io.Serializable; + +public class CharacterData extends Data implements Serializable { + private final String name; + private final GameCharacter character; + + public CharacterData(String name, GameCharacter character) { + super("Character"); + super.setPayload(this); + this.name = name; + this.character = character; + } +} diff --git a/core/src/netwerkprog/game/util/data/ConnectionData.java b/core/src/netwerkprog/game/util/data/ConnectionData.java new file mode 100644 index 0000000..911181f --- /dev/null +++ b/core/src/netwerkprog/game/util/data/ConnectionData.java @@ -0,0 +1,23 @@ +package netwerkprog.game.util.data; + +import java.io.Serializable; + +public class ConnectionData extends Data implements Serializable { + private final String action; + private final String message; + + public ConnectionData(String action, String message) { + super("Connection"); + super.setPayload(this); + this.action = action; + this.message = message; + } + + public String getAction() { + return action; + } + + public String getMessage() { + return message; + } +} diff --git a/core/src/netwerkprog/game/util/data/Data.java b/core/src/netwerkprog/game/util/data/Data.java index 2bdcce4..24ed738 100644 --- a/core/src/netwerkprog/game/util/data/Data.java +++ b/core/src/netwerkprog/game/util/data/Data.java @@ -1,7 +1,32 @@ package netwerkprog.game.util.data; -public class Data { +import java.io.Serializable; + +public class Data implements Serializable { public static int port() { return 8000; } + + private String objectType; + private Data payload; + + public Data(String type) { + this.objectType = type; + } + + public void setObjectType(String objectType) { + this.objectType = objectType; + } + + public void setPayload(Data payload) { + this.payload = payload; + } + + public String getType() { + return objectType; + } + + public Data getPayload() { + return payload; + } } diff --git a/core/src/netwerkprog/game/util/data/DataCallback.java b/core/src/netwerkprog/game/util/data/DataCallback.java new file mode 100644 index 0000000..95b2d88 --- /dev/null +++ b/core/src/netwerkprog/game/util/data/DataCallback.java @@ -0,0 +1,5 @@ +package netwerkprog.game.util.data; + +public interface DataCallback { + void onDataReceived(Data data); +} diff --git a/core/src/netwerkprog/game/util/game/GameCharacter.java b/core/src/netwerkprog/game/util/game/GameCharacter.java index 4715e86..282533e 100644 --- a/core/src/netwerkprog/game/util/game/GameCharacter.java +++ b/core/src/netwerkprog/game/util/game/GameCharacter.java @@ -5,13 +5,14 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.Actor; import netwerkprog.game.client.game.map.GameTile; +import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Objects; -public abstract class GameCharacter extends Actor implements Comparable { +public abstract class GameCharacter extends Actor implements Comparable, Serializable { protected String name; protected Faction faction; protected HashSet abilities; diff --git a/core/src/test/java/RestartSessionControllerTest.java b/core/src/test/java/RestartSessionControllerTest.java index efd4ede..9d5f5b2 100644 --- a/core/src/test/java/RestartSessionControllerTest.java +++ b/core/src/test/java/RestartSessionControllerTest.java @@ -8,7 +8,7 @@ public class RestartSessionControllerTest { SessionController sessionController; Thread sessionThread; - sessionController = new SessionController(); + sessionController = new SessionController(null); sessionThread = new Thread(sessionController); sessionThread.start();