Merge remote-tracking branch 'origin/Story62_Creating_Game_Loop' into Story62_Reading_Keystrokes

# Conflicts:
#	src/main/java/seng302/controllers/RaceViewController.java
#	src/main/java/seng302/gameServer/MainServerThread.java
#	src/main/java/seng302/gameServer/ServerToClientThread.java
This commit is contained in:
Zhi You Tan
2017-07-21 11:13:40 +12:00
18 changed files with 297 additions and 170 deletions
+2 -2
View File
@@ -6,8 +6,8 @@ import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import seng302.client.ClientPacketParser;
import seng302.models.PolarTable;
import seng302.models.stream.StreamParser;
import seng302.models.stream.StreamReceiver;
public class App extends Application {
@@ -26,7 +26,7 @@ public class App extends Application {
primaryStage.show();
primaryStage.setOnCloseRequest(e -> {
StreamParser.appClose();
ClientPacketParser.appClose();
StreamReceiver.noMoreBytes();
System.exit(0);
});
@@ -1,4 +1,4 @@
package seng302.models.stream;
package seng302.client;
import java.io.IOException;
@@ -22,6 +22,7 @@ import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import seng302.models.Yacht;
import seng302.models.mark.Mark;
import seng302.models.stream.XMLParser;
import seng302.models.stream.packets.BoatPositionPacket;
import seng302.models.stream.packets.StreamPacket;
@@ -31,7 +32,7 @@ import seng302.models.stream.packets.StreamPacket;
* that are threadsafe so the visualiser can always access the latest speed and position available
* Created by kre39 on 23/04/17.
*/
public class StreamParser{
public class ClientPacketParser {
public static ConcurrentHashMap<Long, PriorityBlockingQueue<BoatPositionPacket>> markLocations = new ConcurrentHashMap<>();
public static ConcurrentHashMap<Long, PriorityBlockingQueue<BoatPositionPacket>> boatLocations = new ConcurrentHashMap<>();
@@ -58,7 +59,7 @@ public class StreamParser{
/**
* Used to initialise the thread name and stream parser object so a thread can be executed
*/
public StreamParser() {
public ClientPacketParser() {
}
/**
* Looks at the type of the packet then sends it to the appropriate parser to extract the
@@ -106,9 +107,6 @@ public class StreamParser{
case AVG_WIND:
extractAvgWind(packet);
break;
case BOAT_ACTION:
extractBoatAction(packet);
break;
}
} catch (NullPointerException e) {
System.out.println("Error parsing packet");
@@ -491,27 +489,6 @@ public class StreamParser{
long speed4 = bytesToLong(Arrays.copyOfRange(payload, 21, 23));
}
private static void extractBoatAction(StreamPacket packet) {
byte[] payload = packet.getPayload();
int messageVersionNo = payload[0];
long actionType = bytesToLong(Arrays.copyOfRange(payload, 0, 1));
if (actionType == 1) {
System.out.println("VMG");
} else if (actionType == 2) {
System.out.println("SAILS IN");
} else if (actionType == 3) {
System.out.println("SAILS OUT");
} else if (actionType == 4) {
System.out.println("TACK/GYBE");
} else if (actionType == 5) {
System.out.println("UPWIND");
} else if (actionType == 6) {
System.out.println("DOWNWIND");
}
}
/**
* takes an array of up to 7 bytes and returns a positive
* long constructed from the input bytes
@@ -8,10 +8,8 @@ import java.net.Socket;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
import seng302.models.stream.StreamParser;
import seng302.models.stream.packets.StreamPacket;
import seng302.server.messages.BoatActionMessage;
import seng302.server.messages.BoatActionType;
import seng302.server.messages.Message;
/**
@@ -76,7 +74,8 @@ public class ClientToServerThread extends Thread {
long computedCrc = checksum.getValue();
long packetCrc = Message.bytesToLong(getBytes(4));
if (computedCrc == packetCrc) {
StreamParser.parsePacket(new StreamPacket(type, payloadLength, timeStamp, payload));
ClientPacketParser
.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!?!?
// packetBufferDelegate.addToBuffer(new StreamPacket(type, payloadLength, timeStamp, payload));
} else {
@@ -15,13 +15,13 @@ import javafx.scene.Group;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.text.Text;
import seng302.client.ClientPacketParser;
import seng302.fxObjects.BoatGroup;
import seng302.models.Colors;
import seng302.models.Yacht;
@@ -32,7 +32,6 @@ import seng302.models.mark.MarkType;
import seng302.models.mark.SingleMark;
import seng302.models.map.Boundary;
import seng302.models.map.CanvasMap;
import seng302.models.stream.StreamParser;
import seng302.models.stream.XMLParser;
import seng302.models.stream.XMLParser.RaceXMLObject.Limit;
import seng302.models.stream.XMLParser.RaceXMLObject.Participant;
@@ -156,13 +155,13 @@ public class CanvasController {
raceViewController.updateSparkLine();
}
updateGroups();
if (StreamParser.isRaceFinished()) {
if (ClientPacketParser.isRaceFinished()) {
this.stop();
}
lastTime = now;
}
}
if (StreamParser.isRaceFinished()) {
if (ClientPacketParser.isRaceFinished()) {
this.stop();
switchToFinishScreen();
}
@@ -231,7 +230,7 @@ public class CanvasController {
* in a compound mark etc..
*/
private void addRaceBorder() {
XMLParser.RaceXMLObject raceXMLObject = StreamParser.getXmlObject().getRaceXML();
XMLParser.RaceXMLObject raceXMLObject = ClientPacketParser.getXmlObject().getRaceXML();
ArrayList<Limit> courseLimits = raceXMLObject.getCourseLimit();
raceBorder.setStroke(new Color(0.0f, 0.0f, 0.74509807f, 1));
raceBorder.setStrokeWidth(3);
@@ -249,7 +248,7 @@ public class CanvasController {
for (BoatGroup boatGroup : boatGroups) {
// some raceObjects will have multiple ID's (for instance gate marks)
//checking if the current "ID" has any updates associated with it
if (StreamParser.boatLocations.containsKey(boatGroup.getRaceId())) {
if (ClientPacketParser.boatLocations.containsKey(boatGroup.getRaceId())) {
if (boatGroup.isStopped()) {
updateBoatGroup(boatGroup);
}
@@ -258,7 +257,7 @@ public class CanvasController {
}
for (MarkGroup markGroup : markGroups) {
for (Long id : markGroup.getRaceIds()) {
if (StreamParser.markLocations.containsKey(id)) {
if (ClientPacketParser.markLocations.containsKey(id)) {
updateMarkGroup(id, markGroup);
}
}
@@ -267,13 +266,14 @@ public class CanvasController {
}
private void checkForCourseChanges() {
if (StreamParser.isNewRaceXmlReceived()){
if (ClientPacketParser.isNewRaceXmlReceived()) {
addRaceBorder();
}
}
private void updateBoatGroup(BoatGroup boatGroup) {
PriorityBlockingQueue<BoatPositionPacket> movementQueue = StreamParser.boatLocations.get(boatGroup.getRaceId());
PriorityBlockingQueue<BoatPositionPacket> movementQueue = ClientPacketParser.boatLocations
.get(boatGroup.getRaceId());
// giving the movementQueue a 5 packet buffer to account for slightly out of order packets
if (movementQueue.size() > 0) {
try {
@@ -291,7 +291,8 @@ public class CanvasController {
}
void updateMarkGroup (long raceId, MarkGroup markGroup) {
PriorityBlockingQueue<BoatPositionPacket> movementQueue = StreamParser.markLocations.get(raceId);
PriorityBlockingQueue<BoatPositionPacket> movementQueue = ClientPacketParser.markLocations
.get(raceId);
if (movementQueue.size() > 0){
try {
BoatPositionPacket positionPacket = movementQueue.take();
@@ -307,12 +308,12 @@ public class CanvasController {
* Draws all the boats.
*/
private void initializeBoats() {
Map<Integer, Yacht> boats = StreamParser.getBoats();
Map<Integer, Yacht> boats = ClientPacketParser.getBoats();
Group wakes = new Group();
Group trails = new Group();
Group annotations = new Group();
ArrayList<Participant> participants = StreamParser.getXmlObject().getRaceXML()
ArrayList<Participant> participants = ClientPacketParser.getXmlObject().getRaceXML()
.getParticipants();
ArrayList<Integer> participantIDs = new ArrayList<>();
for (Participant p : participants) {
@@ -336,7 +337,8 @@ public class CanvasController {
}
private void initializeMarks() {
List<Mark> allMarks = StreamParser.getXmlObject().getRaceXML().getNonDupCompoundMarks();
List<Mark> allMarks = ClientPacketParser.getXmlObject().getRaceXML()
.getNonDupCompoundMarks();
for (Mark mark : allMarks) {
if (mark.getMarkType() == MarkType.SINGLE_MARK) {
SingleMark sMark = (SingleMark) mark;
@@ -402,7 +404,7 @@ public class CanvasController {
*/
private void fitMarksToCanvas() {
//Check is called once to avoid unnecessarily change the course limits once the race is running
StreamParser.isNewRaceXmlReceived();
ClientPacketParser.isNewRaceXmlReceived();
findMinMaxPoint();
double minLonToMaxLon = scaleRaceExtremities();
calculateReferencePointLocation(minLonToMaxLon);
@@ -418,7 +420,7 @@ public class CanvasController {
*/
private void findMinMaxPoint() {
List<Limit> sortedPoints = new ArrayList<>();
for (Limit limit : StreamParser.getXmlObject().getRaceXML().getCourseLimit()) {
for (Limit limit : ClientPacketParser.getXmlObject().getRaceXML().getCourseLimit()) {
sortedPoints.add(limit);
}
sortedPoints.sort(Comparator.comparingDouble(Limit::getLat));
@@ -9,7 +9,7 @@ import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import seng302.models.stream.StreamParser;
import seng302.client.ClientPacketParser;
import seng302.client.ClientToServerThread;
import seng302.server.messages.BoatActionMessage;
import seng302.server.messages.BoatActionType;
@@ -42,7 +42,7 @@ public class Controller implements Initializable {
contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString());
StartScreenController startScreenController = (StartScreenController) setContentPane("/views/StartScreenView.fxml");
startScreenController.setController(this);
StreamParser.boatLocations.clear();
ClientPacketParser.boatLocations.clear();
}
/** Handle the key-pressed event from the text field. */
@@ -15,8 +15,8 @@ import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import seng302.client.ClientPacketParser;
import seng302.models.Yacht;
import seng302.models.stream.StreamParser;
import seng302.models.stream.XMLParser.RaceXMLObject.Participant;
public class FinishScreenViewController implements Initializable {
@@ -59,7 +59,7 @@ public class FinishScreenViewController implements Initializable {
);
// check if the boat is racing
ArrayList<Participant> participants = StreamParser.getXmlObject().getRaceXML()
ArrayList<Participant> participants = ClientPacketParser.getXmlObject().getRaceXML()
.getParticipants();
ArrayList<Integer> participantIDs = new ArrayList<>();
for (Participant p : participants) {
@@ -67,7 +67,7 @@ public class FinishScreenViewController implements Initializable {
}
// add data to table
for (Yacht boat : StreamParser.getBoatsPos().values()) {
for (Yacht boat : ClientPacketParser.getBoatsPos().values()) {
if (participantIDs.contains(boat.getSourceID())) {
data.add(boat);
}
@@ -4,7 +4,6 @@ import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Point2D;
@@ -17,7 +16,6 @@ import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Slider;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
@@ -29,6 +27,7 @@ import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;
import javafx.util.StringConverter;
import seng302.client.ClientPacketParser;
import seng302.utilities.GeoUtility;
import seng302.controllers.annotations.Annotation;
import seng302.controllers.annotations.ImportantAnnotationController;
@@ -40,7 +39,6 @@ import seng302.models.*;
import seng302.models.mark.GateMark;
import seng302.models.mark.Mark;
import seng302.models.mark.SingleMark;
import seng302.models.stream.StreamParser;
import seng302.models.stream.XMLParser;
import java.io.IOException;
@@ -95,16 +93,16 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
raceSparkLine.getYAxis().setTranslateX(-5);
raceSparkLine.getYAxis().setAutoRanging(false);
sparklineYAxis.setTickMarkVisible(false);
//startingBoats = new ArrayList<>(StreamParser.getBoats().values());
startingBoats = new ArrayList<>(ClientPacketParser.getBoats().values());
//includedCanvasController.setup(this);
//includedCanvasController.initializeCanvas();
//initializeUpdateTimer();
//initialiseFPSCheckBox();
//initialiseAnnotationSlider();
//initialiseBoatSelectionComboBox();
//includedCanvasController.timer.start();
//selectAnnotationBtn.setOnAction(event -> loadSelectAnnotationView());
includedCanvasController.setup(this);
includedCanvasController.initializeCanvas();
initializeUpdateTimer();
initialiseFPSCheckBox();
initialiseAnnotationSlider();
initialiseBoatSelectionComboBox();
includedCanvasController.timer.start();
selectAnnotationBtn.setOnAction(event -> loadSelectAnnotationView());
}
@@ -305,7 +303,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
private Mark getNextMark(BoatGroup bg) {
Integer legNumber = bg.getBoat().getLegNumber();
List<XMLParser.RaceXMLObject.Corner> markSequence = StreamParser.getXmlObject().getRaceXML().getCompoundMarkSequence();
List<XMLParser.RaceXMLObject.Corner> markSequence = ClientPacketParser.getXmlObject()
.getRaceXML().getCompoundMarkSequence();
if (legNumber == 0) {
return null;
@@ -317,7 +316,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
if (legNumber + 2 == corner.getSeqID()) {
Integer thisCompoundMarkID = corner.getCompoundMarkID();
for (Mark mark : StreamParser.getXmlObject().getRaceXML().getAllCompoundMarks()) {
for (Mark mark : ClientPacketParser.getXmlObject().getRaceXML()
.getAllCompoundMarks()) {
if (mark.getCompoundMarkID() == thisCompoundMarkID) {
return mark;
}
@@ -330,11 +330,11 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
/**
* Updates the wind direction arrow and text as from info from the StreamParser
* Updates the wind direction arrow and text as from info from the ClientPacketParser
*/
private void updateWindDirection() {
windDirectionText.setText(String.format("%.1f°", StreamParser.getWindDirection()));
windArrowText.setRotate(StreamParser.getWindDirection());
windDirectionText.setText(String.format("%.1f°", ClientPacketParser.getWindDirection()));
windArrowText.setRotate(ClientPacketParser.getWindDirection());
}
@@ -342,7 +342,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
* Updates the clock for the race
*/
private void updateRaceTime() {
if (StreamParser.isRaceFinished()) {
if (ClientPacketParser.isRaceFinished()) {
timerLabel.setFill(Color.RED);
timerLabel.setText("Race Finished!");
} else {
@@ -352,18 +352,18 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
/**
* Grabs the boats currently in the race as from the StreamParser and sets them to be selectable
* Grabs the boats currently in the race as from the ClientPacketParser and sets them to be selectable
* in the boat selection combo box
*/
private void updateBoatSelectionComboBox() {
ObservableList<Yacht> observableBoats = FXCollections
.observableArrayList(StreamParser.getBoatsPos().values());
.observableArrayList(ClientPacketParser.getBoatsPos().values());
boatSelectionComboBox.setItems(observableBoats);
}
/**
* Updates the order of the boats as from the StreamParser and sets them in the boat order
* Updates the order of the boats as from the ClientPacketParser and sets them in the boat order
* section
*/
private void updateOrder() {
@@ -372,15 +372,15 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString());
// list of racing boat id
ArrayList<Participant> participants = StreamParser.getXmlObject().getRaceXML()
ArrayList<Participant> participants = ClientPacketParser.getXmlObject().getRaceXML()
.getParticipants();
ArrayList<Integer> participantIDs = new ArrayList<>();
for (Participant p : participants) {
participantIDs.add(p.getsourceID());
}
if (StreamParser.isRaceStarted()) {
for (Yacht boat : StreamParser.getBoatsPos().values()) {
if (ClientPacketParser.isRaceStarted()) {
for (Yacht boat : ClientPacketParser.getBoatsPos().values()) {
if (participantIDs.contains(boat.getSourceID())) { // check if the boat is racing
if (boat.getBoatStatus() == 3) { // 3 is finish status
Text textToAdd = new Text(boat.getPosition() + ". " +
@@ -398,7 +398,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
}
}
} else {
for (Yacht boat : StreamParser.getBoats().values()) {
for (Yacht boat : ClientPacketParser.getBoats().values()) {
if (participantIDs.contains(boat.getSourceID())) { // check if the boat is racing
Text textToAdd = new Text(boat.getPosition() + ". " +
boat.getShortName() + " ");
@@ -436,9 +436,11 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
Point2D markPoint2 = includedCanvasController.findScaledXY(singleMark2.getLatitude(), singleMark2.getLongitude());
HashMap<Double, Double> angleAndSpeed;
if (isUpwind) {
angleAndSpeed = PolarTable.getOptimalUpwindVMG(StreamParser.getWindSpeed());
angleAndSpeed = PolarTable
.getOptimalUpwindVMG(ClientPacketParser.getWindSpeed());
} else {
angleAndSpeed = PolarTable.getOptimalDownwindVMG(StreamParser.getWindSpeed());
angleAndSpeed = PolarTable
.getOptimalDownwindVMG(ClientPacketParser.getWindSpeed());
}
Double resultingAngle = angleAndSpeed.keySet().iterator().next();
@@ -450,11 +452,19 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
Line rightLayline = new Line();
Line leftLayline = new Line();
if (lineFuncResult == 1) {
rightLayline = makeRightLayline(markPoint2, 180 - resultingAngle, StreamParser.getWindDirection());
leftLayline = makeLeftLayline(markPoint1, 180 - resultingAngle, StreamParser.getWindDirection());
rightLayline = makeRightLayline(markPoint2, 180 - resultingAngle,
ClientPacketParser
.getWindDirection());
leftLayline = makeLeftLayline(markPoint1, 180 - resultingAngle,
ClientPacketParser
.getWindDirection());
} else if (lineFuncResult == -1) {
rightLayline = makeRightLayline(markPoint1, 180 - resultingAngle, StreamParser.getWindDirection());
leftLayline = makeLeftLayline(markPoint2, 180 - resultingAngle, StreamParser.getWindDirection());
rightLayline = makeRightLayline(markPoint1, 180 - resultingAngle,
ClientPacketParser
.getWindDirection());
leftLayline = makeLeftLayline(markPoint2, 180 - resultingAngle,
ClientPacketParser
.getWindDirection());
}
leftLayline.setStrokeWidth(0.5);
@@ -550,16 +560,16 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
private String getTimeSinceStartOfRace() {
String timerString = "0:00";
if (StreamParser.getTimeSinceStart() > 0) {
String timerMinute = Long.toString(StreamParser.getTimeSinceStart() / 60);
String timerSecond = Long.toString(StreamParser.getTimeSinceStart() % 60);
if (ClientPacketParser.getTimeSinceStart() > 0) {
String timerMinute = Long.toString(ClientPacketParser.getTimeSinceStart() / 60);
String timerSecond = Long.toString(ClientPacketParser.getTimeSinceStart() % 60);
if (timerSecond.length() == 1) {
timerSecond = "0" + timerSecond;
}
timerString = "-" + timerMinute + ":" + timerSecond;
} else {
String timerMinute = Long.toString(-1 * StreamParser.getTimeSinceStart() / 60);
String timerSecond = Long.toString(-1 * StreamParser.getTimeSinceStart() % 60);
String timerMinute = Long.toString(-1 * ClientPacketParser.getTimeSinceStart() / 60);
String timerSecond = Long.toString(-1 * ClientPacketParser.getTimeSinceStart() % 60);
if (timerSecond.length() == 1) {
timerSecond = "0" + timerSecond;
}
@@ -5,8 +5,8 @@ import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import seng302.client.ClientPacketParser;
import seng302.models.Yacht;
import seng302.models.stream.StreamParser;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@@ -88,7 +88,7 @@ public class BoatAnnotations extends Group{
if (boat.getTimeTillNext() != null) {
DateFormat format = new SimpleDateFormat("mm:ss");
String timeToNextMark = format
.format(boat.getTimeTillNext() - StreamParser.getCurrentTimeLong());
.format(boat.getTimeTillNext() - ClientPacketParser.getCurrentTimeLong());
estTimeToNextMarkObject.setText("Next mark: " + timeToNextMark);
} else {
estTimeToNextMarkObject.setText("Next mark: -");
@@ -97,7 +97,7 @@ public class BoatAnnotations extends Group{
if (boat.getMarkRoundTime() != null) {
DateFormat format = new SimpleDateFormat("mm:ss");
String elapsedTime = format
.format(StreamParser.getCurrentTimeLong() - boat.getMarkRoundTime());
.format(ClientPacketParser.getCurrentTimeLong() - boat.getMarkRoundTime());
legTimeObject.setText("Last mark: " + elapsedTime);
}else {
legTimeObject.setText("Last mark: - ");
@@ -9,13 +9,13 @@ import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Polygon;
import javafx.scene.transform.Rotate;
import seng302.client.ClientPacketParser;
import seng302.models.Yacht;
import seng302.utilities.GeoUtility;
import seng302.controllers.CanvasController;
import seng302.models.mark.GateMark;
import seng302.models.mark.Mark;
import seng302.models.mark.SingleMark;
import seng302.models.stream.StreamParser;
/**
* BoatGroup is a javafx group that by default contains a graphical objects for representing a 2
@@ -238,7 +238,7 @@ public class BoatGroup extends Group {
*/
public Boolean isUpwindLeg(CanvasController canvasController, Mark nextMark) {
Double windAngle = StreamParser.getWindDirection();
Double windAngle = ClientPacketParser.getWindDirection();
GateMark thisGateMark = (GateMark) nextMark;
SingleMark nextMark1 = thisGateMark.getSingleMark1();
SingleMark nextMark2 = thisGateMark.getSingleMark2();
+47 -11
View File
@@ -1,8 +1,13 @@
package seng302.gameServer;
import java.util.List;
import java.util.Map;
import java.util.Set;
import seng302.models.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,8 +15,13 @@ import java.util.ArrayList;
*/
public class GameState {
private static Long previousUpdateTime;
private static Double windDirection = 0d;
private static Double windSpeed = 0d;
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;
@@ -20,13 +30,15 @@ public class GameState {
players = new ArrayList<>();
currentStage = GameStages.LOBBYING;
isRaceStarted = false;
//set this when game stage changes to prerace
previousUpdateTime = System.currentTimeMillis();
}
public static String getHostIpAddress() {
return hostIpAddress;
}
public static ArrayList<Player> getPlayers() {
public static List<Player> getPlayers() {
return players;
}
@@ -38,6 +50,10 @@ public class GameState {
players.remove(player);
}
public static void addYacht(Integer sourceId, Yacht yatch) {
yachts.put(sourceId, yatch);
}
public static Boolean getIsRaceStarted() {
return isRaceStarted;
}
@@ -50,16 +66,36 @@ 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 void updateBoat(Integer sourceId, BoatActionType actionType) {
switch (actionType) {
case VMG:
break;
case SAILS_IN:
break;
case SAILS_OUT:
break;
case TACK_GYBE:
break;
case UPWIND:
break;
case DOWNWIND:
break;
}
}
public static void update() {
Long timeInterval = System.currentTimeMillis() - previousUpdateTime;
previousUpdateTime = System.currentTimeMillis();
for (Yacht yacht : yachts.values()) {
yacht.update(timeInterval);
}
}
}
@@ -1,8 +1,8 @@
package seng302.gameServer;
import seng302.client.ClientPacketParser;
import seng302.models.Player;
import seng302.models.stream.PacketBufferDelegate;
import seng302.models.stream.StreamParser;
import seng302.models.stream.packets.StreamPacket;
import java.io.IOException;
@@ -57,11 +57,12 @@ public class MainServerThread extends Thread implements PacketBufferDelegate, Cl
e.printStackTrace();
}
if (GameState.getCurrentStage() == GameStages.PRE_RACE) {
GameState.update();
}
//RACING
if (GameState.getCurrentStage() == GameStages.RACING) {
updateClients();
GameState.update();
}
@@ -71,12 +72,11 @@ public class MainServerThread extends Thread implements PacketBufferDelegate, Cl
}
updateClients();
while (!packetBuffer.isEmpty()){
System.out.println("WHATUPPP");
try {
StreamPacket packet = packetBuffer.take();
StreamParser.parsePacket(packet);
ClientPacketParser.parsePacket(packet);
} catch (InterruptedException e) {
continue;
}
@@ -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,18 +1,22 @@
package seng302.gameServer;
import seng302.gameServer.GameState;
import java.util.Random;
import seng302.client.ClientPacketParser;
import seng302.models.Player;
import seng302.models.stream.PacketBufferDelegate;
import seng302.models.stream.StreamParser;
import seng302.models.Yacht;
import seng302.models.stream.packets.PacketType;
import seng302.models.stream.packets.StreamPacket;
import seng302.server.messages.ChatterMessage;
import seng302.server.messages.Heartbeat;
import seng302.server.messages.BoatActionType;
import seng302.server.messages.Message;
import java.io.*;
import java.net.Socket;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
import seng302.utilities.GeoPoint;
/**
* A class describing a single connection to a Client for the purposes of sending and receiving on its own thread.
@@ -20,7 +24,6 @@ import java.util.zip.Checksum;
* Created by wmu16 on 13/07/17.
*/
public class ServerToClientThread extends Thread {
private static final Integer MAX_ID_ATTEMPTS = 10;
private InputStream is;
@@ -33,6 +36,8 @@ public class ServerToClientThread extends Thread {
private Boolean connected = true;
private Boolean updateClient = true;
private Integer sourceId;
public ServerToClientThread(Socket socket) {
this.socket = socket;
try {
@@ -43,6 +48,9 @@ public class ServerToClientThread extends Thread {
}
// threeWayHandshake();
GameState.addPlayer(new Player(socket));
Random rand = new Random();
sourceId = rand.nextInt(100000);
GameState.addYacht(sourceId, new Yacht("Kappa", "Kap", new GeoPoint(0.0, 0.0), 0.0));
}
public void run() {
@@ -86,8 +94,14 @@ 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");
}
+5 -2
View File
@@ -1,6 +1,9 @@
package seng302.models;
import java.io.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
@@ -140,7 +143,7 @@ public final class PolarTable {
}
private static Double getClosestMatch(Double thisWindSpeed) {
public static Double getClosestMatch(Double thisWindSpeed) {
ArrayList<Double> windValues = new ArrayList<>(polarTable.keySet());
+49 -32
View File
@@ -1,11 +1,14 @@
package seng302.models;
import javafx.scene.paint.Color;
import seng302.models.mark.Mark;
import seng302.controllers.RaceViewController;
import static seng302.utilities.GeoUtility.getGeoCoordinate;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Map;
import javafx.scene.paint.Color;
import seng302.controllers.RaceViewController;
import seng302.models.mark.Mark;
import seng302.utilities.GeoPoint;
/**
* Yacht class for the racing boat.
@@ -35,10 +38,9 @@ public class Yacht {
private Integer penaltiesServed;
private Long estimateTimeAtFinish;
private String position;
private Double lat;
private Double lon;
private Float heading;
private double velocity;
private GeoPoint location;
private Double heading;
private Double velocity;
private Long timeTillNext;
private Long markRoundTime;
@@ -52,8 +54,12 @@ public class Yacht {
*
* @param boatName Create a yacht object with name.
*/
public Yacht(String boatName) {
public Yacht(String boatName, String shortName, GeoPoint location, Double heading) {
this.boatName = boatName;
this.shortName = shortName;
this.location = location;
this.heading = heading;
this.velocity = 0.0;
}
/**
@@ -81,6 +87,41 @@ public class Yacht {
this.position = "-";
}
/**
* @param timeInterval since last update in milliseconds
*/
public void update(Long timeInterval) {
Double secondsElapsed = timeInterval / 1000000.0;
Double metersCovered = velocity * secondsElapsed;
location = getGeoCoordinate(location, heading, metersCovered);
}
/**
* Adjusts the yachts velocity based on the wind direction and speed from the polar table.
*
* @param windDir current wind Direction TODO: 20/07/17 ajm412: (TWA or AWA, not 100% sure?)
* @param windSpd current wind Speed
*/
public void updateYachtVelocity(Double windDir, Double windSpd) {
Double closestSpd = PolarTable.getClosestMatch(windSpd);
Map<Double, Double> polarsFromClosestSpd = PolarTable.getPolarTable().get(closestSpd);
Double closest = 0d;
Double closest_key = 0d;
for (Double key : polarsFromClosestSpd.keySet()) {
Double difference = Math.abs(key - windDir);
if (difference <= closest) {
closest = difference;
closest_key = key;
}
}
// System.out.println("Closest angle " + closest_key);
// System.out.println("WindDir " + windDir);
velocity = polarsFromClosestSpd.get(closest_key);
}
public String getBoatType() {
return boatType;
}
@@ -206,30 +247,6 @@ public class Yacht {
return nextMark;
}
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
public Double getLon() {
return lon;
}
public void setLon(Double lon) {
this.lon = lon;
}
public Float getHeading() {
return heading;
}
public void setHeading(Float heading) {
this.heading = heading;
}
@Override
public String toString() {
return boatName;
@@ -18,7 +18,7 @@ public class BoatActionMessage extends Message{
allocateBuffer();
writeHeaderToBuffer();
// Write message fields
putInt((int) BoatActionType.getBoatPacketType(actionType), 1);
putInt(actionType.getValue(), 1);
writeCRC();
rewind();
@@ -1,5 +1,8 @@
package seng302.server.messages;
import java.util.HashMap;
import java.util.Map;
/**
* Created by kre39 on 12/07/17.
*/
@@ -12,31 +15,24 @@ public enum BoatActionType {
UPWIND(5),
DOWNWIND(6);
private int type;
private final int type;
private static final Map<Integer, BoatActionType> intToTypeMap = new HashMap<>();
static {
for (BoatActionType type : BoatActionType.values()) {
intToTypeMap.put(type.getValue(), type);
}
}
BoatActionType(int type){
this.type = type;
}
public int getType(){
return this.type;
public static BoatActionType getType(int value) {
return intToTypeMap.get(value);
}
public static Short getBoatPacketType(BoatActionType type){
switch (type){
case VMG:
return 1;
case SAILS_IN:
return 2;
case SAILS_OUT:
return 3;
case TACK_GYBE:
return 4;
case UPWIND:
return 5;
case DOWNWIND:
return 6;
}
return 0;
public int getValue() {
return this.type;
}
}
@@ -0,0 +1,36 @@
package seng302.models;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import seng302.utilities.GeoPoint;
public class YachtTest {
Double windDir;
Double windSpd;
List<Yacht> yachts = new ArrayList<Yacht>();
@Before
public void setUp() {
PolarTable.parsePolarFile(getClass().getResourceAsStream("/config/acc_polars.csv"));
windDir = 90d;
windSpd = 10d;
yachts.add(new Yacht("Yacht 1", "Y1", new GeoPoint(-30.0, 20.0), 160.0));
yachts.add(new Yacht("Yacht 2", "Y2", new GeoPoint(-40.0, -20.0), 100.0));
yachts.add(new Yacht("Yacht 3", "Y3", new GeoPoint(-35.0, -15.5), 20.0));
}
@Test
public void testVelocityUpdate() {
for (Yacht yacht : yachts) {
yacht.updateYachtVelocity(windDir, windSpd);
System.out.println(yacht.getVelocity());
// TODO: 20/07/17 ajm412: add assertions.
}
}
}