Fixed start line boat position algorithm. Fixed map limits and max players. Fixed concurrency bug on token creation and pickup. Fixed mini map arrows not rendering correctly for finish lines on maps other than the original. Removed System.gc() call after memory issues causing pauses could not be replicated.

This commit is contained in:
Calum
2017-10-11 00:13:55 +13:00
parent 057af2799a
commit 5dbc23866a
16 changed files with 63 additions and 84 deletions
+6 -12
View File
@@ -13,9 +13,6 @@ import org.slf4j.LoggerFactory;
import seng302.discoveryServer.DiscoveryServer; import seng302.discoveryServer.DiscoveryServer;
import seng302.visualiser.controllers.ViewManager; import seng302.visualiser.controllers.ViewManager;
import java.util.Timer;
import java.util.TimerTask;
public class App extends Application { public class App extends Application {
private static Logger logger = LoggerFactory.getLogger(App.class); private static Logger logger = LoggerFactory.getLogger(App.class);
@@ -95,15 +92,12 @@ public class App extends Application {
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
/* // new Timer().schedule(new TimerTask() {
* Do not trust Java to do garbage collection // @Override
*/ // public void run() {
new Timer().schedule(new TimerTask() { // System.gc();
@Override // }
public void run() { // }, 0, 1_000);
System.gc();
}
}, 0, 1_000);
try { try {
parseArgs(args); parseArgs(args);
@@ -11,6 +11,7 @@ import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArrayList;
import javafx.beans.property.ReadOnlyDoubleWrapper; import javafx.beans.property.ReadOnlyDoubleWrapper;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -98,7 +99,7 @@ public class GameState implements Runnable {
private static long startTime; private static long startTime;
private static Set<Mark> marks = new HashSet<>(); private static Set<Mark> marks = new HashSet<>();
private static List<Limit> courseLimit = new ArrayList<>(); private static List<Limit> courseLimit = new ArrayList<>();
private static Integer maxPlayers = 8; private static Integer maxPlayers = 12;
private static List<Token> tokensInPlay; private static List<Token> tokensInPlay;
private static RandomSpawn randomSpawn; private static RandomSpawn randomSpawn;
@@ -113,7 +114,7 @@ public class GameState implements Runnable {
windDirectionProperty.set(windDirection); windDirectionProperty.set(windDirection);
windSpeed = 10000d; windSpeed = 10000d;
yachts = new HashMap<>(); yachts = new HashMap<>();
tokensInPlay = new ArrayList<>(); tokensInPlay = new CopyOnWriteArrayList<>();
players = new ArrayList<>(); players = new ArrayList<>();
customizationFlag = false; customizationFlag = false;
playerHasLeftFlag = false; playerHasLeftFlag = false;
@@ -123,7 +124,7 @@ public class GameState implements Runnable {
newMessageListeners = new ArrayList<>(); newMessageListeners = new ArrayList<>();
resetStartTime(); resetStartTime();
//setCourseLimit("/server_config/race.xml");
new Thread(this, "GameState").start(); //Run the auto updates on the game state new Thread(this, "GameState").start(); //Run the auto updates on the game state
} }
@@ -284,13 +284,13 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
private void initialiseBoatPositions() { private void initialiseBoatPositions() {
final double DISTANCE_TO_START = 75d; final double DISTANCE_TO_START = 75d;
final double YACHT_SEPARATION = 20d; final double YACHT_SEPARATION = 35d;
//Length of start line //Length of start line
double startLineLength = GeoUtility.getDistance( double startLineLength = GeoUtility.getDistance(
GameState.getMarkOrder().getMarkOrder().get(0).getSubMark(1), GameState.getMarkOrder().getMarkOrder().get(0).getSubMark(1),
GameState.getMarkOrder().getMarkOrder().get(0).getSubMark(2) GameState.getMarkOrder().getMarkOrder().get(0).getSubMark(2)
); ) - YACHT_SEPARATION;
//How many yachts can fit along the start line //How many yachts can fit along the start line
int spacesAlongLine = (int) Math.round(startLineLength / YACHT_SEPARATION); int spacesAlongLine = (int) Math.round(startLineLength / YACHT_SEPARATION);
@@ -312,7 +312,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
GameState.getMarkOrder().getMarkOrder().get(1).getMidPoint() GameState.getMarkOrder().getMarkOrder().get(1).getMidPoint()
); );
GeoPoint startingPoint = GeoUtility.getGeoCoordinate( GeoPoint midPoint = GeoUtility.getGeoCoordinate(
GameState.getMarkOrder().getMarkOrder().get(0).getMidPoint(), GameState.getMarkOrder().getMarkOrder().get(0).getMidPoint(),
angleToStart, DISTANCE_TO_START angleToStart, DISTANCE_TO_START
); );
@@ -321,26 +321,24 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
Collections.shuffle(randomisedYachts); Collections.shuffle(randomisedYachts);
while (randomisedYachts.size() > 0) { while (randomisedYachts.size() > 0) {
int numYachtsInLine = int numYachts = spacesAlongLine > randomisedYachts.size() ? randomisedYachts.size() : spacesAlongLine;
spacesAlongLine > randomisedYachts.size() ? randomisedYachts.size() double yachtSpace = (numYachts - 1) * YACHT_SEPARATION / 2;
: spacesAlongLine;
double yachtSpace = numYachtsInLine * YACHT_SEPARATION / 2;
GeoPoint firstYachtPoint = GeoUtility.getGeoCoordinate( GeoPoint firstYachtPoint = GeoUtility.getGeoCoordinate(
startingPoint, startMarkToMarkAngle + 180, yachtSpace midPoint, startMarkToMarkAngle + 180, yachtSpace
); );
for (int i = 0; i < numYachtsInLine; i++) { for (int i = 0; i < numYachts; i++) {
randomisedYachts.get(0).setHeading(angleFromStart); randomisedYachts.get(0).setHeading(angleFromStart);
randomisedYachts.get(0).setLocation(firstYachtPoint); randomisedYachts.get(0).setLocation(firstYachtPoint);
firstYachtPoint = GeoUtility.getGeoCoordinate( firstYachtPoint = GeoUtility.getGeoCoordinate(
firstYachtPoint, startMarkToMarkAngle, yachtSpace firstYachtPoint, startMarkToMarkAngle, YACHT_SEPARATION
); );
randomisedYachts.remove(0); randomisedYachts.remove(0);
} }
startingPoint = GeoUtility.getGeoCoordinate( midPoint = GeoUtility.getGeoCoordinate(
startingPoint, angleToStart, DISTANCE_TO_START midPoint, angleToStart, YACHT_SEPARATION * 1.5
); );
} }
} }
@@ -206,7 +206,7 @@ public class MapPreview extends GameView {
} }
GeoPoint secondToLastMarkAv = new GeoPoint(averageLat / numMarks, averageLng / numMarks); GeoPoint secondToLastMarkAv = new GeoPoint(averageLat / numMarks, averageLng / numMarks);
for (Mark mark : course.get(course.size()-1).getMarks()) { for (Mark mark : course.get(course.size()-1).getMarks()) {
markerObjects.get(mark).addArrows( markerObjects.get(mark).addFinishArrow(
mark.getRoundingSide() == RoundingSide.STARBOARD ? MarkArrowFactory.RoundingSide.STARBOARD : MarkArrowFactory.RoundingSide.PORT, mark.getRoundingSide() == RoundingSide.STARBOARD ? MarkArrowFactory.RoundingSide.STARBOARD : MarkArrowFactory.RoundingSide.PORT,
GeoUtility.getBearing(secondToLastMarkAv, mark), GeoUtility.getBearing(secondToLastMarkAv, mark),
GeoUtility.getBearing(mark, mark) GeoUtility.getBearing(mark, mark)
@@ -5,14 +5,12 @@ import com.jfoenix.controls.JFXDialog;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.event.EventHandler;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
@@ -20,7 +18,6 @@ import javafx.geometry.Point3D;
import javafx.scene.Group; import javafx.scene.Group;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane; import javafx.scene.control.ScrollPane;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane; import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
@@ -43,7 +40,6 @@ import seng302.utilities.Sounds;
import seng302.visualiser.MapPreview; import seng302.visualiser.MapPreview;
import seng302.visualiser.controllers.cells.PlayerCell; import seng302.visualiser.controllers.cells.PlayerCell;
import seng302.visualiser.controllers.dialogs.BoatCustomizeController; import seng302.visualiser.controllers.dialogs.BoatCustomizeController;
import seng302.visualiser.controllers.dialogs.PopupDialogController;
import seng302.visualiser.controllers.dialogs.TokenInfoDialogController; import seng302.visualiser.controllers.dialogs.TokenInfoDialogController;
import seng302.visualiser.fxObjects.assets_3D.ModelFactory; import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
import seng302.visualiser.fxObjects.assets_3D.ModelType; import seng302.visualiser.fxObjects.assets_3D.ModelType;
@@ -357,8 +353,8 @@ public class LobbyController implements Initializable {
} }
/** /**
* * Updates the state of the race and changes the value
* @param raceState * @param raceState the new race state
*/ */
public void updateRaceState(RaceState raceState){ public void updateRaceState(RaceState raceState){
this.raceState = raceState; this.raceState = raceState;
@@ -86,16 +86,6 @@ public class MarkArrowFactory {
*/ */
public static Group constructEntryArrow (RoundingSide roundingSide, double angleOfEntry, public static Group constructEntryArrow (RoundingSide roundingSide, double angleOfEntry,
double angleOfExit, Paint colour) { double angleOfExit, Paint colour) {
// Check to see if the the angle around mark would take you inside of it. (less than 180)
// If so make interior angle.
if (roundingSide == RoundingSide.PORT && angleOfEntry < angleOfExit &&
Math.abs(angleOfExit - angleOfEntry) < 180) {
return makeInteriorAngle(roundingSide, angleOfExit, angleOfEntry, colour);
} else if (roundingSide == RoundingSide.STARBOARD && angleOfEntry > angleOfExit &&
-Math.abs(angleOfEntry - angleOfExit) > -180) {
return makeInteriorAngle(roundingSide, angleOfExit, angleOfEntry, colour);
}
//Create regular exit arrow. //Create regular exit arrow.
Group arrow = new Group(); Group arrow = new Group();
Group exitSection = constructExitArrow(roundingSide, angleOfExit, colour); Group exitSection = constructExitArrow(roundingSide, angleOfExit, colour);
@@ -132,7 +122,9 @@ public class MarkArrowFactory {
* @param colour colour of arrow * @param colour colour of arrow
* @return the arrow. * @return the arrow.
*/ */
private static Group makeInteriorAngle (RoundingSide roundingSide, double angleOfExit, double angleOfEntry, Paint colour) { public static Group constructInteriorArrow(RoundingSide roundingSide, double angleOfExit,
double angleOfEntry, Paint colour) {
Group arrow = new Group(); Group arrow = new Group();
Polygon lineSegment; Polygon lineSegment;
//Reverse angle of exit/entry to find position between them //Reverse angle of exit/entry to find position between them
@@ -16,6 +16,9 @@ public abstract class Marker extends Group{
protected int exitArrowIndex = 0; protected int exitArrowIndex = 0;
public abstract void addArrows(RoundingSide roundingSide, double entryAngle, double exitAngle); public abstract void addArrows(RoundingSide roundingSide, double entryAngle, double exitAngle);
public abstract void addFinishArrow(RoundingSide roundingSide, double entryAngle, double exitAngle);
/** /**
* Shows the next EnterArrow. Does nothing if there are no more enter arrows. Other arrows become hidden. * Shows the next EnterArrow. Does nothing if there are no more enter arrows. Other arrows become hidden.
*/ */
@@ -7,6 +7,7 @@ import javafx.scene.paint.Color;
import javafx.scene.paint.Paint; import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle; import javafx.scene.shape.Circle;
import seng302.visualiser.fxObjects.MarkArrowFactory; import seng302.visualiser.fxObjects.MarkArrowFactory;
import seng302.visualiser.fxObjects.MarkArrowFactory.RoundingSide;
import seng302.visualiser.fxObjects.Marker; import seng302.visualiser.fxObjects.Marker;
/** /**
@@ -57,6 +58,14 @@ public class Marker2D extends Marker {
); );
} }
@Override
public void addFinishArrow(RoundingSide roundingSide, double entryAngle, double exitAngle){
enterArrows.add(
MarkArrowFactory.constructInteriorArrow(roundingSide, entryAngle, exitAngle, Color.RED)
);
exitArrows.add(new Group());
}
/** /**
* Shows the next EnterArrow. Does nothing if there are no more enter arrows. Other arrows * Shows the next EnterArrow. Does nothing if there are no more enter arrows. Other arrows
* become hidden. * become hidden.
@@ -55,6 +55,16 @@ public class Marker3D extends Marker {
); );
} }
public void addFinishArrow(RoundingSide roundingSide, double entryAngle,
double exitAngle) {
enterArrows.add(
MarkArrowFactory.constructEntryArrow3D(roundingSide, entryAngle, ModelType.FINISH_ARROW).getAssets()
);
exitArrows.add(
MarkArrowFactory.constructExitArrow3D(roundingSide, exitAngle, ModelType.FINISH_ARROW).getAssets()
);
}
@Override @Override
protected void showArrow(List<Group> arrowList, int arrowListIndex) { protected void showArrow(List<Group> arrowList, int arrowListIndex) {
if (arrowListIndex < arrowList.size()) { if (arrowListIndex < arrowList.size()) {
+1 -1
View File
@@ -6,7 +6,7 @@
<CentralLat> 57.6679590 </CentralLat> <CentralLat> 57.6679590 </CentralLat>
<CentralLng> 11.8503233 </CentralLng> <CentralLng> 11.8503233 </CentralLng>
<MaxPlayers> 10 </MaxPlayers> <MaxPlayers> 8 </MaxPlayers>
<Marks> <Marks>
<CompoundMark CompoundMarkID="1"> <CompoundMark CompoundMarkID="1">
+1 -1
View File
@@ -6,7 +6,7 @@
<CentralLat> -14.6457 </CentralLat> <CentralLat> -14.6457 </CentralLat>
<CentralLng> 47.612855 </CentralLng> <CentralLng> 47.612855 </CentralLng>
<MaxPlayers> 5 </MaxPlayers> <MaxPlayers> 8 </MaxPlayers>
<Marks> <Marks>
<CompoundMark CompoundMarkID="1"> <CompoundMark CompoundMarkID="1">
+1 -1
View File
@@ -6,7 +6,7 @@
<CentralLat> 57.6679590 </CentralLat> <CentralLat> 57.6679590 </CentralLat>
<CentralLng> 11.8503233 </CentralLng> <CentralLng> 11.8503233 </CentralLng>
<MaxPlayers> 5 </MaxPlayers> <MaxPlayers> 8 </MaxPlayers>
<Marks> <Marks>
<CompoundMark CompoundMarkID="1"> <CompoundMark CompoundMarkID="1">
+1 -1
View File
@@ -6,7 +6,7 @@
<CentralLat>-15.67707</CentralLat> <CentralLat>-15.67707</CentralLat>
<CentralLng>49.79338</CentralLng> <CentralLng>49.79338</CentralLng>
<MaxPlayers>10</MaxPlayers> <MaxPlayers> 5 </MaxPlayers>
<Marks> <Marks>
<CompoundMark CompoundMarkID="1"> <CompoundMark CompoundMarkID="1">
+8 -8
View File
@@ -6,7 +6,7 @@
<CentralLat>-36.80008</CentralLat> <CentralLat>-36.80008</CentralLat>
<CentralLng>175.012225</CentralLng> <CentralLng>175.012225</CentralLng>
<MaxPlayers>10</MaxPlayers> <MaxPlayers> 6 </MaxPlayers>
<Marks> <Marks>
<CompoundMark CompoundMarkID="1"> <CompoundMark CompoundMarkID="1">
@@ -32,13 +32,13 @@
<Course> <Course>
<OpeningSegment> <OpeningSegment>
<Corner CompoundMarkID="1" Rounding="PS"/> <Corner CompoundMarkID="1" Rounding="SP"/>
<Corner CompoundMarkID="2" Rounding="P"/> <Corner CompoundMarkID="2" Rounding="P"/>
</OpeningSegment> </OpeningSegment>
<RepeatingSegment> <RepeatingSegment>
<Corner CompoundMarkID="3" Rounding="SP"/> <Corner CompoundMarkID="3" Rounding="PS"/>
<Corner CompoundMarkID="4" Rounding="PS"/> <Corner CompoundMarkID="4" Rounding="SP"/>
</RepeatingSegment> </RepeatingSegment>
<ClosingSegment> <ClosingSegment>
@@ -47,14 +47,14 @@
</Course> </Course>
<CourseLimit> <CourseLimit>
<Limit Lat="-36.7938" Lng="175.01194"/> <Limit Lat="-36.79350" Lng="175.01194"/>
<Limit Lat="-36.79411" Lng="175.01555"/> <Limit Lat="-36.79411" Lng="175.01455"/>
<Limit Lat="-36.79765" Lng="175.01898"/> <Limit Lat="-36.79765" Lng="175.01898"/>
<Limit Lat="-36.79909" Lng="175.02149"/> <Limit Lat="-36.79909" Lng="175.02149"/>
<Limit Lat="-36.80163" Lng="175.02014"/> <Limit Lat="-36.80163" Lng="175.02014"/>
<Limit Lat="-36.80292" Lng="175.0175"/> <Limit Lat="-36.80292" Lng="175.0175"/>
<Limit Lat="-36.80325" Lng="175.01008"/> <Limit Lat="-36.80295" Lng="175.01008"/>
<Limit Lat="-36.80107" Lng="175.0089"/> <Limit Lat="-36.80107" Lng="175.00960"/>
<Limit Lat="-36.79567" Lng="175.00961"/> <Limit Lat="-36.79567" Lng="175.00961"/>
</CourseLimit> </CourseLimit>
+2 -15
View File
@@ -1,25 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import java.net.*?>
<?import javafx.scene.*?>
<?import com.jfoenix.controls.*?>
<?import java.lang.*?> <?import java.lang.*?>
<?import java.net.*?>
<?import com.jfoenix.controls.*?>
<?import javafx.geometry.*?> <?import javafx.geometry.*?>
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?> <?import javafx.scene.text.*?>
<?import com.jfoenix.controls.JFXButton?>
<?import java.lang.String?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<StackPane fx:id="serverListMainStackPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.LobbyController"> <StackPane fx:id="serverListMainStackPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.LobbyController">
<children> <children>
+1 -12
View File
@@ -6,18 +6,7 @@
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?> <?import javafx.scene.text.*?>
<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXTextField?>
<?import java.lang.String?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<StackPane fx:id="serverListMainStackPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.ServerListController"> <StackPane fx:id="serverListMainStackPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.ServerListController">
<children> <children>