mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Merge branch 'develop' into story61_player_perspective
# Conflicts: # src/main/java/seng302/App.java # src/main/java/seng302/client/ClientPacketParser.java # src/main/java/seng302/controllers/Controller.java # src/main/java/seng302/controllers/RaceViewController.java # src/main/java/seng302/fxObjects/BoatAnnotations.java # src/main/java/seng302/gameServer/GameState.java # src/main/java/seng302/gameServer/MainServerThread.java # src/main/java/seng302/gameServer/ServerToClientThread.java # src/main/java/seng302/model/Boat.java # src/main/java/seng302/models/stream/XMLParser.java # src/main/java/seng302/visualiser/ClientToServerThread.java # src/main/java/seng302/visualiser/GameView.java # src/main/java/seng302/visualiser/controllers/FinishScreenViewController.java # src/main/java/seng302/visualiser/controllers/StartScreenController.java # src/main/java/seng302/visualiser/fxObjects/BoatObject.java # src/main/resources/views/LobbyView.fxml # src/main/resources/views/MainView.fxml
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
package seng302.gameServer;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import seng302.models.Player;
|
||||
import seng302.model.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import seng302.models.Yacht;
|
||||
import seng302.server.messages.BoatActionType;
|
||||
|
||||
/**
|
||||
* A Static class to hold information about the current state of the game (model)
|
||||
@@ -10,23 +14,38 @@ import java.util.ArrayList;
|
||||
*/
|
||||
public class GameState {
|
||||
|
||||
private static Long previousUpdateTime;
|
||||
public static Double windDirection;
|
||||
private static Double windSpeed;
|
||||
|
||||
private static String hostIpAddress;
|
||||
private static ArrayList<Player> players;
|
||||
private static List<Player> players;
|
||||
private static Map<Integer, Yacht> yachts;
|
||||
private static Boolean isRaceStarted;
|
||||
private static GameStages currentStage;
|
||||
|
||||
public GameState(String hostIpAddress) {
|
||||
windDirection = 170d;
|
||||
windSpeed = 10000d;
|
||||
yachts = new HashMap<>();
|
||||
players = new ArrayList<>();
|
||||
|
||||
|
||||
GameState.hostIpAddress = hostIpAddress;
|
||||
players = new ArrayList<>();
|
||||
currentStage = GameStages.LOBBYING;
|
||||
isRaceStarted = false;
|
||||
yachts = new HashMap<>();
|
||||
//set this when game stage changes to prerace
|
||||
previousUpdateTime = System.currentTimeMillis();
|
||||
yachts = new HashMap<>();
|
||||
}
|
||||
|
||||
public static String getHostIpAddress() {
|
||||
return hostIpAddress;
|
||||
}
|
||||
|
||||
public static ArrayList<Player> getPlayers() {
|
||||
public static List<Player> getPlayers() {
|
||||
return players;
|
||||
}
|
||||
|
||||
@@ -38,6 +57,14 @@ public class GameState {
|
||||
players.remove(player);
|
||||
}
|
||||
|
||||
public static void addYacht(Integer sourceId, Yacht yacht) {
|
||||
yachts.put(sourceId, yacht);
|
||||
}
|
||||
|
||||
public static void removeYacht(Integer yachtId) {
|
||||
yachts.remove(yachtId);
|
||||
}
|
||||
|
||||
public static Boolean getIsRaceStarted() {
|
||||
return isRaceStarted;
|
||||
}
|
||||
@@ -50,16 +77,72 @@ public class GameState {
|
||||
GameState.currentStage = currentStage;
|
||||
}
|
||||
|
||||
/**
|
||||
* This iterates through all players and updates each players info to its new state based on its current data
|
||||
*/
|
||||
private void update(){
|
||||
for(Player player : players) {
|
||||
// TODO: 10/07/17 wmu16 - Update all player info
|
||||
public static Double getWindDirection() {
|
||||
return windDirection;
|
||||
}
|
||||
|
||||
public static Double getWindSpeed() {
|
||||
return windSpeed;
|
||||
}
|
||||
|
||||
public static Map<Integer, Yacht> getYachts() {
|
||||
return yachts;
|
||||
}
|
||||
|
||||
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("Lat: " + playerYacht.getLocation().getLat());
|
||||
// System.out.println("Lng: " + playerYacht.getLocation().getLng());
|
||||
// System.out.println("-----------------------\n");
|
||||
}
|
||||
|
||||
public static void update() {
|
||||
|
||||
Long timeInterval = System.currentTimeMillis() - previousUpdateTime;
|
||||
previousUpdateTime = System.currentTimeMillis();
|
||||
for (Yacht yacht : yachts.values()) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.util.*;
|
||||
* cannot be sent to a player
|
||||
*/
|
||||
public class HeartbeatThread extends Thread{
|
||||
private final int HEARTBEAT_PERIOD = 5000;
|
||||
private final int HEARTBEAT_PERIOD = 200;
|
||||
private ClientConnectionDelegate delegate;
|
||||
private Integer seqNum;
|
||||
private Stack<Player> disconnectedPlayers;
|
||||
@@ -43,7 +43,7 @@ public class HeartbeatThread extends Thread{
|
||||
Message heartbeat = new Heartbeat(seqNum);
|
||||
|
||||
for (Player player : GameState.getPlayers()){
|
||||
if (!player.getSocket().isConnected()){
|
||||
if (!player.getSocket().isConnected()) {
|
||||
playerLostConnection(player);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package seng302.gameServer;
|
||||
|
||||
import seng302.model.Player;
|
||||
import seng302.model.stream.PacketBufferDelegate;
|
||||
import seng302.model.stream.parsers.StreamParser;
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Observable;
|
||||
import seng302.client.ClientPacketParser;
|
||||
import seng302.models.Player;
|
||||
import seng302.models.stream.PacketBufferDelegate;
|
||||
import seng302.models.stream.packets.StreamPacket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
@@ -15,12 +17,15 @@ 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 extends Observable implements Runnable, PacketBufferDelegate, ClientConnectionDelegate{
|
||||
|
||||
private static final int PORT = 4950;
|
||||
private static final int PORT = 4942;
|
||||
private static final Integer MAX_NUM_PLAYERS = 3;
|
||||
private static final Integer UPDATES_PER_SECOND = 2;
|
||||
private static final int LOG_LEVEL = 1;
|
||||
|
||||
private Thread thread;
|
||||
|
||||
private ServerSocket serverSocket = null;
|
||||
private Socket socket;
|
||||
private ArrayList<ServerToClientThread> serverToClientThreads = new ArrayList<>();
|
||||
@@ -32,10 +37,13 @@ public class MainServerThread extends Thread implements PacketBufferDelegate, Cl
|
||||
try {
|
||||
serverSocket = new ServerSocket(PORT);
|
||||
} catch (IOException e) {
|
||||
System.out.println("IO error in server thread handler upon trying to make new server socket");
|
||||
serverLog("IO error in server thread handler upon trying to make new server socket", 0);
|
||||
}
|
||||
|
||||
packetBuffer = new PriorityBlockingQueue<>();
|
||||
|
||||
thread = new Thread(this);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
|
||||
@@ -49,43 +57,40 @@ public class MainServerThread extends Thread implements PacketBufferDelegate, Cl
|
||||
heartbeatThread.start();
|
||||
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
|
||||
Thread.sleep(1000 / UPDATES_PER_SECOND);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
if (GameState.getCurrentStage() == GameStages.PRE_RACE) {
|
||||
GameState.update();
|
||||
}
|
||||
|
||||
//RACING
|
||||
if (GameState.getCurrentStage() == GameStages.RACING) {
|
||||
GameState.update();
|
||||
updateClients();
|
||||
}
|
||||
|
||||
|
||||
//FINISHED
|
||||
else if (GameState.getCurrentStage() == GameStages.FINISHED) {
|
||||
|
||||
}
|
||||
updateClients();
|
||||
|
||||
|
||||
while (!packetBuffer.isEmpty()){
|
||||
System.out.println("WHATUPPP");
|
||||
try {
|
||||
StreamPacket packet = packetBuffer.take();
|
||||
StreamParser.parsePacket(packet);
|
||||
ClientPacketParser.parsePacket(packet);
|
||||
} catch (InterruptedException e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("WHOOPSIES");
|
||||
|
||||
|
||||
// TODO: 14/07/17 wmu16 - Send out disconnect packet to clients
|
||||
try {
|
||||
serverSocket.close();
|
||||
@@ -95,7 +100,6 @@ public class MainServerThread extends Thread implements PacketBufferDelegate, Cl
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void updateClients() {
|
||||
for (ServerToClientThread serverToClientThread : serverToClientThreads) {
|
||||
serverToClientThread.updateClient();
|
||||
@@ -105,32 +109,26 @@ public class MainServerThread extends Thread implements PacketBufferDelegate, Cl
|
||||
|
||||
static void serverLog(String message, int logLevel){
|
||||
if(logLevel <= LOG_LEVEL){
|
||||
System.out.println("[SERVER] " + message);
|
||||
System.out.println("[SERVER " + LocalDateTime.now().toLocalTime().toString() + "] " + message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addToBuffer(StreamPacket streamPacket) {
|
||||
System.out.println("HEY HI");
|
||||
return packetBuffer.add(streamPacket);
|
||||
}
|
||||
|
||||
private void initializeRace(){
|
||||
for (ServerToClientThread serverToClientThread : serverToClientThreads) {
|
||||
serverToClientThread.updateClient();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A client has tried to connect to the server
|
||||
* @param serverToClientThread The player that connected
|
||||
*/
|
||||
@Override
|
||||
public void clientConnected(ServerToClientThread serverToClientThread) {
|
||||
serverLog("Player Connected From " + serverToClientThread.getName(), 0);
|
||||
serverLog("Player Connected From " + serverToClientThread.getThread().getName(), 0);
|
||||
serverToClientThreads.add(serverToClientThread);
|
||||
|
||||
this.addObserver(serverToClientThread);
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,9 +137,26 @@ public class MainServerThread extends Thread implements PacketBufferDelegate, Cl
|
||||
*/
|
||||
@Override
|
||||
public void clientDisconnected(Player player) {
|
||||
serverLog("Player disconnected", 0);
|
||||
try {
|
||||
player.getSocket().close();
|
||||
} catch (Exception e) {
|
||||
serverLog("Cannot disconnect the socket for the disconnected player.", 0);
|
||||
}
|
||||
serverLog("Player " + player.getYacht().getSourceId() + "'s socket disconnected", 0);
|
||||
GameState.removeYacht(player.getYacht().getSourceId());
|
||||
GameState.removePlayer(player);
|
||||
// sendXml();
|
||||
for (ServerToClientThread serverToClientThread : serverToClientThreads) {
|
||||
if (serverToClientThread.getSocket() == player.getSocket()) {
|
||||
this.deleteObserver(serverToClientThread);
|
||||
}
|
||||
}
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
public void startGame() {
|
||||
for (ServerToClientThread serverToClientThread : serverToClientThreads) {
|
||||
serverToClientThread.sendRaceStatusMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ public class ServerListenThread extends Thread{
|
||||
Socket thisClient = serverSocket.accept();
|
||||
if (thisClient != null){
|
||||
ServerToClientThread thisConnection = new ServerToClientThread(thisClient);
|
||||
thisConnection.start();
|
||||
delegate.clientConnected(thisConnection);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package seng302.gameServer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import seng302.models.stream.packets.StreamPacket;
|
||||
import seng302.server.messages.BoatActionType;
|
||||
|
||||
|
||||
public class ServerPacketParser {
|
||||
|
||||
|
||||
public static BoatActionType extractBoatAction(StreamPacket packet) {
|
||||
byte[] payload = packet.getPayload();
|
||||
int messageVersionNo = payload[0];
|
||||
long actionTypeValue = bytesToLong(Arrays.copyOfRange(payload, 0, 1));
|
||||
return BoatActionType.getType((int) actionTypeValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* takes an array of up to 7 bytes and returns a positive
|
||||
* long constructed from the input bytes
|
||||
*
|
||||
* @return a positive long if there is less than 7 bytes -1 otherwise
|
||||
*/
|
||||
private static long bytesToLong(byte[] bytes) {
|
||||
long partialLong = 0;
|
||||
int index = 0;
|
||||
for (byte b : bytes) {
|
||||
if (index > 6) {
|
||||
return -1;
|
||||
}
|
||||
partialLong = partialLong | (b & 0xFFL) << (index * 8);
|
||||
index++;
|
||||
}
|
||||
return partialLong;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,74 @@
|
||||
package seng302.gameServer;
|
||||
|
||||
import seng302.model.Player;
|
||||
import seng302.model.stream.parsers.StreamParser;
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
import seng302.server.messages.ChatterMessage;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Random;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.Checksum;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import seng302.models.Player;
|
||||
import seng302.models.Yacht;
|
||||
import seng302.models.stream.packets.PacketType;
|
||||
import seng302.models.stream.packets.StreamPacket;
|
||||
import seng302.models.xml.Race;
|
||||
import seng302.models.xml.Regatta;
|
||||
import seng302.models.xml.XMLGenerator;
|
||||
import seng302.server.messages.BoatActionType;
|
||||
import seng302.server.messages.BoatLocationMessage;
|
||||
import seng302.server.messages.BoatStatus;
|
||||
import seng302.server.messages.BoatSubMessage;
|
||||
import seng302.server.messages.Message;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.Checksum;
|
||||
import seng302.server.messages.RaceStatus;
|
||||
import seng302.server.messages.RaceStatusMessage;
|
||||
import seng302.server.messages.RaceType;
|
||||
import seng302.server.messages.XMLMessage;
|
||||
import seng302.server.messages.XMLMessageSubType;
|
||||
import seng302.server.messages.XMLMessage;
|
||||
import seng302.server.messages.XMLMessageSubType;
|
||||
import seng302.utilities.GeoPoint;
|
||||
|
||||
/**
|
||||
* A class describing a single connection to a Client for the purposes of sending and receiving on its own thread.
|
||||
* 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.
|
||||
* A class describing a single connection to a Client for the purposes of sending and receiving on
|
||||
* its own thread. 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, Observer {
|
||||
|
||||
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;
|
||||
|
||||
private ByteArrayOutputStream crcBuffer;
|
||||
private ByteArrayOutputStream crcBuffer;
|
||||
|
||||
private Boolean userIdentified = false;
|
||||
private Boolean connected = true;
|
||||
private Boolean updateClient = true;
|
||||
// private Boolean initialisedRace = true;
|
||||
|
||||
private Integer seqNo;
|
||||
private Integer sourceId;
|
||||
|
||||
private XMLGenerator xml;
|
||||
|
||||
public ServerToClientThread(Socket socket) {
|
||||
this.socket = socket;
|
||||
@@ -38,39 +78,69 @@ public class ServerToClientThread extends Thread {
|
||||
} catch (IOException e) {
|
||||
System.out.println("IO error in server thread upon grabbing streams");
|
||||
}
|
||||
// threeWayHandshake();
|
||||
GameState.addPlayer(new Player(socket));
|
||||
//Attempt threeway handshake with connection
|
||||
sourceId = GameState.getUniquePlayerID();
|
||||
if (threeWayHandshake(sourceId)) {
|
||||
serverLog("Successful handshake. Client allocated id: " + sourceId, 1);
|
||||
Yacht yacht = new Yacht("Yacht", sourceId, sourceId.toString(), "Kapa", "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));
|
||||
} else {
|
||||
serverLog("Unsuccessful handshake. Connection rejected", 1);
|
||||
closeSocket();
|
||||
return;
|
||||
}
|
||||
|
||||
seqNo = 0;
|
||||
thread = new Thread(this);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
static void serverLog(String message, int logLevel) {
|
||||
if (logLevel <= LOG_LEVEL) {
|
||||
System.out.println(
|
||||
"[SERVER " + LocalDateTime.now().toLocalTime().toString() + "] " + message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
sendSetupMessages();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int sync1;
|
||||
int sync2;
|
||||
// TODO: 14/07/17 wmu16 - Work out how to fix this while loop
|
||||
while(true) {
|
||||
//System.out.print(".");
|
||||
|
||||
while (socket.isConnected()) {
|
||||
|
||||
try {
|
||||
// if (initialisedRace) {
|
||||
// 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
|
||||
ChatterMessage chatterMessage = new ChatterMessage(4, 14, "Hello, it's me");
|
||||
sendMessage(chatterMessage);
|
||||
|
||||
// ChatterMessage chatterMessage = new ChatterMessage(4, 14, "Hello, it's me");
|
||||
// sendMessage(chatterMessage);
|
||||
// try {
|
||||
// GameState.outputState(os);
|
||||
// } catch (IOException e) {
|
||||
// System.out.println("IO error in server thread upon writing to output stream");
|
||||
// }
|
||||
// sendBoatLocationPackets();
|
||||
updateClient = false;
|
||||
}
|
||||
|
||||
|
||||
crcBuffer = new ByteArrayOutputStream();
|
||||
sync1 = readByte();
|
||||
sync2 = readByte();
|
||||
|
||||
//checking if it is the start of the packet
|
||||
if(sync1 == 0x47 && sync2 == 0x83) {
|
||||
if (sync1 == 0x47 && sync2 == 0x83) {
|
||||
int type = readByte();
|
||||
//No. of milliseconds since Jan 1st 1970
|
||||
long timeStamp = Message.bytesToLong(getBytes(6));
|
||||
@@ -83,14 +153,22 @@ public class ServerToClientThread extends Thread {
|
||||
long packetCrc = Message.bytesToLong(getBytes(4));
|
||||
if (computedCrc == packetCrc) {
|
||||
//System.out.println("RECEIVED A PACKET");
|
||||
StreamParser.parsePacket(new StreamPacket(type, payloadLength, timeStamp, payload));
|
||||
// TODO: 17/07/17 wmu16 - Fix this or maybe we dont need to go through the main server at all!?!?
|
||||
switch (PacketType.assignPacketType(type)) {
|
||||
case BOAT_ACTION:
|
||||
BoatActionType actionType = ServerPacketParser
|
||||
.extractBoatAction(
|
||||
new StreamPacket(type, payloadLength, timeStamp, payload));
|
||||
GameState.updateBoat(sourceId, actionType);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
System.err.println("Packet has been dropped");
|
||||
serverLog("Packet has been dropped", 1);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
// TODO: 24/07/17 zyt10 - fix a logic here when a client disconnected
|
||||
// serverLog("ERROR OCCURRED, CLOSING SERVER CONNECTION: " + socket.getRemoteSocketAddress().toString(), 1);
|
||||
// e.printStackTrace();
|
||||
closeSocket();
|
||||
return;
|
||||
}
|
||||
@@ -98,7 +176,34 @@ public class ServerToClientThread extends Thread {
|
||||
|
||||
}
|
||||
|
||||
private void sendSetupMessages() {
|
||||
xml = new XMLGenerator();
|
||||
Race race = new Race();
|
||||
|
||||
for (Yacht yacht : GameState.getYachts().values()) {
|
||||
race.addBoat(yacht);
|
||||
}
|
||||
|
||||
//@TODO calculate lat/lng values
|
||||
xml.setRegatta(new Regatta("RaceVision Test Game", 57.6679590, 11.8503233));
|
||||
xml.setRace(race);
|
||||
|
||||
XMLMessage xmlMessage = new XMLMessage(xml.getRegattaAsXml(), XMLMessageSubType.REGATTA,
|
||||
xml.getRegattaAsXml().length());
|
||||
sendMessage(xmlMessage);
|
||||
|
||||
xmlMessage = new XMLMessage(xml.getBoatsAsXml(), XMLMessageSubType.BOAT,
|
||||
xml.getBoatsAsXml().length());
|
||||
sendMessage(xmlMessage);
|
||||
|
||||
xmlMessage = new XMLMessage(xml.getRaceAsXml(), XMLMessageSubType.RACE,
|
||||
xml.getRaceAsXml().length());
|
||||
sendMessage(xmlMessage);
|
||||
// System.out.println("Sent xml messages for " + thread.getName());
|
||||
}
|
||||
|
||||
public void updateClient() {
|
||||
sendBoatLocationPackets();
|
||||
updateClient = true;
|
||||
}
|
||||
|
||||
@@ -109,28 +214,33 @@ 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) {
|
||||
@@ -148,31 +258,101 @@ public class ServerToClientThread extends Thread {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (currentByte == -1){
|
||||
if (currentByte == -1) {
|
||||
throw new Exception();
|
||||
}
|
||||
return currentByte;
|
||||
}
|
||||
|
||||
private byte[] getBytes(int n) throws Exception{
|
||||
private byte[] getBytes(int n) throws Exception {
|
||||
byte[] bytes = new byte[n];
|
||||
for (int i = 0; i < n; i++){
|
||||
for (int i = 0; i < n; i++) {
|
||||
bytes[i] = (byte) readByte();
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private void skipBytes(long n) throws Exception{
|
||||
for (int i=0; i < n; i++){
|
||||
private void skipBytes(long n) throws Exception {
|
||||
for (int i = 0; i < n; i++) {
|
||||
readByte();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessage(Message message){
|
||||
public void sendMessage(Message message) {
|
||||
try {
|
||||
os.write(message.getBuffer());
|
||||
} catch (SocketException e) {
|
||||
//serverLog("Player " + sourceId + " side socket disconnected", 0);
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private int getSeqNo() {
|
||||
seqNo++;
|
||||
return seqNo;
|
||||
}
|
||||
|
||||
|
||||
private void sendBoatLocationPackets() {
|
||||
ArrayList<Yacht> yachts = new ArrayList<>(GameState.getYachts().values());
|
||||
for (Yacht yacht : yachts) {
|
||||
// System.out.println("[SERVER] Lat: " + yacht.getLocation().getLat() + " Lon: " + yacht.getLocation().getLng());
|
||||
BoatLocationMessage boatLocationMessage =
|
||||
new BoatLocationMessage(
|
||||
yacht.getSourceId(),
|
||||
getSeqNo(),
|
||||
yacht.getLocation().getLat(),
|
||||
yacht.getLocation().getLng(),
|
||||
yacht.getHeading(),
|
||||
(long) yacht.getVelocity());
|
||||
|
||||
sendMessage(boatLocationMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public Thread getThread() {
|
||||
return thread;
|
||||
}
|
||||
|
||||
public void sendRaceStatusMessage() {
|
||||
// variables taken from GameServerThread
|
||||
int TIME_TILL_RACE_START = 20 * 1000;
|
||||
long startTime = System.currentTimeMillis() + TIME_TILL_RACE_START;
|
||||
|
||||
List<BoatSubMessage> boatSubMessages = new ArrayList<>();
|
||||
BoatStatus boatStatus;
|
||||
RaceStatus raceStatus;
|
||||
|
||||
for (Player player : GameState.getPlayers()) {
|
||||
Yacht y = player.getYacht();
|
||||
|
||||
if (GameState.getCurrentStage() == GameStages.PRE_RACE) {
|
||||
boatStatus = BoatStatus.PRESTART;
|
||||
} else if (GameState.getCurrentStage() == GameStages.RACING) {
|
||||
boatStatus = BoatStatus.RACING;
|
||||
} else {
|
||||
boatStatus = BoatStatus.UNDEFINED;
|
||||
}
|
||||
|
||||
BoatSubMessage m = new BoatSubMessage(y.getSourceId(), boatStatus, 0, 0, 0, 1234l,
|
||||
1234l);
|
||||
boatSubMessages.add(m);
|
||||
}
|
||||
|
||||
if (GameState.getCurrentStage() == GameStages.RACING) {
|
||||
raceStatus = RaceStatus.STARTED;
|
||||
} else {
|
||||
raceStatus = RaceStatus.WARNING;
|
||||
}
|
||||
|
||||
sendMessage(new RaceStatusMessage(1, raceStatus, startTime, GameState.getWindDirection(),
|
||||
GameState.getWindSpeed().longValue(), GameState.getPlayers().size(),
|
||||
RaceType.MATCH_RACE, 1, boatSubMessages));
|
||||
}
|
||||
|
||||
public Socket getSocket() {
|
||||
return socket;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user