Merge branch 'Story62_Creating_Game_Loop' into Merging_GameLoop_with_Broadcast

# Conflicts:
#	src/main/java/seng302/controllers/StartScreenController.java
#	src/main/java/seng302/gameServer/ServerListenThread.java
#	src/main/java/seng302/gameServer/ServerToClientThread.java
#	src/main/java/seng302/models/Yacht.java
This commit is contained in:
Kusal Ekanayake
2017-07-23 17:34:24 +12:00
7 changed files with 246 additions and 55 deletions
@@ -14,8 +14,8 @@ import seng302.server.messages.BoatActionType;
public class GameState {
private static Long previousUpdateTime;
private static Double windDirection = 0d;
private static Double windSpeed = 0d;
public static Double windDirection;
private static Double windSpeed;
private static String hostIpAddress;
private static List<Player> players;
@@ -24,6 +24,12 @@ public class GameState {
private static GameStages currentStage;
public GameState(String hostIpAddress) {
windDirection = 170d;
windSpeed = 0d;
yachts = new HashMap<>();
players = new ArrayList<>();
GameState.hostIpAddress = hostIpAddress;
players = new ArrayList<>();
currentStage = GameStages.LOBBYING;
@@ -49,8 +55,8 @@ public class GameState {
players.remove(player);
}
public static void addYacht(Integer sourceId, Yacht yatch) {
yachts.put(sourceId, yatch);
public static void addYacht(Integer sourceId, Yacht yacht) {
yachts.put(sourceId, yacht);
}
public static Boolean getIsRaceStarted() {
@@ -78,20 +84,39 @@ public class GameState {
}
public static void updateBoat(Integer sourceId, BoatActionType actionType) {
Yacht playerYacht = yachts.get(sourceId);
System.out.println("-----------------------");
switch (actionType) {
case VMG:
System.out.println("Snapping to VMG");
// TODO: 22/07/17 wmu16 - Add in the vmg calculation code here
break;
case SAILS_IN:
playerYacht.toggleSailIn();
System.out.println("Toggling Sails");
break;
case SAILS_OUT:
playerYacht.toggleSailIn();
System.out.println("Toggling Sails");
break;
case TACK_GYBE:
playerYacht.tackGybe(windDirection);
System.out.println("Tack/Gybe");
break;
case UPWIND:
playerYacht.turnUpwind();
System.out.println("Moving upwind");
break;
case DOWNWIND:
playerYacht.turnDownwind();
System.out.println("Moving downwind");
break;
}
System.out.println("-----------------------");
System.out.println("Heading: " + playerYacht.getHeading());
System.out.println("Sails are in: " + playerYacht.getSailIn());
System.out.println("-----------------------\n");
}
public static void update() {
@@ -102,4 +127,14 @@ public class GameState {
yacht.update(timeInterval);
}
}
/**
* Generates a new ID based off the size of current players + 1
* @return a playerID to be allocated to a new connetion
*/
public static Integer getUniquePlayerID() {
// TODO: 22/07/17 wmu16 - This may not be robust enough and may have to be improved on.
return yachts.size() + 1;
}
}
@@ -15,12 +15,14 @@ import java.util.concurrent.PriorityBlockingQueue;
* A class describing the overall server, which creates and collects server threads for each client
* Created by wmu16 on 13/07/17.
*/
public class MainServerThread extends Thread implements PacketBufferDelegate, ClientConnectionDelegate{
public class MainServerThread implements Runnable, PacketBufferDelegate, ClientConnectionDelegate{
private static final int PORT = 4950;
private static final Integer MAX_NUM_PLAYERS = 3;
private static final int LOG_LEVEL = 1;
private Thread thread;
private ServerSocket serverSocket = null;
private Socket socket;
private ArrayList<ServerToClientThread> serverToClientThreads = new ArrayList<>();
@@ -36,6 +38,9 @@ public class MainServerThread extends Thread implements PacketBufferDelegate, Cl
}
packetBuffer = new PriorityBlockingQueue<>();
thread = new Thread(this);
thread.start();
}
@@ -50,7 +55,7 @@ public class MainServerThread extends Thread implements PacketBufferDelegate, Cl
serverListenThread.start();
//You should handle interrupts in some way, so that the thread won't keep on forever if you exit the app.
while (!isInterrupted()) {
while (!thread.isInterrupted()) {
try {
Thread.sleep(1000 / 60); //60 times per second we should calculate the game state
} catch (InterruptedException e) {
@@ -123,7 +128,7 @@ public class MainServerThread extends Thread implements PacketBufferDelegate, Cl
*/
@Override
public void clientConnected(ServerToClientThread serverToClientThread) {
serverLog("Player Connected From " + serverToClientThread.getName(), 0);
serverLog("Player Connected From " + serverToClientThread.getThread().getName(), 0);
serverToClientThreads.add(serverToClientThread);
}
@@ -29,8 +29,6 @@ public class ServerListenThread extends Thread{
Socket thisClient = serverSocket.accept();
if (thisClient != null){
ServerToClientThread thisConnection = new ServerToClientThread(thisClient);
thisConnection.initialiseRace();
thisConnection.start();
delegate.clientConnected(thisConnection);
}
} catch (IOException e) {
@@ -29,9 +29,13 @@ import seng302.utilities.GeoPoint;
* All server threads created and owned by the server thread handler which can trigger client updates on its threads
* Created by wmu16 on 13/07/17.
*/
public class ServerToClientThread extends Thread {
public class ServerToClientThread implements Runnable {
private static final Integer LOG_LEVEL = 1;
private static final Integer MAX_ID_ATTEMPTS = 10;
private Thread thread;
private InputStream is;
private OutputStream os;
private Socket socket;
@@ -56,14 +60,31 @@ public class ServerToClientThread extends Thread {
} catch (IOException e) {
System.out.println("IO error in server thread upon grabbing streams");
}
// threeWayHandshake();
Random rand = new Random();
sourceId = rand.nextInt(1000);
//Attempt threeway handshake with connection
sourceId = GameState.getUniquePlayerID();
if (threeWayHandshake(sourceId)) {
serverLog("Successful handshake. Client allocated id: " + sourceId, 1);
GameState.addYacht(sourceId,
new Yacht("Kappa", "Kap", new GeoPoint(0.0, 0.0), 0.0));
GameState.addPlayer(new Player(socket)); //Is this neccesary???
} else {
serverLog("Unsuccessful handshake. Connection rejected", 1);
closeSocket();
return;
}
Yacht yacht = new Yacht("Yacht", sourceId, sourceId.toString(), "Kap", "Kappa", "NZ");
// Yacht yacht = new Yacht("Kappa", "Kap", new GeoPoint(57.6708220, 11.8321340), 90.0);
GameState.addYacht(sourceId, yacht);
GameState.addPlayer(new Player(socket, yacht));
seqNo = 0;
thread = new Thread(this);
thread.start();
}
static void serverLog(String message, int logLevel){
if(logLevel <= LOG_LEVEL){
System.out.println("[SERVER] " + message);
}
}
public void run() {
@@ -78,7 +99,7 @@ public class ServerToClientThread extends Thread {
sendSetupMessages();
initialisedRace = false;
}
//Perform a write if it is time to as delegated by the MainServerThread
if (updateClient) {
// TODO: 13/07/17 wmu16 - Write out game state - some function that would write all appropriate messages to this output stream
@@ -93,11 +114,9 @@ public class ServerToClientThread extends Thread {
updateClient = false;
}
crcBuffer = new ByteArrayOutputStream();
sync1 = readByte();
sync2 = readByte();
//checking if it is the start of the packet
if(sync1 == 0x47 && sync2 == 0x83) {
int type = readByte();
@@ -125,6 +144,7 @@ public class ServerToClientThread extends Thread {
}
}
} catch (Exception e) {
serverLog("ERROR OCCURRED, CLOSING SERVER CONNECTION: " + socket.getRemoteSocketAddress().toString(), 1);
e.printStackTrace();
closeSocket();
return;
@@ -167,28 +187,32 @@ public class ServerToClientThread extends Thread {
* if so, sends a confirmation packet back to that connection
* Creates a player instance with that ID and this thread and adds it to the GameState
* If not, close the socket and end the threads execution
* @param id the id to try and assign to the connection
* @return A boolean indicating if it was a successful handshake
*/
private void threeWayHandshake() {
// // TODO: 13/07/17 Finish using AC35
// Integer playerID = GameState.getUniquePlayerID();
// Integer confirmationID = null;
// Integer identificationAttempt = 0
// while (!userIdentified) {
// os.write(playerID); //Send out new ID looking for echo
// confirmationID = is.read();
// if (playerID == idConfirmation) { //ID is echoed back. Connection is a client
// os.write( some determined confirmation message ); //Confirm to client
// GameState.addPlayer(new Player(playerID, this)); //Create a player in game state for client
// userIdentified = true;
// } else if (identificationAttempt > MAX_ID_ATTEMPTS) { //No response. not a client. tidy up and go home.
// closeSocket();
// return;
// }
// identificationAttempt++;
// }
private Boolean threeWayHandshake(Integer id) {
Integer confirmationID = null;
Integer identificationAttempt = 0;
while (!userIdentified) {
try {
os.write(id); //Send out new ID looking for echo
confirmationID = is.read();
} catch (IOException e) {
e.printStackTrace();
}
if (id.equals(confirmationID)) { //ID is echoed back. Connection is a client
return true;
} else if (identificationAttempt > MAX_ID_ATTEMPTS) { //No response. not a client. tidy up and go home.
return false;
}
identificationAttempt++;
}
return true;
}
public void closeSocket() {
private void closeSocket() {
try {
socket.close();
} catch (IOException e) {
@@ -200,8 +224,8 @@ public class ServerToClientThread extends Thread {
public void initialiseRace(){
initialisedRace = true;
}
private int readByte() throws Exception {
int currentByte = -1;
try {
@@ -252,4 +276,9 @@ public class ServerToClientThread extends Thread {
sendMessage(boatLocationMessage);
}
}
public Thread getThread() {
return thread;
}
}