mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 06:18:44 +00:00
Fixed sending wrong race xml when a player disconnected because xml is getting data from gamestate yacht but the yachts are not updated is player disconnect.
Heartbeat packet was sent out at wrong rate which cause the player disconnect detection to be slow. Heartbeat packet is send out every 200ms now. #story[1055] #pair[hyi25, zyt10]
This commit is contained in:
@@ -60,6 +60,10 @@ public class GameState {
|
|||||||
yachts.put(sourceId, yacht);
|
yachts.put(sourceId, yacht);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void removeYacht(Integer yachtId) {
|
||||||
|
yachts.remove(yachtId);
|
||||||
|
}
|
||||||
|
|
||||||
public static Boolean getIsRaceStarted() {
|
public static Boolean getIsRaceStarted() {
|
||||||
return isRaceStarted;
|
return isRaceStarted;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import java.util.*;
|
|||||||
* cannot be sent to a player
|
* cannot be sent to a player
|
||||||
*/
|
*/
|
||||||
public class HeartbeatThread extends Thread{
|
public class HeartbeatThread extends Thread{
|
||||||
private final int HEARTBEAT_PERIOD = 5000;
|
private final int HEARTBEAT_PERIOD = 200;
|
||||||
private ClientConnectionDelegate delegate;
|
private ClientConnectionDelegate delegate;
|
||||||
private Integer seqNum;
|
private Integer seqNum;
|
||||||
private Stack<Player> disconnectedPlayers;
|
private Stack<Player> disconnectedPlayers;
|
||||||
|
|||||||
@@ -137,11 +137,21 @@ public class MainServerThread extends Observable implements Runnable, PacketBuff
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void clientDisconnected(Player player) {
|
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);
|
GameState.removePlayer(player);
|
||||||
|
for (ServerToClientThread serverToClientThread : serverToClientThreads) {
|
||||||
|
if (serverToClientThread.getSocket() == player.getSocket()) {
|
||||||
|
this.deleteObserver(serverToClientThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
setChanged();
|
setChanged();
|
||||||
notifyObservers();
|
notifyObservers();
|
||||||
// sendXml();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startGame() {
|
public void startGame() {
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ import seng302.server.messages.XMLMessageSubType;
|
|||||||
import seng302.utilities.GeoPoint;
|
import seng302.utilities.GeoPoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class describing a single connection to a Client for the purposes of sending and receiving on its own thread.
|
* A class describing a single connection to a Client for the purposes of sending and receiving on
|
||||||
* All server threads created and owned by the server thread handler which can trigger client updates on its threads
|
* its own thread. All server threads created and owned by the server thread handler which can
|
||||||
* Created by wmu16 on 13/07/17.
|
* trigger client updates on its threads Created by wmu16 on 13/07/17.
|
||||||
*/
|
*/
|
||||||
public class ServerToClientThread implements Runnable, Observer {
|
public class ServerToClientThread implements Runnable, Observer {
|
||||||
|
|
||||||
@@ -58,12 +58,12 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
private OutputStream os;
|
private OutputStream os;
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
|
|
||||||
private ByteArrayOutputStream crcBuffer;
|
private ByteArrayOutputStream crcBuffer;
|
||||||
|
|
||||||
private Boolean userIdentified = false;
|
private Boolean userIdentified = false;
|
||||||
private Boolean connected = true;
|
private Boolean connected = true;
|
||||||
private Boolean updateClient = true;
|
private Boolean updateClient = true;
|
||||||
private Boolean initialisedRace = true;
|
// private Boolean initialisedRace = true;
|
||||||
|
|
||||||
private Integer seqNo;
|
private Integer seqNo;
|
||||||
private Integer sourceId;
|
private Integer sourceId;
|
||||||
@@ -97,9 +97,10 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serverLog(String message, int logLevel){
|
static void serverLog(String message, int logLevel) {
|
||||||
if(logLevel <= LOG_LEVEL){
|
if (logLevel <= LOG_LEVEL) {
|
||||||
System.out.println("[SERVER " + LocalDateTime.now().toLocalTime().toString() + "] " + message);
|
System.out.println(
|
||||||
|
"[SERVER " + LocalDateTime.now().toLocalTime().toString() + "] " + message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,83 +114,13 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
int sync2;
|
int sync2;
|
||||||
// TODO: 14/07/17 wmu16 - Work out how to fix this while loop
|
// TODO: 14/07/17 wmu16 - Work out how to fix this while loop
|
||||||
|
|
||||||
// used by ryan to simulate sending boats.xml
|
while (socket.isConnected()) {
|
||||||
// InputStream inputStream = getClass().getResourceAsStream("/server_config/boats1.xml");
|
|
||||||
// StringWriter writer = new StringWriter();
|
|
||||||
// try {
|
|
||||||
// IOUtils.copy(inputStream, writer);
|
|
||||||
// } catch (IOException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
// String xml = writer.toString();
|
|
||||||
// Message message = new XMLMessage(xml, XMLMessageSubType.BOAT, 0);
|
|
||||||
// sendMessage(message);
|
|
||||||
// System.out.println("[server] send message 1 " + message);
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// Thread.sleep(3000);
|
|
||||||
// } catch (InterruptedException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// inputStream = getClass().getResourceAsStream("/server_config/boats.xml");
|
|
||||||
// writer = new StringWriter();
|
|
||||||
// try {
|
|
||||||
// IOUtils.copy(inputStream, writer);
|
|
||||||
// } catch (IOException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
// xml = writer.toString();
|
|
||||||
// message = new XMLMessage(xml, XMLMessageSubType.BOAT, 0);
|
|
||||||
// sendMessage(message);
|
|
||||||
// System.out.println("[server] send message 2 " + message);
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// Thread.sleep(3000);
|
|
||||||
// } catch (InterruptedException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// inputStream = getClass().getResourceAsStream("/server_config/boats2.xml");
|
|
||||||
// writer = new StringWriter();
|
|
||||||
// try {
|
|
||||||
// IOUtils.copy(inputStream, writer);
|
|
||||||
// } catch (IOException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
// xml = writer.toString();
|
|
||||||
// message = new XMLMessage(xml, XMLMessageSubType.BOAT, 0);
|
|
||||||
// sendMessage(message);
|
|
||||||
// System.out.println("[server] send message 3 " + message);
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// Thread.sleep(3000);
|
|
||||||
// } catch (InterruptedException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// inputStream = getClass().getResourceAsStream("/server_config/boats.xml");
|
|
||||||
// writer = new StringWriter();
|
|
||||||
// try {
|
|
||||||
// IOUtils.copy(inputStream, writer);
|
|
||||||
// } catch (IOException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
// xml = writer.toString();
|
|
||||||
// message = new XMLMessage(xml, XMLMessageSubType.BOAT, 0);
|
|
||||||
// sendMessage(message);
|
|
||||||
// System.out.println("[server] send message 4 " + message);
|
|
||||||
// sendMessage(getRaceStatusMessage());
|
|
||||||
// System.out.println("sent race status");
|
|
||||||
//-------
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (initialisedRace) {
|
// if (initialisedRace) {
|
||||||
sendSetupMessages();
|
// sendSetupMessages();
|
||||||
initialisedRace = false;
|
// initialisedRace = false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
//Perform a write if it is time to as delegated by the MainServerThread
|
//Perform a write if it is time to as delegated by the MainServerThread
|
||||||
if (updateClient) {
|
if (updateClient) {
|
||||||
@@ -209,7 +140,7 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
sync1 = readByte();
|
sync1 = readByte();
|
||||||
sync2 = readByte();
|
sync2 = readByte();
|
||||||
//checking if it is the start of the packet
|
//checking if it is the start of the packet
|
||||||
if(sync1 == 0x47 && sync2 == 0x83) {
|
if (sync1 == 0x47 && sync2 == 0x83) {
|
||||||
int type = readByte();
|
int type = readByte();
|
||||||
//No. of milliseconds since Jan 1st 1970
|
//No. of milliseconds since Jan 1st 1970
|
||||||
long timeStamp = Message.bytesToLong(getBytes(6));
|
long timeStamp = Message.bytesToLong(getBytes(6));
|
||||||
@@ -249,7 +180,7 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
xml = new XMLGenerator();
|
xml = new XMLGenerator();
|
||||||
Race race = new Race();
|
Race race = new Race();
|
||||||
|
|
||||||
for (Yacht yacht : GameState.getYachts().values()){
|
for (Yacht yacht : GameState.getYachts().values()) {
|
||||||
race.addBoat(yacht);
|
race.addBoat(yacht);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,16 +188,18 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
xml.setRegatta(new Regatta("RaceVision Test Game", 57.6679590, 11.8503233));
|
xml.setRegatta(new Regatta("RaceVision Test Game", 57.6679590, 11.8503233));
|
||||||
xml.setRace(race);
|
xml.setRace(race);
|
||||||
|
|
||||||
XMLMessage xmlMessage = new XMLMessage(xml.getRegattaAsXml(), XMLMessageSubType.REGATTA, xml.getRegattaAsXml().length());
|
XMLMessage xmlMessage = new XMLMessage(xml.getRegattaAsXml(), XMLMessageSubType.REGATTA,
|
||||||
|
xml.getRegattaAsXml().length());
|
||||||
sendMessage(xmlMessage);
|
sendMessage(xmlMessage);
|
||||||
|
|
||||||
xmlMessage = new XMLMessage(xml.getBoatsAsXml(), XMLMessageSubType.BOAT, xml.getBoatsAsXml().length());
|
xmlMessage = new XMLMessage(xml.getBoatsAsXml(), XMLMessageSubType.BOAT,
|
||||||
|
xml.getBoatsAsXml().length());
|
||||||
sendMessage(xmlMessage);
|
sendMessage(xmlMessage);
|
||||||
|
|
||||||
xmlMessage = new XMLMessage(xml.getRaceAsXml(), XMLMessageSubType.RACE, xml.getRaceAsXml().length());
|
xmlMessage = new XMLMessage(xml.getRaceAsXml(), XMLMessageSubType.RACE,
|
||||||
|
xml.getRaceAsXml().length());
|
||||||
sendMessage(xmlMessage);
|
sendMessage(xmlMessage);
|
||||||
// System.out.println("Sent xml messages for " + thread.getName());
|
// System.out.println("Sent xml messages for " + thread.getName());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateClient() {
|
public void updateClient() {
|
||||||
@@ -281,6 +214,7 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
* if so, sends a confirmation packet back to that connection
|
* 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
|
* 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
|
* If not, close the socket and end the threads execution
|
||||||
|
*
|
||||||
* @param id the id to try and assign to the connection
|
* @param id the id to try and assign to the connection
|
||||||
* @return A boolean indicating if it was a successful handshake
|
* @return A boolean indicating if it was a successful handshake
|
||||||
*/
|
*/
|
||||||
@@ -300,7 +234,7 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
} else if (identificationAttempt > MAX_ID_ATTEMPTS) { //No response. not a client. tidy up and go home.
|
} else if (identificationAttempt > MAX_ID_ATTEMPTS) { //No response. not a client. tidy up and go home.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
identificationAttempt++;
|
identificationAttempt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -315,7 +249,6 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private int readByte() throws Exception {
|
private int readByte() throws Exception {
|
||||||
int currentByte = -1;
|
int currentByte = -1;
|
||||||
try {
|
try {
|
||||||
@@ -325,54 +258,55 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
if (currentByte == -1){
|
if (currentByte == -1) {
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
}
|
}
|
||||||
return currentByte;
|
return currentByte;
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getBytes(int n) throws Exception{
|
private byte[] getBytes(int n) throws Exception {
|
||||||
byte[] bytes = new byte[n];
|
byte[] bytes = new byte[n];
|
||||||
for (int i = 0; i < n; i++){
|
for (int i = 0; i < n; i++) {
|
||||||
bytes[i] = (byte) readByte();
|
bytes[i] = (byte) readByte();
|
||||||
}
|
}
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void skipBytes(long n) throws Exception{
|
private void skipBytes(long n) throws Exception {
|
||||||
for (int i=0; i < n; i++){
|
for (int i = 0; i < n; i++) {
|
||||||
readByte();
|
readByte();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(Message message){
|
public void sendMessage(Message message) {
|
||||||
try {
|
try {
|
||||||
os.write(message.getBuffer());
|
os.write(message.getBuffer());
|
||||||
} catch (SocketException e) {
|
} catch (SocketException e) {
|
||||||
serverLog("Player " + sourceId + " " + e.getMessage(), 0);
|
//serverLog("Player " + sourceId + " side socket disconnected", 0);
|
||||||
|
return;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getSeqNo(){
|
private int getSeqNo() {
|
||||||
seqNo++;
|
seqNo++;
|
||||||
return seqNo;
|
return seqNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void sendBoatLocationPackets(){
|
private void sendBoatLocationPackets() {
|
||||||
ArrayList<Yacht> yachts = new ArrayList<>(GameState.getYachts().values());
|
ArrayList<Yacht> yachts = new ArrayList<>(GameState.getYachts().values());
|
||||||
for (Yacht yacht: yachts){
|
for (Yacht yacht : yachts) {
|
||||||
// System.out.println("[SERVER] Lat: " + yacht.getLocation().getLat() + " Lon: " + yacht.getLocation().getLng());
|
// System.out.println("[SERVER] Lat: " + yacht.getLocation().getLat() + " Lon: " + yacht.getLocation().getLng());
|
||||||
BoatLocationMessage boatLocationMessage =
|
BoatLocationMessage boatLocationMessage =
|
||||||
new BoatLocationMessage(
|
new BoatLocationMessage(
|
||||||
yacht.getSourceId(),
|
yacht.getSourceId(),
|
||||||
getSeqNo(),
|
getSeqNo(),
|
||||||
yacht.getLocation().getLat(),
|
yacht.getLocation().getLat(),
|
||||||
yacht.getLocation().getLng(),
|
yacht.getLocation().getLng(),
|
||||||
yacht.getHeading(),
|
yacht.getHeading(),
|
||||||
(long) yacht.getVelocity());
|
(long) yacht.getVelocity());
|
||||||
|
|
||||||
sendMessage(boatLocationMessage);
|
sendMessage(boatLocationMessage);
|
||||||
}
|
}
|
||||||
@@ -382,38 +316,43 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendRaceStatusMessage(){
|
public void sendRaceStatusMessage() {
|
||||||
// variables taken from GameServerThread
|
// variables taken from GameServerThread
|
||||||
int TIME_TILL_RACE_START = 20*1000;
|
int TIME_TILL_RACE_START = 20 * 1000;
|
||||||
long startTime = System.currentTimeMillis() + TIME_TILL_RACE_START;
|
long startTime = System.currentTimeMillis() + TIME_TILL_RACE_START;
|
||||||
|
|
||||||
List<BoatSubMessage> boatSubMessages = new ArrayList<>();
|
List<BoatSubMessage> boatSubMessages = new ArrayList<>();
|
||||||
BoatStatus boatStatus;
|
BoatStatus boatStatus;
|
||||||
RaceStatus raceStatus;
|
RaceStatus raceStatus;
|
||||||
|
|
||||||
for (Player player : GameState.getPlayers()){
|
for (Player player : GameState.getPlayers()) {
|
||||||
Yacht y = player.getYacht();
|
Yacht y = player.getYacht();
|
||||||
|
|
||||||
if (GameState.getCurrentStage() == GameStages.PRE_RACE){
|
if (GameState.getCurrentStage() == GameStages.PRE_RACE) {
|
||||||
boatStatus = BoatStatus.PRESTART;
|
boatStatus = BoatStatus.PRESTART;
|
||||||
}
|
} else if (GameState.getCurrentStage() == GameStages.RACING) {
|
||||||
else if(GameState.getCurrentStage() == GameStages.RACING){
|
|
||||||
boatStatus = BoatStatus.RACING;
|
boatStatus = BoatStatus.RACING;
|
||||||
} else {
|
} else {
|
||||||
boatStatus = BoatStatus.UNDEFINED;
|
boatStatus = BoatStatus.UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
BoatSubMessage m = new BoatSubMessage(y.getSourceId(), boatStatus, 0, 0, 0, 1234l, 1234l);
|
BoatSubMessage m = new BoatSubMessage(y.getSourceId(), boatStatus, 0, 0, 0, 1234l,
|
||||||
|
1234l);
|
||||||
boatSubMessages.add(m);
|
boatSubMessages.add(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameState.getCurrentStage() == GameStages.RACING){
|
if (GameState.getCurrentStage() == GameStages.RACING) {
|
||||||
raceStatus = RaceStatus.STARTED;
|
raceStatus = RaceStatus.STARTED;
|
||||||
} else {
|
} else {
|
||||||
raceStatus = RaceStatus.WARNING;
|
raceStatus = RaceStatus.WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(new RaceStatusMessage(1, raceStatus, startTime, GameState.getWindDirection(),
|
sendMessage(new RaceStatusMessage(1, raceStatus, startTime, GameState.getWindDirection(),
|
||||||
GameState.getWindSpeed().longValue(), GameState.getPlayers().size(), RaceType.MATCH_RACE, 1, boatSubMessages));
|
GameState.getWindSpeed().longValue(), GameState.getPlayers().size(),
|
||||||
|
RaceType.MATCH_RACE, 1, boatSubMessages));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Socket getSocket() {
|
||||||
|
return socket;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user