Starting rework of client request protocol to allow multiplayer
This commit is contained in:
@@ -9,27 +9,28 @@ public class TicTacToe_Client {
|
|||||||
|
|
||||||
private Engine renderEngine;
|
private Engine renderEngine;
|
||||||
private Client client;
|
private Client client;
|
||||||
private boolean isSingleServer;
|
|
||||||
private static String clientName;
|
private static String clientName;
|
||||||
|
private boolean isPlayerOne;
|
||||||
|
|
||||||
public TicTacToe_Client(){
|
public TicTacToe_Client() {
|
||||||
renderEngine = Engine.waitForEngine();
|
renderEngine = Engine.waitForEngine();
|
||||||
}
|
|
||||||
|
|
||||||
private void ticTacToe_gameloop(){
|
|
||||||
//Setup
|
|
||||||
client = new Client("server", 2589, clientName);
|
client = new Client("server", 2589, clientName);
|
||||||
client.handshake();
|
client.handshake();
|
||||||
isSingleServer = client.getServerType();
|
isPlayerOne = client.isPlayerOne();
|
||||||
if (isSingleServer){
|
this.setWindowTitle(isPlayerOne);
|
||||||
this.setWindowTitle(client.isPlayerOne());
|
|
||||||
client.sendToServer("ready");
|
client.sendToServer("ready");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ticTacToe_gameloop() {
|
||||||
|
this.drawBoard(client.getGameState());
|
||||||
|
if (isPlayerOne){
|
||||||
|
this.userInput();
|
||||||
|
}
|
||||||
while (client.isConnected() && !renderEngine.isWindowClosed()) {
|
while (client.isConnected() && !renderEngine.isWindowClosed()) {
|
||||||
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.charAt(0) == 'x' || message.charAt(0) == '-' || message.charAt(0) == 'o') {
|
||||||
this.drawBoard(message);
|
this.drawBoard(message);
|
||||||
this.gameFlow("userInput");
|
|
||||||
}
|
}
|
||||||
//Handle everything else
|
//Handle everything else
|
||||||
else {
|
else {
|
||||||
@@ -38,18 +39,15 @@ public class TicTacToe_Client {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
client.exitProcess();
|
client.exitProcess();
|
||||||
} catch (Exception e){
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
this.setWindowTitle(client.isPlayerOne());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void gameFlow(String input){
|
private void gameFlow(String input) {
|
||||||
switch (input) {
|
switch (input) {
|
||||||
case "userInput":
|
case "userInput":
|
||||||
while(!renderEngine.isMouseClicked()){
|
while (!renderEngine.isMouseClicked()) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@@ -59,26 +57,20 @@ public class TicTacToe_Client {
|
|||||||
renderEngine.setMouseClicked(false);
|
renderEngine.setMouseClicked(false);
|
||||||
this.userInput();
|
this.userInput();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "invalidInput":
|
||||||
|
this.onInvalidInput();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void requestOpponentMove(){
|
||||||
|
client.sendToServer("opponentMove");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onGameEnd(){
|
||||||
|
|
||||||
private void userInput(){
|
|
||||||
//Send command
|
|
||||||
client.sendToServer("clientMove");
|
|
||||||
//Send position
|
|
||||||
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()) {
|
|
||||||
client.sendToServer("computerMove");
|
|
||||||
this.drawBoard(client.getResponse());
|
|
||||||
} else {
|
|
||||||
LinkedList<Integer> winCoordinates = new LinkedList<>();
|
LinkedList<Integer> winCoordinates = new LinkedList<>();
|
||||||
//Get winning fields
|
//Get winning fields
|
||||||
String response = client.getResponse();
|
String response = client.getResponse();
|
||||||
@@ -94,6 +86,27 @@ public class TicTacToe_Client {
|
|||||||
}
|
}
|
||||||
client.resetBoard();
|
client.resetBoard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onInvalidInput(){
|
||||||
|
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);
|
||||||
|
this.userInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void userInput() {
|
||||||
|
client.sendToServer("clientMove");
|
||||||
|
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 {
|
} else {
|
||||||
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;
|
||||||
@@ -110,8 +123,8 @@ public class TicTacToe_Client {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setWindowTitle(boolean isClientOne){
|
private void setWindowTitle(boolean isClientOne) {
|
||||||
if (isClientOne){
|
if (isClientOne) {
|
||||||
Platform.runLater(new Runnable() {
|
Platform.runLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -129,16 +142,16 @@ public class TicTacToe_Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
new Thread(){
|
new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run(){
|
public void run() {
|
||||||
javafx.application.Application.launch(Engine.class);
|
javafx.application.Application.launch(Engine.class);
|
||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
TicTacToe_Client test = new TicTacToe_Client();
|
TicTacToe_Client test = new TicTacToe_Client();
|
||||||
try{
|
try {
|
||||||
clientName = args[0];
|
clientName = args[0];
|
||||||
} catch (Exception e){
|
} catch (Exception e) {
|
||||||
clientName = "testing";
|
clientName = "testing";
|
||||||
}
|
}
|
||||||
test.ticTacToe_gameloop();
|
test.ticTacToe_gameloop();
|
||||||
|
|||||||
@@ -92,6 +92,16 @@ public class Client {
|
|||||||
return isClientOne;
|
return isClientOne;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getGameState(){
|
||||||
|
try {
|
||||||
|
out.writeUTF("gameState");
|
||||||
|
return this.getResponse();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return "---------";
|
||||||
|
}
|
||||||
|
|
||||||
public boolean getServerType(){
|
public boolean getServerType(){
|
||||||
this.sendToServer("serverType");
|
this.sendToServer("serverType");
|
||||||
boolean serverType = this.getBooleanResponse("isSingleServer");
|
boolean serverType = this.getBooleanResponse("isSingleServer");
|
||||||
|
|||||||
@@ -11,13 +11,12 @@ import java.io.IOException;
|
|||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class TicTacToe_Server {
|
public class TicTacToe_Server {
|
||||||
|
|
||||||
private ServerSocket serverSocket;
|
private ServerSocket serverSocket;
|
||||||
private HashMap<Integer, Socket> clients;
|
private HashMap<Integer, Socket> clients;
|
||||||
|
private HashMap<Socket, Integer> clientIds;
|
||||||
private HashMap<Socket, String> clientNames;
|
private HashMap<Socket, String> clientNames;
|
||||||
private HashMap<Socket, Boolean> clientMoveAuthorizations;
|
private HashMap<Socket, Boolean> clientMoveAuthorizations;
|
||||||
private HashMap<Socket, DataOutputStream> outstreams;
|
private HashMap<Socket, DataOutputStream> outstreams;
|
||||||
@@ -25,6 +24,7 @@ public class TicTacToe_Server {
|
|||||||
private TicTacToe_GameRules ticTacToe_gameRules;
|
private TicTacToe_GameRules ticTacToe_gameRules;
|
||||||
private ServerLogger serverLogger;
|
private ServerLogger serverLogger;
|
||||||
private int requiredConnections;
|
private int requiredConnections;
|
||||||
|
private boolean[] clientsReady;
|
||||||
|
|
||||||
|
|
||||||
public TicTacToe_Server(int port, int requiredConnections) {
|
public TicTacToe_Server(int port, int requiredConnections) {
|
||||||
@@ -32,12 +32,14 @@ public class TicTacToe_Server {
|
|||||||
serverSocket = new ServerSocket(port);
|
serverSocket = new ServerSocket(port);
|
||||||
clients = new HashMap<>();
|
clients = new HashMap<>();
|
||||||
clientNames = new HashMap<>();
|
clientNames = new HashMap<>();
|
||||||
|
clientIds = new HashMap<>();
|
||||||
clientMoveAuthorizations = 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();
|
||||||
serverLogger = new ServerLogger();
|
serverLogger = new ServerLogger();
|
||||||
this.requiredConnections = requiredConnections;
|
this.requiredConnections = requiredConnections;
|
||||||
|
clientsReady = new boolean[requiredConnections];
|
||||||
|
|
||||||
serverLogger.printLog("Server started successfully", LogType.Log);
|
serverLogger.printLog("Server started successfully", LogType.Log);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -46,6 +48,7 @@ public class TicTacToe_Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSingleServer() {
|
private boolean isSingleServer() {
|
||||||
|
serverLogger.printLog(""+ requiredConnections + (requiredConnections == 1), LogType.Error);
|
||||||
return requiredConnections == 1;
|
return requiredConnections == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,6 +59,7 @@ public class TicTacToe_Server {
|
|||||||
while (clients.size() < requiredConnections) {
|
while (clients.size() < requiredConnections) {
|
||||||
Socket momentaryClient = serverSocket.accept();
|
Socket momentaryClient = serverSocket.accept();
|
||||||
clients.put(id, momentaryClient);
|
clients.put(id, momentaryClient);
|
||||||
|
clientIds.put(clients.get(id), id);
|
||||||
outstreams.put(momentaryClient, new DataOutputStream(momentaryClient.getOutputStream()));
|
outstreams.put(momentaryClient, new DataOutputStream(momentaryClient.getOutputStream()));
|
||||||
instreams.put(momentaryClient, new DataInputStream(momentaryClient.getInputStream()));
|
instreams.put(momentaryClient, new DataInputStream(momentaryClient.getInputStream()));
|
||||||
id++;
|
id++;
|
||||||
@@ -102,7 +106,7 @@ public class TicTacToe_Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String handleInput(Socket client){
|
public String handleInput(Socket client) {
|
||||||
String message = null;
|
String message = null;
|
||||||
try {
|
try {
|
||||||
message = instreams.get(client).readUTF();
|
message = instreams.get(client).readUTF();
|
||||||
@@ -117,31 +121,22 @@ public class TicTacToe_Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void ticTacToe_gameloop() {
|
public void ticTacToe_gameloop() {
|
||||||
if (isSingleServer()) {
|
while (clients.size() == requiredConnections) {
|
||||||
Socket client = clients.get(0);
|
for (Socket client : clients.values()) {
|
||||||
//SingleServer GameLoop
|
gameFlow(handleInput(client), client);
|
||||||
while (!client.isClosed()) {
|
|
||||||
//Get instruction
|
|
||||||
this.gameFlow(handleInput(client), client);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//MultiServer GameLoop
|
|
||||||
gameFlow("gameState");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gameFlow(String input){
|
|
||||||
this.gameFlow(input, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gameFlow(String input, Socket client) {
|
public void gameFlow(String input, Socket client) {
|
||||||
switch (input) {
|
switch (input) {
|
||||||
case "ready":
|
case "ready":
|
||||||
if (isSingleServer()){
|
if (isSingleServer()) {
|
||||||
sendGameState();
|
sendGameState();
|
||||||
} else {
|
} else {
|
||||||
sendGameState(client);
|
sendGameState(client);
|
||||||
}
|
}
|
||||||
|
clientsReady[clientIds.get(client)] = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "gameState":
|
case "gameState":
|
||||||
@@ -152,14 +147,12 @@ public class TicTacToe_Server {
|
|||||||
try {
|
try {
|
||||||
//Get position (X|Y)
|
//Get position (X|Y)
|
||||||
String position = handleInput(client);
|
String position = handleInput(client);
|
||||||
boolean moveAllowed = ticTacToe_gameRules.makeClientMove(position);
|
boolean moveAllowed = ticTacToe_gameRules.makeClientMove(position, clientIds.get(client));
|
||||||
if (moveAllowed) {
|
if (moveAllowed) {
|
||||||
sendGameState();
|
sendGameState();
|
||||||
} else {
|
} else {
|
||||||
//send " "
|
outstreams.get(client).writeUTF("invalidInput");
|
||||||
outstreams.get(client).writeUTF("userInput");
|
|
||||||
outstreams.get(client).flush();
|
outstreams.get(client).flush();
|
||||||
serverLogger.printLog("Requested userInput", LogType.Log);
|
|
||||||
serverLogger.printLog(String.format("Move is not allowed!"), clientNames.get(client), LogType.Error);
|
serverLogger.printLog(String.format("Move is not allowed!"), clientNames.get(client), LogType.Error);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -167,9 +160,22 @@ public class TicTacToe_Server {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "computerMove":
|
case "opponentMove":
|
||||||
|
if (isSingleServer()) {
|
||||||
ticTacToe_gameRules.makeComputerMove();
|
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();
|
sendGameState();
|
||||||
|
if (isSingleServer()) {
|
||||||
try {
|
try {
|
||||||
outstreams.get(client).writeUTF("userInput");
|
outstreams.get(client).writeUTF("userInput");
|
||||||
outstreams.get(client).flush();
|
outstreams.get(client).flush();
|
||||||
@@ -177,11 +183,12 @@ public class TicTacToe_Server {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "serverType":
|
case "serverType":
|
||||||
try {
|
try {
|
||||||
outstreams.get(client).writeBoolean(true);
|
outstreams.get(client).writeBoolean(isSingleServer());
|
||||||
outstreams.get(client).flush();
|
outstreams.get(client).flush();
|
||||||
serverLogger.printLog("Sent serverType", Boolean.toString(true), clientNames.get(client), LogType.Log);
|
serverLogger.printLog("Sent serverType", Boolean.toString(true), clientNames.get(client), LogType.Log);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -190,20 +197,12 @@ public class TicTacToe_Server {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "isClientOne":
|
case "isClientOne":
|
||||||
for (Map.Entry<Integer, Socket> entry : clients.entrySet()) {
|
boolean isClientOne = clientIds.get(client) == 0;
|
||||||
if (Objects.equals(client, entry.getValue())) {
|
|
||||||
try {
|
try {
|
||||||
boolean isClientOne = entry.getKey() == 0;
|
|
||||||
outstreams.get(client).writeBoolean(isClientOne);
|
outstreams.get(client).writeBoolean(isClientOne);
|
||||||
outstreams.get(client).flush();
|
|
||||||
serverLogger.printLog("Sent isPlayerOne", Boolean.toString(isClientOne), clientNames.get(client), LogType.Log);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
serverLogger.printLog("Current client not in clients!", LogType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "gameEnded":
|
case "gameEnded":
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ public class TicTacToe_GameRules {
|
|||||||
Point startWin, endWin;
|
Point startWin, endWin;
|
||||||
|
|
||||||
public TicTacToe_GameRules(){
|
public TicTacToe_GameRules(){
|
||||||
gameState = "---------";
|
gameState = "o--x-o--x";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetGameState() {
|
public void resetGameState() {
|
||||||
@@ -34,13 +34,13 @@ public class TicTacToe_GameRules {
|
|||||||
board = this.convertToNumbers(gameState);
|
board = this.convertToNumbers(gameState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean makeClientMove(String input) {
|
public boolean makeClientMove(String input, int id) {
|
||||||
int column = Double.valueOf(input.split("\\|")[0]).intValue() / 300;
|
int column = Double.valueOf(input.split("\\|")[0]).intValue() / 300;
|
||||||
int row = Double.valueOf(input.split("\\|")[1]).intValue() / 300;
|
int row = Double.valueOf(input.split("\\|")[1]).intValue() / 300;
|
||||||
int index = column * 3 + row;
|
int index = column * 3 + row;
|
||||||
|
|
||||||
if (isLegalMove(column, row)) {
|
if (isLegalMove(column, row)) {
|
||||||
makeMoveOnBoard(index, 0);
|
makeMoveOnBoard(index, id);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -144,7 +144,6 @@ public class TicTacToe_GameRules {
|
|||||||
return horizontalWin() || verticalWin() || diagonalWin();
|
return horizontalWin() || verticalWin() || diagonalWin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Point[] getWinCoordinates(){
|
public Point[] getWinCoordinates(){
|
||||||
return new Point[]{startWin, endWin};
|
return new Point[]{startWin, endWin};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user