Reworked protocol between server and client
- Changed successCodes from int to boolean - Added exception handling for better debugging in TicTacToe_Client - fixed bug that disallowed singleplayer mode
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
import logging.LogType;
|
||||||
import networking.Client;
|
import networking.Client;
|
||||||
import render.Engine;
|
import render.Engine;
|
||||||
|
|
||||||
@@ -11,26 +12,29 @@ public class TicTacToe_Client {
|
|||||||
private Client client;
|
private Client client;
|
||||||
private static String clientName;
|
private static String clientName;
|
||||||
private boolean isPlayerOne;
|
private boolean isPlayerOne;
|
||||||
|
private boolean isAllowedToMove;
|
||||||
|
|
||||||
public TicTacToe_Client() {
|
public TicTacToe_Client() {
|
||||||
renderEngine = Engine.waitForEngine();
|
renderEngine = Engine.waitForEngine();
|
||||||
client = new Client("server", 2589, clientName);
|
client = new Client("server", 2589, clientName);
|
||||||
client.handshake();
|
client.handshake();
|
||||||
isPlayerOne = client.isPlayerOne();
|
isPlayerOne = client.isPlayerOne();
|
||||||
|
isAllowedToMove = isPlayerOne;
|
||||||
this.setWindowTitle(isPlayerOne);
|
this.setWindowTitle(isPlayerOne);
|
||||||
client.sendToServer("ready");
|
client.sendToServer("ready");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ticTacToe_gameloop() {
|
private void ticTacToe_gameloop() {
|
||||||
this.drawBoard(client.getGameState());
|
|
||||||
if (isPlayerOne){
|
|
||||||
this.userInput();
|
|
||||||
}
|
|
||||||
while (client.isConnected() && !renderEngine.isWindowClosed()) {
|
while (client.isConnected() && !renderEngine.isWindowClosed()) {
|
||||||
|
client.printLog("Waiting for data", true, LogType.Log);
|
||||||
String message = client.getResponse();
|
String message = client.getResponse();
|
||||||
//Check if message is gamestate
|
//Check if message is gamestate
|
||||||
if (message.charAt(0) == 'x' || message.charAt(0) == '-' || message.charAt(0) == 'o') {
|
if (message.matches("([xo-]){9}")) {
|
||||||
|
client.printLog("Board updated", true, LogType.Log);
|
||||||
this.drawBoard(message);
|
this.drawBoard(message);
|
||||||
|
if (isAllowedToMove){
|
||||||
|
this.gameFlow("userInput");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//Handle everything else
|
//Handle everything else
|
||||||
else {
|
else {
|
||||||
@@ -46,6 +50,11 @@ public class TicTacToe_Client {
|
|||||||
|
|
||||||
private void gameFlow(String input) {
|
private void gameFlow(String input) {
|
||||||
switch (input) {
|
switch (input) {
|
||||||
|
case "opponentMove":
|
||||||
|
//if opponent makes move allow a move
|
||||||
|
isAllowedToMove = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case "userInput":
|
case "userInput":
|
||||||
while (!renderEngine.isMouseClicked()) {
|
while (!renderEngine.isMouseClicked()) {
|
||||||
try {
|
try {
|
||||||
@@ -55,21 +64,21 @@ public class TicTacToe_Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
renderEngine.setMouseClicked(false);
|
renderEngine.setMouseClicked(false);
|
||||||
|
isAllowedToMove = false;
|
||||||
this.userInput();
|
this.userInput();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "invalidInput":
|
case "invalidInput":
|
||||||
|
isAllowedToMove = true;
|
||||||
this.onInvalidInput();
|
this.onInvalidInput();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ""
|
case "gameEnded":
|
||||||
|
this.onGameEnd();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void requestOpponentMove(){
|
|
||||||
client.sendToServer("opponentMove");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onGameEnd(){
|
private void onGameEnd(){
|
||||||
LinkedList<Integer> winCoordinates = new LinkedList<>();
|
LinkedList<Integer> winCoordinates = new LinkedList<>();
|
||||||
//Get winning fields
|
//Get winning fields
|
||||||
@@ -91,27 +100,12 @@ public class TicTacToe_Client {
|
|||||||
int column = (int) renderEngine.getCoordinates().getX() / 300;
|
int column = (int) renderEngine.getCoordinates().getX() / 300;
|
||||||
int row = (int) renderEngine.getCoordinates().getY() / 300;
|
int row = (int) renderEngine.getCoordinates().getY() / 300;
|
||||||
System.err.printf("You are not allowed to place at %d|%d%n", column, row);
|
System.err.printf("You are not allowed to place at %d|%d%n", column, row);
|
||||||
this.userInput();
|
this.gameFlow("userInput");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void userInput() {
|
private void userInput() {
|
||||||
client.sendToServer("clientMove");
|
client.sendToServer("clientMove");
|
||||||
client.sendToServer(String.format("%f|%f", renderEngine.getCoordinates().getX(), renderEngine.getCoordinates().getY()));
|
client.sendToServer(String.format("%f|%f", renderEngine.getCoordinates().getX(), renderEngine.getCoordinates().getY()));
|
||||||
//Get gameState
|
|
||||||
String gameState = client.getResponse();
|
|
||||||
if (gameState.length() == 9) {
|
|
||||||
this.drawBoard(gameState);
|
|
||||||
//Send command
|
|
||||||
if (!client.getGameEnded()) {
|
|
||||||
this.requestOpponentMove();
|
|
||||||
} else {
|
|
||||||
this.onGameEnd();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int column = (int) renderEngine.getCoordinates().getX() / 300;
|
|
||||||
int row = (int) renderEngine.getCoordinates().getY() / 300;
|
|
||||||
System.err.printf("You are not allowed to place at %d|%d%n", column, row);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawBoard(String gameState) {
|
private void drawBoard(String gameState) {
|
||||||
@@ -148,12 +142,12 @@ public class TicTacToe_Client {
|
|||||||
javafx.application.Application.launch(Engine.class);
|
javafx.application.Application.launch(Engine.class);
|
||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
TicTacToe_Client test = new TicTacToe_Client();
|
|
||||||
try {
|
try {
|
||||||
clientName = args[0];
|
clientName = args[0];
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
clientName = "testing";
|
clientName = "testing";
|
||||||
}
|
}
|
||||||
|
TicTacToe_Client test = new TicTacToe_Client();
|
||||||
test.ticTacToe_gameloop();
|
test.ticTacToe_gameloop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ public class ClientLogger {
|
|||||||
this.printLog(message, "server", success, logType);
|
this.printLog(message, "server", success, logType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void printConfirmation(int code){
|
public void printConfirmation(boolean success){
|
||||||
if (code == 200){
|
if (success){
|
||||||
printLog(" Status: sent!", true, LogType.Log);
|
printLog(" Status: sent!", true, LogType.Log);
|
||||||
} else {
|
} else {
|
||||||
printLog(" Status: not sent!", false, LogType.Log);
|
printLog(" Status: not sent!", false, LogType.Log);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import java.io.DataInputStream;
|
|||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.Scanner;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class Client {
|
public class Client {
|
||||||
private Socket serverSocket;
|
private Socket serverSocket;
|
||||||
@@ -39,7 +39,7 @@ public class Client {
|
|||||||
try {
|
try {
|
||||||
out.writeInt(165313125);
|
out.writeInt(165313125);
|
||||||
out.flush();
|
out.flush();
|
||||||
success = in.readInt() == 200;
|
success = in.readBoolean();
|
||||||
if (success) {
|
if (success) {
|
||||||
out.writeUTF(name);
|
out.writeUTF(name);
|
||||||
out.flush();
|
out.flush();
|
||||||
@@ -54,11 +54,37 @@ public class Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void sendToServer(String message) {
|
public void sendToServer(String message) {
|
||||||
|
int availableBits = 0;
|
||||||
try {
|
try {
|
||||||
out.writeUTF(message);
|
out.writeUTF(message);
|
||||||
out.flush();
|
out.flush();
|
||||||
success = in.readInt() == 200;
|
boolean success = in.readBoolean();
|
||||||
clientLogger.printLog(String.format("Sent the message: %s", message), serverName, success, LogType.Output);
|
clientLogger.printLog(String.format("Sent the message: %s", message), serverName, success, LogType.Output);
|
||||||
|
if(in.available() > 0){
|
||||||
|
availableBits = in.available();
|
||||||
|
throw new Exception("More than just a boolean sent");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (Exception e) {
|
||||||
|
this.exitProcess();
|
||||||
|
this.printInputStream();
|
||||||
|
e.printStackTrace();
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printInputStream(){
|
||||||
|
try {
|
||||||
|
byte[] inputBytes = in.readAllBytes();
|
||||||
|
for (byte b: inputBytes) {
|
||||||
|
if (b == 1 || b == 0){
|
||||||
|
System.out.println(b == 1);
|
||||||
|
}
|
||||||
|
System.out.print(Character.toString(b));
|
||||||
|
}
|
||||||
|
System.out.println(Arrays.toString(inputBytes));
|
||||||
|
System.out.print("\n");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -124,7 +150,7 @@ public class Client {
|
|||||||
try {
|
try {
|
||||||
out.writeUTF("exit");
|
out.writeUTF("exit");
|
||||||
out.flush();
|
out.flush();
|
||||||
success = in.readInt()==200;
|
success = in.readBoolean();
|
||||||
clientLogger.printLog("Closing connection to server", serverName, success, LogType.Log);
|
clientLogger.printLog("Closing connection to server", serverName, success, LogType.Log);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -135,7 +161,7 @@ public class Client {
|
|||||||
try {
|
try {
|
||||||
out.writeUTF("reset");
|
out.writeUTF("reset");
|
||||||
out.flush();
|
out.flush();
|
||||||
success = in.readInt()==200;
|
success = in.readBoolean();
|
||||||
clientLogger.printLog("Resetting board", serverName, success, LogType.Log);
|
clientLogger.printLog("Resetting board", serverName, success, LogType.Log);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -150,8 +176,8 @@ public class Client {
|
|||||||
authorizedToMove = isAuthorizedToMove;
|
authorizedToMove = isAuthorizedToMove;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void printLog(String message, boolean success){
|
public void printLog(String message, boolean success, LogType logType){
|
||||||
clientLogger.printLog(message, success, LogType.Log);
|
clientLogger.printLog(message, success, logType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConnected(){
|
public boolean isConnected(){
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ public class Engine extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateTitle(String title) {
|
public void updateTitle(String title) {
|
||||||
System.out.println("title: " + title);
|
|
||||||
primaryStage.setTitle(title);
|
primaryStage.setTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,10 +86,6 @@ public class Engine extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void drawBoard(String gameState) {
|
public void drawBoard(String gameState) {
|
||||||
if (gameState.length() != 9) {
|
|
||||||
System.err.println("Wrong length of gameState string");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (gameState.equals("---------")) {
|
if (gameState.equals("---------")) {
|
||||||
grid.getChildren().clear();
|
grid.getChildren().clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ public class TicTacToe_Server {
|
|||||||
private HashMap<Integer, Socket> clients;
|
private HashMap<Integer, Socket> clients;
|
||||||
private HashMap<Socket, Integer> clientIds;
|
private HashMap<Socket, Integer> clientIds;
|
||||||
private HashMap<Socket, String> clientNames;
|
private HashMap<Socket, String> clientNames;
|
||||||
private HashMap<Socket, Boolean> clientMoveAuthorizations;
|
|
||||||
private HashMap<Socket, DataOutputStream> outstreams;
|
private HashMap<Socket, DataOutputStream> outstreams;
|
||||||
private HashMap<Socket, DataInputStream> instreams;
|
private HashMap<Socket, DataInputStream> instreams;
|
||||||
private TicTacToe_GameRules ticTacToe_gameRules;
|
private TicTacToe_GameRules ticTacToe_gameRules;
|
||||||
@@ -33,7 +32,6 @@ public class TicTacToe_Server {
|
|||||||
clients = new HashMap<>();
|
clients = new HashMap<>();
|
||||||
clientNames = new HashMap<>();
|
clientNames = new HashMap<>();
|
||||||
clientIds = new HashMap<>();
|
clientIds = new HashMap<>();
|
||||||
clientMoveAuthorizations = new HashMap<>();
|
|
||||||
outstreams = new HashMap<>();
|
outstreams = new HashMap<>();
|
||||||
instreams = new HashMap<>();
|
instreams = new HashMap<>();
|
||||||
ticTacToe_gameRules = new TicTacToe_GameRules();
|
ticTacToe_gameRules = new TicTacToe_GameRules();
|
||||||
@@ -48,10 +46,18 @@ public class TicTacToe_Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSingleServer() {
|
private boolean isSingleServer() {
|
||||||
serverLogger.printLog(""+ requiredConnections + (requiredConnections == 1), LogType.Error);
|
|
||||||
return requiredConnections == 1;
|
return requiredConnections == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean allClientsReady(){
|
||||||
|
for (boolean status: clientsReady) {
|
||||||
|
if (status == false){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void connectClients() {
|
public void connectClients() {
|
||||||
try {
|
try {
|
||||||
int id = 0;
|
int id = 0;
|
||||||
@@ -74,7 +80,7 @@ public class TicTacToe_Server {
|
|||||||
try {
|
try {
|
||||||
int handshakeValue = instreams.get(client).readInt();
|
int handshakeValue = instreams.get(client).readInt();
|
||||||
if (handshakeValue == 165313125) {
|
if (handshakeValue == 165313125) {
|
||||||
outstreams.get(client).writeInt(200);
|
outstreams.get(client).writeBoolean(true);
|
||||||
outstreams.get(client).flush();
|
outstreams.get(client).flush();
|
||||||
clientNames.put(client, instreams.get(client).readUTF());
|
clientNames.put(client, instreams.get(client).readUTF());
|
||||||
serverLogger.printLog(String.format("Client \"%s\" got connected", clientNames.get(client)), LogType.Log);
|
serverLogger.printLog(String.format("Client \"%s\" got connected", clientNames.get(client)), LogType.Log);
|
||||||
@@ -109,11 +115,12 @@ public class TicTacToe_Server {
|
|||||||
public String handleInput(Socket client) {
|
public String handleInput(Socket client) {
|
||||||
String message = null;
|
String message = null;
|
||||||
try {
|
try {
|
||||||
|
serverLogger.printLog("Waiting for input...", LogType.Log);
|
||||||
message = instreams.get(client).readUTF();
|
message = instreams.get(client).readUTF();
|
||||||
serverLogger.printLog(message, clientNames.get(client), LogType.Message);
|
serverLogger.printLog(message, clientNames.get(client), LogType.Message);
|
||||||
outstreams.get(client).writeInt(200);
|
outstreams.get(client).writeBoolean(true);
|
||||||
outstreams.get(client).flush();
|
outstreams.get(client).flush();
|
||||||
serverLogger.printLog("Sent verification code", "200", clientNames.get(client), LogType.Log);
|
serverLogger.printLog("Sent verification code", Boolean.toString(true), clientNames.get(client), LogType.Log);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -121,6 +128,11 @@ public class TicTacToe_Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void ticTacToe_gameloop() {
|
public void ticTacToe_gameloop() {
|
||||||
|
while (!allClientsReady()) {
|
||||||
|
for (Socket client : clients.values()) {
|
||||||
|
gameFlow(handleInput(client), client);
|
||||||
|
}
|
||||||
|
}
|
||||||
while (clients.size() == requiredConnections) {
|
while (clients.size() == requiredConnections) {
|
||||||
for (Socket client : clients.values()) {
|
for (Socket client : clients.values()) {
|
||||||
gameFlow(handleInput(client), client);
|
gameFlow(handleInput(client), client);
|
||||||
@@ -149,7 +161,25 @@ public class TicTacToe_Server {
|
|||||||
String position = handleInput(client);
|
String position = handleInput(client);
|
||||||
boolean moveAllowed = ticTacToe_gameRules.makeClientMove(position, clientIds.get(client));
|
boolean moveAllowed = ticTacToe_gameRules.makeClientMove(position, clientIds.get(client));
|
||||||
if (moveAllowed) {
|
if (moveAllowed) {
|
||||||
|
if (ticTacToe_gameRules.gameEnded()){
|
||||||
|
for (DataOutputStream outputStream : outstreams.values()) {
|
||||||
|
outputStream.writeUTF("gameEnded");
|
||||||
|
outputStream.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isSingleServer()) {
|
||||||
|
outstreams.get(clients.get(1 - clientIds.get(client))).writeUTF("opponentMove");
|
||||||
|
outstreams.get(clients.get(1 - clientIds.get(client))).flush();
|
||||||
sendGameState();
|
sendGameState();
|
||||||
|
} else {
|
||||||
|
sendGameState();
|
||||||
|
ticTacToe_gameRules.makeComputerMove();
|
||||||
|
serverLogger.printLog("Trigger computer move", LogType.Log);
|
||||||
|
outstreams.get(client).writeUTF("opponentMove");
|
||||||
|
outstreams.get(client).flush();
|
||||||
|
sendGameState();
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
outstreams.get(client).writeUTF("invalidInput");
|
outstreams.get(client).writeUTF("invalidInput");
|
||||||
outstreams.get(client).flush();
|
outstreams.get(client).flush();
|
||||||
@@ -160,32 +190,6 @@ public class TicTacToe_Server {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "opponentMove":
|
|
||||||
if (isSingleServer()) {
|
|
||||||
ticTacToe_gameRules.makeComputerMove();
|
|
||||||
serverLogger.printLog("Made computer move", LogType.Log);
|
|
||||||
} else {
|
|
||||||
//request move from other player
|
|
||||||
try {
|
|
||||||
outstreams.get(1-clientIds.get(client)).writeUTF("userInput");
|
|
||||||
outstreams.get(client).flush();
|
|
||||||
serverLogger.printLog("Requested opponent userInput", clientNames.get(1-clientIds.get(client)), LogType.Log);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sendGameState();
|
|
||||||
if (isSingleServer()) {
|
|
||||||
try {
|
|
||||||
outstreams.get(client).writeUTF("userInput");
|
|
||||||
outstreams.get(client).flush();
|
|
||||||
serverLogger.printLog("Requested userInput", LogType.Log);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "serverType":
|
case "serverType":
|
||||||
try {
|
try {
|
||||||
outstreams.get(client).writeBoolean(isSingleServer());
|
outstreams.get(client).writeBoolean(isSingleServer());
|
||||||
|
|||||||
Reference in New Issue
Block a user