Merge branch 'develop' into StartScreen

# Conflicts:
#	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/utilities/StreamParser.java
#	src/main/java/seng302/visualiser/GameClient.java
#	src/main/java/seng302/visualiser/controllers/LobbyController.java
This commit is contained in:
Michael Rausch
2017-08-16 14:31:14 +12:00
68 changed files with 2568 additions and 2366 deletions
@@ -9,7 +9,6 @@ import java.io.InputStreamReader;
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;
@@ -18,15 +17,28 @@ import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
import seng302.gameServer.server.messages.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import seng302.gameServer.server.messages.YachtEventCodeMessage;
import seng302.model.Player;
import seng302.model.Yacht;
import seng302.model.stream.packets.PacketType;
import seng302.model.stream.packets.StreamPacket;
import seng302.model.stream.xml.generator.Race;
import seng302.model.stream.xml.generator.Regatta;
import seng302.utilities.XMLGenerator;
import seng302.gameServer.server.messages.BoatAction;
import seng302.gameServer.server.messages.BoatLocationMessage;
import seng302.gameServer.server.messages.BoatSubMessage;
import seng302.gameServer.server.messages.ClientType;
import seng302.gameServer.server.messages.Message;
import seng302.gameServer.server.messages.RaceStatus;
import seng302.gameServer.server.messages.RaceStatusMessage;
import seng302.gameServer.server.messages.RaceType;
import seng302.gameServer.server.messages.RegistrationResponseMessage;
import seng302.gameServer.server.messages.RegistrationResponseStatus;
import seng302.gameServer.server.messages.XMLMessage;
import seng302.gameServer.server.messages.XMLMessageSubType;
import seng302.model.ServerYacht;
/**
* A class describing a single connection to a Client for the purposes of sending and receiving on
@@ -35,8 +47,15 @@ import seng302.utilities.XMLGenerator;
*/
public class ServerToClientThread implements Runnable, Observer {
private static final Integer LOG_LEVEL = 1;
private static final Integer MAX_ID_ATTEMPTS = 10;
/**
* Called to notify listeners when this thread receives a connection correctly.
*/
@FunctionalInterface
interface ConnectionListener {
void notifyConnection ();
}
private Logger logger = LoggerFactory.getLogger(ServerToClientThread.class);
private Thread thread;
@@ -46,11 +65,6 @@ public class ServerToClientThread implements Runnable, Observer {
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;
@@ -64,6 +78,10 @@ public class ServerToClientThread implements Runnable, Observer {
private static final int PREPATORY_TIME = 10 * -1000;
private List<ConnectionListener> connectionListeners = new ArrayList<>();
private ServerYacht yacht;
public ServerToClientThread(Socket socket) {
this.socket = socket;
seqNo = 0;
@@ -75,58 +93,51 @@ public class ServerToClientThread implements Runnable, Observer {
return;
}
thread = new Thread(this);
thread = new Thread(this, "ServerToClient");
thread.start();
}
private void setUpYacht(){
private void setUpPlayer(){
BufferedReader fn;
String fName = "";
BufferedReader ln;
String lName = "";
try {
is = socket.getInputStream();
os = socket.getOutputStream();
fn = new BufferedReader(
new InputStreamReader(
ServerToClientThread.class.getResourceAsStream(
"/server_config/CSV_Database_of_First_Names.csv"
)
)
);
List<String> all = fn.lines().collect(Collectors.toList());
fName = all.get(ThreadLocalRandom.current().nextInt(0, all.size()));
ln = new BufferedReader(
new InputStreamReader(
ServerToClientThread.class.getResourceAsStream(
"/server_config/CSV_Database_of_Last_Names.csv"
)
)
);
all = ln.lines().collect(Collectors.toList());
lName = all.get(ThreadLocalRandom.current().nextInt(0, all.size()));
} catch (IOException e) {
serverLog("IO error in server thread upon grabbing streams", 1);
}
Yacht yacht = new Yacht(
fn = new BufferedReader(
new InputStreamReader(
ServerToClientThread.class.getResourceAsStream(
"/server_config/CSV_Database_of_First_Names.csv"
)
)
);
List<String> all = fn.lines().collect(Collectors.toList());
fName = all.get(ThreadLocalRandom.current().nextInt(0, all.size()));
ln = new BufferedReader(
new InputStreamReader(
ServerToClientThread.class.getResourceAsStream(
"/server_config/CSV_Database_of_Last_Names.csv"
)
)
);
all = ln.lines().collect(Collectors.toList());
lName = all.get(ThreadLocalRandom.current().nextInt(0, all.size()));
ServerYacht yacht = new ServerYacht(
"Yacht", sourceId, sourceId.toString(), fName, fName + " " + lName, "NZ"
);
yacht.addObserver(this); // TODO: yacht can notify mark rounding message hyi25 13/8/17
GameState.addYacht(sourceId, yacht);
GameState.addPlayer(new Player(socket, yacht));
}
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();
if (arg != null) {
sendMessage((Message) arg);
} else {
sendSetupMessages();
}
}
private void completeRegistration(ClientType clientType) throws IOException {
@@ -148,12 +159,14 @@ public class ServerToClientThread implements Runnable, Observer {
this.clientType = clientType;
this.sourceId = sourceId;
setUpYacht();
isRegistered = true;
os.write(responseMessage.getBuffer());
sendSetupMessages();
setUpPlayer();
for (ConnectionListener listener : connectionListeners) {
listener.notifyConnection();
}
}
public void run() {
@@ -161,24 +174,9 @@ public class ServerToClientThread implements Runnable, Observer {
int sync2;
// TODO: 14/07/17 wmu16 - Work out how to fix this while loop
while (socket.isConnected()) {
try {
//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);
// 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();
@@ -198,7 +196,7 @@ public class ServerToClientThread implements Runnable, Observer {
//System.out.println("RECEIVED A PACKET");
switch (PacketType.assignPacketType(type, payload)) {
case BOAT_ACTION:
BoatActionType actionType = ServerPacketParser
BoatAction actionType = ServerPacketParser
.extractBoatAction(
new StreamPacket(type, payloadLength, timeStamp, payload));
GameState.updateBoat(sourceId, actionType);
@@ -212,7 +210,7 @@ public class ServerToClientThread implements Runnable, Observer {
break;
}
} else {
serverLog("Packet has been dropped", 1);
logger.warn("Packet has been dropped", 1);
}
}
} catch (Exception e) {
@@ -222,11 +220,11 @@ public class ServerToClientThread implements Runnable, Observer {
}
}
private void sendSetupMessages() {
public void sendSetupMessages() {
xml = new XMLGenerator();
Race race = new Race();
for (Yacht yacht : GameState.getYachts().values()) {
for (ServerYacht yacht : GameState.getYachts().values()) {
race.addBoat(yacht);
}
@@ -248,28 +246,6 @@ public class ServerToClientThread implements Runnable, Observer {
sendMessage(xmlMessage);
}
public void updateClient() {
sendRaceStatusMessage();
sendBoatLocationPackets();
updateClient = true;
}
/**
* Tries to confirm the connection just accepted.
* Sends ID, expects that ID echoed for confirmation,
* 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 Boolean threeWayHandshake(Integer id) {
return true;
}
private void closeSocket() {
try {
socket.close();
@@ -278,7 +254,6 @@ public class ServerToClientThread implements Runnable, Observer {
}
}
private int readByte() throws Exception {
int currentByte = -1;
try {
@@ -287,7 +262,7 @@ public class ServerToClientThread implements Runnable, Observer {
crcBuffer.write(currentByte);
} catch (IOException e) {
e.printStackTrace();
serverLog("Socket read failed", 1);
logger.warn("Socket read failed", 1);
}
if (currentByte == -1) {
throw new Exception();
@@ -316,7 +291,7 @@ public class ServerToClientThread implements Runnable, Observer {
//serverLog("Player " + sourceId + " side socket disconnected", 1);
return;
} catch (IOException e) {
serverLog("Message send failed", 1);
logger.warn("Message send failed", 1);
}
}
@@ -326,10 +301,9 @@ public class ServerToClientThread implements Runnable, Observer {
}
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());
public void sendBoatLocationPackets() {
ArrayList<ServerYacht> yachts = new ArrayList<>(GameState.getYachts().values());
for (ServerYacht yacht : yachts) {
BoatLocationMessage boatLocationMessage =
new BoatLocationMessage(
yacht.getSourceId(),
@@ -337,7 +311,7 @@ public class ServerToClientThread implements Runnable, Observer {
yacht.getLocation().getLat(),
yacht.getLocation().getLng(),
yacht.getHeading(),
yacht.getVelocity().longValue());
yacht.getCurrentVelocity().longValue());
sendMessage(boatLocationMessage);
}
@@ -347,64 +321,23 @@ public class ServerToClientThread implements Runnable, Observer {
return thread;
}
public void sendRaceStatusMessage() {
// variables taken from GameServerThread
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);
}
long timeTillStart = System.currentTimeMillis() - GameState.getStartTime();
if (GameState.getCurrentStage() == GameStages.LOBBYING) {
raceStatus = RaceStatus.PRESTART;
} else if (GameState.getCurrentStage() == GameStages.PRE_RACE) {
raceStatus = RaceStatus.PRESTART;
if (timeTillStart > WARNING_TIME) {
raceStatus = RaceStatus.WARNING;
}
if (timeTillStart > PREPATORY_TIME) {
raceStatus = RaceStatus.PREPARATORY;
}
} else {
raceStatus = RaceStatus.STARTED;
}
System.out.println("raceStatus.ger = " + raceStatus.getCode());
sendMessage(new RaceStatusMessage(1, raceStatus, GameState.getStartTime(), GameState.getWindDirection(),
GameState.getWindSpeedMMS().longValue(), GameState.getPlayers().size(),
RaceType.MATCH_RACE, 1, boatSubMessages));
if (GameState.getCurrentStage() == GameStages.PRE_RACE || GameState.getCurrentStage() == GameStages.LOBBYING){
Long raceStartTime = GameState.getStartTime();
sendMessage(new RaceStartStatusMessage(1, raceStartTime ,
1, RaceStartNotificationType.SET_RACE_START_TIME));
}
}
public Socket getSocket() {
return socket;
}
public ServerYacht getYacht() {
return yacht;
}
public void sendCollisionMessage(Integer yachtId) {
sendMessage(new YachtEventCodeMessage(yachtId));
}
public void addConnectionListener(ConnectionListener listener) {
connectionListeners.add(listener);
}
public void removeConnectionListener(ConnectionListener listener) {
connectionListeners.remove(listener);
}
}