mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Compare commits
90 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e5af7bf666 | |||
| 85ca91db96 | |||
| 2eb7e603f1 | |||
| 658a342118 | |||
| ea52977aeb | |||
| 10fa51a105 | |||
| c54a1e141d | |||
| 6d51ea3574 | |||
| d56468e4aa | |||
| 5248921576 | |||
| 330ccd272d | |||
| 4b7dfe38c4 | |||
| ab07c7f298 | |||
| b5076bc976 | |||
| 2dcdd1c248 | |||
| 9b00f76907 | |||
| f11c457d28 | |||
| 9e4fa30787 | |||
| 99ce4fa11d | |||
| 69d1fa9488 | |||
| 66e6a8a2a4 | |||
| 8ba44d7476 | |||
| dd43097677 | |||
| 1a53579317 | |||
| 132a729758 | |||
| 2e7487fdfc | |||
| 1bd4db73cd | |||
| 7a4cdbe0c9 | |||
| 7027de80c4 | |||
| 0211f2df38 | |||
| dba5a5680f | |||
| 5c50e77efa | |||
| 0e93be7b36 | |||
| 191b818e38 | |||
| 00b09997b0 | |||
| d250c635d8 | |||
| 376c4d25a8 | |||
| e66abb4340 | |||
| a19e191684 | |||
| 29b97a194d | |||
| 8a0ad8d6a9 | |||
| 19db6668da | |||
| 44275aec04 | |||
| 64245833cd | |||
| aa0149b9a7 | |||
| f6b41f0513 | |||
| 8dfdb228e9 | |||
| 1042817e4e | |||
| 066557584f | |||
| 4011295b8b | |||
| 78259f8e33 | |||
| c47e5b1450 | |||
| 0a885dd8fd | |||
| e9b50038a9 | |||
| 364264377a | |||
| 9112183ac3 | |||
| 8c7f9a878d | |||
| ecb3d4ecbf | |||
| e61b6d50a1 | |||
| 957821f1f2 | |||
| 061e49bab9 | |||
| 094eb4c1cf | |||
| a3c555d5fe | |||
| 607acff7c6 | |||
| 22fdf1e4ac | |||
| da8c91f5c1 | |||
| 52dc7a956d | |||
| 9f64b2380d | |||
| b05580f018 | |||
| c20c6fb264 | |||
| faeece27ff | |||
| c4a6113f6c | |||
| 307e79ecfc | |||
| 7d8a6afa5f | |||
| ea0be5e952 | |||
| 3be8cd264d | |||
| 7197bc2bee | |||
| 66d9a06f9e | |||
| fba522d0c3 | |||
| 0e829874c2 | |||
| c5d56065b6 | |||
| 410d765745 | |||
| fe76e85c71 | |||
| 9d61a43bd7 | |||
| d4d7ddf8e2 | |||
| a1933c2869 | |||
| 8084a61333 | |||
| 03f5f91043 | |||
| 9ed52a1225 | |||
| 027324cc4f |
@@ -10,13 +10,11 @@ import org.apache.commons.cli.Options;
|
|||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import seng302.discoveryServer.DiscoveryServer;
|
|
||||||
import seng302.visualiser.controllers.ViewManager;
|
import seng302.visualiser.controllers.ViewManager;
|
||||||
|
|
||||||
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);
|
||||||
private static boolean isRunningAsCache = false;
|
|
||||||
|
|
||||||
public static void parseArgs(String[] args) throws ParseException {
|
public static void parseArgs(String[] args) throws ParseException {
|
||||||
Options options = new Options();
|
Options options = new Options();
|
||||||
@@ -27,52 +25,40 @@ public class App extends Application {
|
|||||||
.getLogger(Logger.ROOT_LOGGER_NAME);
|
.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||||
|
|
||||||
options.addOption("debugLevel", true, "Set the application debug level");
|
options.addOption("debugLevel", true, "Set the application debug level");
|
||||||
options.addOption("runAsDiscoveryServer", false, "Run as a discovery server");
|
|
||||||
options.addOption("discoveryDevMode", false, "Use a local discovery server");
|
|
||||||
|
|
||||||
cmd = parser.parse(options, args);
|
cmd = parser.parse(options, args);
|
||||||
|
|
||||||
if (cmd.hasOption("runAsDiscoveryServer")){
|
|
||||||
isRunningAsCache = true;
|
|
||||||
rootLogger.setLevel(Level.ALL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd.hasOption("discoveryDevMode")) {
|
|
||||||
DiscoveryServer.DISCOVERY_SERVER = "localhost";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd.hasOption("debugLevel")) {
|
if (cmd.hasOption("debugLevel")) {
|
||||||
|
|
||||||
switch (cmd.getOptionValue("debugLevel")) {
|
switch (cmd.getOptionValue("debugLevel")) {
|
||||||
case "DEBUG":
|
case "DEBUG":
|
||||||
rootLogger.setLevel(Level.DEBUG);
|
rootLogger.setLevel(Level.DEBUG);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "ALL":
|
case "ALL":
|
||||||
rootLogger.setLevel(Level.ALL);
|
rootLogger.setLevel(Level.ALL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "WARNING":
|
case "WARNING":
|
||||||
rootLogger.setLevel(Level.WARN);
|
rootLogger.setLevel(Level.WARN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "ERROR":
|
case "ERROR":
|
||||||
rootLogger.setLevel(Level.ERROR);
|
rootLogger.setLevel(Level.ERROR);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "INFO":
|
case "INFO":
|
||||||
rootLogger.setLevel(Level.INFO);
|
rootLogger.setLevel(Level.INFO);
|
||||||
|
|
||||||
case "TRACE":
|
case "TRACE":
|
||||||
rootLogger.setLevel(Level.TRACE);
|
rootLogger.setLevel(Level.TRACE);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
rootLogger.setLevel(Level.ALL);
|
rootLogger.setLevel(Level.ALL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rootLogger.setLevel(Level.WARN);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
rootLogger.setLevel(Level.WARN);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -81,19 +67,14 @@ public class App extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) {
|
||||||
try {
|
try {
|
||||||
parseArgs(args);
|
parseArgs(args);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
logger.error("Could not parse command line arguments");
|
logger.error("Could not parse command line arguments");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isRunningAsCache){
|
launch(args);
|
||||||
launch(args);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
new DiscoveryServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,117 +0,0 @@
|
|||||||
package seng302.discoveryServer;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import seng302.gameServer.messages.Message;
|
|
||||||
import seng302.gameServer.messages.RoomCodeRequest;
|
|
||||||
import seng302.gameServer.messages.ServerRegistrationMessage;
|
|
||||||
import seng302.model.stream.packets.PacketType;
|
|
||||||
import seng302.discoveryServer.util.ServerListing;
|
|
||||||
import seng302.discoveryServer.util.ServerRepoStreamParser;
|
|
||||||
import seng302.discoveryServer.util.ServerTable;
|
|
||||||
|
|
||||||
import java.net.ServerSocket;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public class DiscoveryServer {
|
|
||||||
public static final String ANSI_GREEN = "\u001B[32m";
|
|
||||||
public static final String ANSI_YELLOW = "\u001B[33m";
|
|
||||||
public static final String ANSI_BLUE = "\u001B[34m";
|
|
||||||
public static final String ANSI_RESET = "\u001B[0m";
|
|
||||||
public static String DISCOVERY_SERVER = "party.sydney.srv.michaelrausch.nz";
|
|
||||||
|
|
||||||
private ServerTable serverTable;
|
|
||||||
public static final Integer PORT_NUMBER = 9969;
|
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(DiscoveryServer.class);
|
|
||||||
|
|
||||||
private void displayHeader(){
|
|
||||||
String selectedColor = Arrays.asList(ANSI_BLUE, ANSI_GREEN, ANSI_YELLOW).get(new Random().nextInt(2));
|
|
||||||
System.out.println(selectedColor);
|
|
||||||
System.out.println(" .ccccc. \n" +
|
|
||||||
" .cc;'coooxkl;. \n" +
|
|
||||||
" .:c:::c:,,,,,;c;;,.'. \n" +
|
|
||||||
" .clc,',:,..:xxocc;'..c; \n" +
|
|
||||||
" .c:,';:ox:..:c,,,,,,...cd, \n" +
|
|
||||||
" .c:'.,oxxxxl::l:.,loll;..;ol. \n" +
|
|
||||||
" ;Oc..:xxxxxxxxx:.,llll,....oc \n" +
|
|
||||||
" .,;,',:loxxxxxxxxx:.,llll;.,,.'ld, \n" +
|
|
||||||
" .lo;..:xxxxxxxxxxxx:.'cllc,.:l:'cO; \n" +
|
|
||||||
" .:;...'cxxxxxxxxxxxxoc;,::,..cdl;;l' \n" +
|
|
||||||
" .cl;':,'';oxxxxxxdxxxxxx:....,cooc,cO; \n" +
|
|
||||||
" .,,,::;,lxoc:,,:lxxxxxxxxxxxo:,,;lxxl;'oNc \n" +
|
|
||||||
" .cdxo;':lxxxxxxc'';cccccoxxxxxxxxxxxxo,.;lc. " + ANSI_YELLOW + "Party-Parrots-At-Sea Discovery Server v0.1 " + selectedColor +"\n" +
|
|
||||||
" .loc'.'lxxxxxxxxocc;''''';ccoxxxxxxxxx:..oc \n" +
|
|
||||||
"olc,..',:cccccccccccc:;;;;;;;;:ccccccccc,.'c, \n" +
|
|
||||||
"Ol;......................................;l' ");
|
|
||||||
System.out.println(ANSI_RESET);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DiscoveryServer() throws Exception {
|
|
||||||
displayHeader();
|
|
||||||
serverTable = new ServerTable();
|
|
||||||
|
|
||||||
ServerSocket serverSocket;
|
|
||||||
|
|
||||||
try{
|
|
||||||
serverSocket = new ServerSocket(PORT_NUMBER);
|
|
||||||
}
|
|
||||||
catch(java.net.BindException e){
|
|
||||||
logger.error("FATAL - Could not bind socket, are you sure there isn't already an instance running?");
|
|
||||||
System.exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("Started successfully - Now accepting connections");
|
|
||||||
|
|
||||||
while (true){
|
|
||||||
Socket clientSocket = serverSocket.accept();
|
|
||||||
|
|
||||||
parseRequest(clientSocket);
|
|
||||||
|
|
||||||
clientSocket.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void parseRequest(Socket clientSocket) throws Exception {
|
|
||||||
ServerRepoStreamParser parser = new ServerRepoStreamParser(clientSocket.getInputStream());
|
|
||||||
|
|
||||||
if (clientSocket.isConnected() && !clientSocket.isClosed()){
|
|
||||||
PacketType parsePacketResult = parser.parse();
|
|
||||||
|
|
||||||
switch (parsePacketResult){
|
|
||||||
case SERVER_REGISTRATION:
|
|
||||||
ServerListing listing = parser.getServerListing();
|
|
||||||
|
|
||||||
if (!serverTable.getAllServers().contains(listing)){
|
|
||||||
listing.setRoomCode(serverTable.getNextRoomCode().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
serverTable.addServer(listing);
|
|
||||||
|
|
||||||
Message serverRegMessage = new RoomCodeRequest(listing.getRoomCode());
|
|
||||||
clientSocket.getOutputStream().write(serverRegMessage.getBuffer());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ROOM_CODE_REQUEST:
|
|
||||||
String desiredRoomCode = parser.getRoomCode();
|
|
||||||
|
|
||||||
ServerListing serverListing = serverTable.getServerByRoomCode(desiredRoomCode);
|
|
||||||
Message response;
|
|
||||||
|
|
||||||
if (serverListing != null){
|
|
||||||
response = new ServerRegistrationMessage(serverListing.getServerName(), serverListing.getMapName(), serverListing.getAddress(), serverListing.getPortNumber(), 0, 0, desiredRoomCode);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
response = new ServerRegistrationMessage("", "", "", 0, 0, 0, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
clientSocket.getOutputStream().write(response.getBuffer());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
package seng302.discoveryServer;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import seng302.gameServer.messages.Message;
|
|
||||||
import seng302.gameServer.messages.RoomCodeRequest;
|
|
||||||
import seng302.gameServer.messages.ServerRegistrationMessage;
|
|
||||||
import seng302.model.stream.packets.PacketType;
|
|
||||||
import seng302.discoveryServer.util.ServerListing;
|
|
||||||
import seng302.discoveryServer.util.ServerRepoStreamParser;
|
|
||||||
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
public class DiscoveryServerClient {
|
|
||||||
private final Integer UPDATE_INTERVAL_MS = 5000;
|
|
||||||
|
|
||||||
private static String roomCode = null;
|
|
||||||
private Timer serverListingUpdateTimer;
|
|
||||||
private Logger logger = LoggerFactory.getLogger(DiscoveryServerClient.class);
|
|
||||||
|
|
||||||
public DiscoveryServerClient() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register the server with the discovery server
|
|
||||||
* @param serverListing The listing to register
|
|
||||||
*/
|
|
||||||
public void register(ServerListing serverListing){
|
|
||||||
if (serverListingUpdateTimer != null){
|
|
||||||
serverListingUpdateTimer.cancel();
|
|
||||||
serverListingUpdateTimer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
serverListingUpdateTimer = new Timer();
|
|
||||||
|
|
||||||
serverListingUpdateTimer.schedule(new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
sendRegistrationUpdate(serverListing);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.debug("Could not update server listing");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 0, UPDATE_INTERVAL_MS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop updating the server registration updates
|
|
||||||
*/
|
|
||||||
public void unregister(){
|
|
||||||
serverListingUpdateTimer.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the connection information for a server given a room code
|
|
||||||
*
|
|
||||||
* @param roomCode The room code to search for
|
|
||||||
* @return The ServerListing, or null if there was an error
|
|
||||||
* @throws Exception .
|
|
||||||
*/
|
|
||||||
public ServerListing getServerForRoomCode(String roomCode) throws Exception {
|
|
||||||
Socket socket = new Socket(DiscoveryServer.DISCOVERY_SERVER, DiscoveryServer.PORT_NUMBER);
|
|
||||||
ServerRepoStreamParser parser = new ServerRepoStreamParser(socket.getInputStream());
|
|
||||||
|
|
||||||
Message request = new RoomCodeRequest(roomCode); //roomCode);
|
|
||||||
socket.getOutputStream().write(request.getBuffer());
|
|
||||||
|
|
||||||
PacketType packetType = parser.parse();
|
|
||||||
|
|
||||||
if (packetType != PacketType.SERVER_REGISTRATION){
|
|
||||||
logger.debug("Wrong packet received in response to a room code request");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.close();
|
|
||||||
|
|
||||||
return parser.getServerListing();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a registration update to the discovery server.
|
|
||||||
*
|
|
||||||
* @param serverListing The server listing to send
|
|
||||||
* @throws Exception IF there was an error sending the update
|
|
||||||
*/
|
|
||||||
private void sendRegistrationUpdate(ServerListing serverListing) throws Exception {
|
|
||||||
Socket socket = new Socket(DiscoveryServer.DISCOVERY_SERVER, DiscoveryServer.PORT_NUMBER);
|
|
||||||
ServerRepoStreamParser parser = new ServerRepoStreamParser(socket.getInputStream());
|
|
||||||
|
|
||||||
Message req = new ServerRegistrationMessage(serverListing);
|
|
||||||
|
|
||||||
socket.getOutputStream().write(req.getBuffer());
|
|
||||||
|
|
||||||
PacketType packetType = parser.parse();
|
|
||||||
|
|
||||||
if (packetType != PacketType.ROOM_CODE_REQUEST){
|
|
||||||
socket.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String roomCode = parser.getRoomCode();
|
|
||||||
|
|
||||||
if (roomCode.length() != 0){
|
|
||||||
DiscoveryServerClient.roomCode = roomCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The last room code received by the client
|
|
||||||
*/
|
|
||||||
public static String getRoomCode(){
|
|
||||||
return roomCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
package seng302.discoveryServer.util;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
public class ReadableByteInputStream {
|
|
||||||
private InputStream is;
|
|
||||||
|
|
||||||
public ReadableByteInputStream(InputStream is){
|
|
||||||
this.is = is;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get n bytes from the input stream
|
|
||||||
* @param n number of bytes
|
|
||||||
* @return the bytes read
|
|
||||||
* @throws Exception .
|
|
||||||
*/
|
|
||||||
public byte[] getBytes(int n) throws Exception {
|
|
||||||
byte[] bytes = new byte[n];
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
bytes[i] = (byte) readByte();
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Skip n bytes
|
|
||||||
* @param n number of bytes to skip
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public void skipBytes(long n) throws Exception {
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
readByte();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the next byte from the stream
|
|
||||||
* @return The byte that was read
|
|
||||||
* @throws Exception .
|
|
||||||
*/
|
|
||||||
public int readByte() throws Exception {
|
|
||||||
int currentByte = is.read();
|
|
||||||
|
|
||||||
if (currentByte == -1) {
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
return currentByte;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
package seng302.discoveryServer.util;
|
|
||||||
|
|
||||||
public class ServerListing {
|
|
||||||
public final static int SERVER_TTL_DEFAULT = 10;
|
|
||||||
|
|
||||||
private String serverName = "";
|
|
||||||
private String mapName = "";
|
|
||||||
private String address = "";
|
|
||||||
private int portNumber = 0;
|
|
||||||
private int capacity = 0;
|
|
||||||
private int players = 0;
|
|
||||||
private String roomCode = "";
|
|
||||||
private int ttl = SERVER_TTL_DEFAULT;
|
|
||||||
|
|
||||||
|
|
||||||
public ServerListing(String serverName, String mapName, String address, int portNumber, int capacity){
|
|
||||||
this.serverName = serverName;
|
|
||||||
this.mapName = mapName;
|
|
||||||
this.address = address;
|
|
||||||
this.portNumber = portNumber;
|
|
||||||
this.capacity = capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServerListing setNumberOfPlayers(int players){
|
|
||||||
this.players = players;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServerListing setRoomCode(String roomCode){
|
|
||||||
this.roomCode = roomCode;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void refreshTtl(){
|
|
||||||
ttl = SERVER_TTL_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void decrementTtl(){
|
|
||||||
ttl--;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasTtlExpired(){
|
|
||||||
return ttl < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (obj == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!ServerListing.class.isAssignableFrom(obj.getClass())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final ServerListing other = (ServerListing) obj;
|
|
||||||
|
|
||||||
if (this.getPortNumber() != other.getPortNumber()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.getMapName().equals(other.getMapName())){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.getServerName().equals(other.getServerName())){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.getCapacity() != other.getCapacity()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.getAddress().equals(other.getAddress())){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return this.getServerName().hashCode() +
|
|
||||||
this.getAddress().hashCode() + this.getMapName().hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRoomCode() {
|
|
||||||
return roomCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPortNumber() {
|
|
||||||
return portNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMapName() {
|
|
||||||
return mapName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getServerName() {
|
|
||||||
return serverName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCapacity() {
|
|
||||||
return capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAddress() {
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTtl(Integer ttl){
|
|
||||||
this.ttl = ttl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
package seng302.discoveryServer.util;
|
|
||||||
|
|
||||||
|
|
||||||
import seng302.gameServer.messages.Message;
|
|
||||||
import seng302.model.stream.packets.PacketType;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class ServerRepoStreamParser {
|
|
||||||
private ReadableByteInputStream inputStream;
|
|
||||||
|
|
||||||
private String roomCode;
|
|
||||||
private String mapName;
|
|
||||||
private ServerListing serverListing;
|
|
||||||
|
|
||||||
public ServerRepoStreamParser(InputStream is){
|
|
||||||
inputStream = new ReadableByteInputStream(is);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PacketType parse() throws Exception {
|
|
||||||
int sync1 = inputStream.readByte();
|
|
||||||
int sync2 = inputStream.readByte();
|
|
||||||
|
|
||||||
PacketType packetType = null;
|
|
||||||
|
|
||||||
if (sync1 == 0x47 && sync2 == 0x83) {
|
|
||||||
int type = inputStream.readByte();
|
|
||||||
inputStream.skipBytes(10);
|
|
||||||
long payloadLength = Message.bytesToLong(inputStream.getBytes(2));
|
|
||||||
byte[] payload = inputStream.getBytes((int) payloadLength);
|
|
||||||
inputStream.skipBytes(4);
|
|
||||||
|
|
||||||
packetType = PacketType.assignPacketType(type, payload);
|
|
||||||
|
|
||||||
switch (packetType) {
|
|
||||||
case ROOM_CODE_REQUEST:
|
|
||||||
roomCode = parseRoomCodeRequest(payload);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LOBBY_REQUEST:
|
|
||||||
mapName = parseLobbyRequest(payload);
|
|
||||||
|
|
||||||
case SERVER_REGISTRATION:
|
|
||||||
serverListing = parseServerRegistration(payload);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return packetType;
|
|
||||||
}
|
|
||||||
private String parseLobbyRequest(byte[] payload) {
|
|
||||||
int mapNameLength = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 0 ,4));
|
|
||||||
|
|
||||||
return new String(Arrays.copyOfRange(payload, 4, 4+mapNameLength));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String parseRoomCodeRequest(byte[] payload) {
|
|
||||||
int roomCodeLength = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 0 ,6));
|
|
||||||
|
|
||||||
return new String(Arrays.copyOfRange(payload, 6, 6+roomCodeLength));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ServerListing parseServerRegistration(byte[] payload) {
|
|
||||||
int nameLength = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 0, 6));
|
|
||||||
int mapNameLength = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 6, 12));
|
|
||||||
int addressLength = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 12, 18));
|
|
||||||
int roomCodeLength = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 18, 24));
|
|
||||||
|
|
||||||
int portNumber = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 24, 28));
|
|
||||||
int players = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 28, 32));
|
|
||||||
int capacity = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 32, 36));
|
|
||||||
|
|
||||||
int currentPos = 36;
|
|
||||||
int nextPos = currentPos + nameLength;
|
|
||||||
String serverName = new String(Arrays.copyOfRange(payload, currentPos, nextPos));
|
|
||||||
|
|
||||||
currentPos = nextPos;
|
|
||||||
nextPos = currentPos + mapNameLength;
|
|
||||||
String mapName = new String(Arrays.copyOfRange(payload, currentPos, nextPos));
|
|
||||||
|
|
||||||
currentPos = nextPos;
|
|
||||||
nextPos = currentPos + addressLength;
|
|
||||||
String address = new String(Arrays.copyOfRange(payload, currentPos, nextPos));
|
|
||||||
|
|
||||||
currentPos = nextPos;
|
|
||||||
nextPos = currentPos + roomCodeLength;
|
|
||||||
String roomCode = new String(Arrays.copyOfRange(payload, currentPos, nextPos));
|
|
||||||
|
|
||||||
ServerListing serverListing = new ServerListing(serverName, mapName, address, portNumber, capacity);
|
|
||||||
serverListing.setNumberOfPlayers(players);
|
|
||||||
serverListing.setRoomCode(roomCode);
|
|
||||||
|
|
||||||
return serverListing;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRoomCode() {
|
|
||||||
return roomCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMapName() {
|
|
||||||
return mapName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServerListing getServerListing() {
|
|
||||||
return serverListing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
package seng302.discoveryServer.util;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class ServerTable {
|
|
||||||
private List<ServerListing> servers;
|
|
||||||
private int lastRoomCode = 4020;
|
|
||||||
private Logger logger = LoggerFactory.getLogger(ServerTable.class);
|
|
||||||
|
|
||||||
public ServerTable(){
|
|
||||||
servers = new ArrayList<>();
|
|
||||||
|
|
||||||
new Timer().schedule(new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
updateServers();
|
|
||||||
}
|
|
||||||
}, 0, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the servers TTL values, and then remove expired servers
|
|
||||||
*/
|
|
||||||
private void updateServers() {
|
|
||||||
List<ServerListing> serversToRemove = new ArrayList<>();
|
|
||||||
|
|
||||||
for (ServerListing server : servers){
|
|
||||||
server.decrementTtl();
|
|
||||||
|
|
||||||
if (server.hasTtlExpired()){
|
|
||||||
logger.debug("Removed expired server - " + server.getServerName());
|
|
||||||
serversToRemove.add(server);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
servers.removeAll(serversToRemove);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a server to the table
|
|
||||||
* @param server The server to add
|
|
||||||
*/
|
|
||||||
public void addServer(ServerListing server){
|
|
||||||
if (servers.contains(server)){
|
|
||||||
updateTtlForServer(server);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
logger.debug("Added new server - " + server.getServerName());
|
|
||||||
servers.add(server);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the TTL for a given server to the default TTL value
|
|
||||||
* @param server The server to update
|
|
||||||
*/
|
|
||||||
private void updateTtlForServer(ServerListing server) {
|
|
||||||
for (ServerListing serverListing : servers){
|
|
||||||
if (server.equals(serverListing)){
|
|
||||||
serverListing.refreshTtl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return All the servers in the table
|
|
||||||
*/
|
|
||||||
public List<ServerListing> getAllServers(){
|
|
||||||
return Collections.unmodifiableList(servers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a server from the table given its room code
|
|
||||||
* @param roomCode The room code to search for
|
|
||||||
* @return The ServerListing of the found server, or null
|
|
||||||
* the server wasn't found
|
|
||||||
*/
|
|
||||||
public ServerListing getServerByRoomCode(String roomCode){
|
|
||||||
for (ServerListing serverListing : servers){
|
|
||||||
if (serverListing.getRoomCode().equals(roomCode)){
|
|
||||||
return serverListing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The next available room code
|
|
||||||
*/
|
|
||||||
public Integer getNextRoomCode(){
|
|
||||||
lastRoomCode += 1;
|
|
||||||
return lastRoomCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +1,47 @@
|
|||||||
package seng302.gameServer;
|
package seng302.gameServer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
import seng302.gameServer.messages.*;
|
import seng302.gameServer.messages.BoatAction;
|
||||||
import seng302.model.*;
|
import seng302.gameServer.messages.BoatStatus;
|
||||||
|
import seng302.gameServer.messages.ChatterMessage;
|
||||||
|
import seng302.gameServer.messages.CustomizeRequestType;
|
||||||
|
import seng302.gameServer.messages.MarkRoundingMessage;
|
||||||
|
import seng302.gameServer.messages.MarkType;
|
||||||
|
import seng302.gameServer.messages.Message;
|
||||||
|
import seng302.gameServer.messages.RoundingBoatStatus;
|
||||||
|
import seng302.gameServer.messages.YachtEventCodeMessage;
|
||||||
|
import seng302.gameServer.messages.YachtEventType;
|
||||||
|
import seng302.model.GeoPoint;
|
||||||
|
import seng302.model.Limit;
|
||||||
|
import seng302.model.Player;
|
||||||
|
import seng302.model.PolarTable;
|
||||||
|
import seng302.model.ServerYacht;
|
||||||
import seng302.model.mark.CompoundMark;
|
import seng302.model.mark.CompoundMark;
|
||||||
import seng302.model.mark.Mark;
|
import seng302.model.mark.Mark;
|
||||||
import seng302.model.mark.MarkOrder;
|
import seng302.model.mark.MarkOrder;
|
||||||
import seng302.model.token.Token;
|
import seng302.model.token.Token;
|
||||||
import seng302.model.token.TokenType;
|
import seng302.model.token.TokenType;
|
||||||
import seng302.utilities.GeoUtility;
|
import seng302.utilities.GeoUtility;
|
||||||
|
import seng302.utilities.RandomSpawn;
|
||||||
import seng302.utilities.XMLParser;
|
import seng302.utilities.XMLParser;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Static class to hold information about the current state of the game (model)
|
* A Static class to hold information about the current state of the game (model)
|
||||||
@@ -34,25 +58,38 @@ public class GameState implements Runnable {
|
|||||||
private static Logger logger = LoggerFactory.getLogger(GameState.class);
|
private static Logger logger = LoggerFactory.getLogger(GameState.class);
|
||||||
|
|
||||||
|
|
||||||
|
private static final Integer STATE_UPDATES_PER_SECOND = 60;
|
||||||
|
|
||||||
|
//Scheduling constants
|
||||||
static final int WARNING_TIME = 10 * -1000;
|
static final int WARNING_TIME = 10 * -1000;
|
||||||
static final int PREPATORY_TIME = 5 * -1000;
|
static final int PREPATORY_TIME = 5 * -1000;
|
||||||
private static final int TIME_TILL_START = 10 * 1000;
|
private static final int TIME_TILL_START = 10 * 1000;
|
||||||
|
|
||||||
private static final Long POWERUP_TIMEOUT_MS = 10_000L;
|
//Wind Constants
|
||||||
|
private static final int MAX_WIND_SPEED = 12000;
|
||||||
|
private static final int MIN_WIND_SPEED = 8000;
|
||||||
|
|
||||||
private static final Integer STATE_UPDATES_PER_SECOND = 60;
|
//Rounding Constants
|
||||||
private static Double ROUNDING_DISTANCE = 50d; // TODO: 14/08/17 wmu16 - Look into this value further
|
private static final Double ROUNDING_DISTANCE = 50d; // TODO: 14/08/17 wmu16 - Look into this value further
|
||||||
|
|
||||||
|
//Collision constants
|
||||||
private static final Double MARK_COLLISION_DISTANCE = 15d;
|
private static final Double MARK_COLLISION_DISTANCE = 15d;
|
||||||
public static final Double YACHT_COLLISION_DISTANCE = 25.0;
|
public static final Double YACHT_COLLISION_DISTANCE = 25.0;
|
||||||
private static final Double BOUNCE_DISTANCE_MARK = 20.0;
|
private static final Double BOUNCE_DISTANCE_MARK = 20.0;
|
||||||
public static final Double BOUNCE_DISTANCE_YACHT = 30.0;
|
public static final Double BOUNCE_DISTANCE_YACHT = 30.0;
|
||||||
private static final Double COLLISION_VELOCITY_PENALTY = 0.3;
|
private static final Double COLLISION_VELOCITY_PENALTY = 0.3;
|
||||||
private static final Integer VELOCITY_BOOST_MULTIPLIER = 2;
|
|
||||||
|
//Powerup Constants
|
||||||
|
public static final Double VELOCITY_BOOST_MULTIPLIER = 2d;
|
||||||
|
public static final Integer HANDLING_BOOST_MULTIPLIER = 2;
|
||||||
|
private static final Double BAD_RANDOM_SPEED_PENALTY = 0.3;
|
||||||
|
public static final Long BUMPER_DISABLE_TIME = 5_000L;
|
||||||
|
private static final Long TOKEN_SPAWN_TIME = 30_000L;
|
||||||
|
|
||||||
private static Long previousUpdateTime;
|
private static Long previousUpdateTime;
|
||||||
public static Double windDirection;
|
public static Double windDirection;
|
||||||
private static Double windSpeed;
|
private static Double windSpeed;
|
||||||
private static Double speedMultiplier = 1d;
|
private static Double serverSpeedMultiplier;
|
||||||
|
|
||||||
private static Boolean customizationFlag; // dirty flag to tell if a player has customized their boat.
|
private static Boolean customizationFlag; // dirty flag to tell if a player has customized their boat.
|
||||||
private static Boolean playerHasLeftFlag;
|
private static Boolean playerHasLeftFlag;
|
||||||
@@ -64,13 +101,12 @@ public class GameState implements Runnable {
|
|||||||
private static GameStages currentStage;
|
private static GameStages currentStage;
|
||||||
private static MarkOrder markOrder;
|
private static MarkOrder markOrder;
|
||||||
private static long startTime;
|
private static long startTime;
|
||||||
private static Set<Mark> marks;
|
private static List<Mark> marks;
|
||||||
private static List<Limit> courseLimit;
|
private static List<Limit> courseLimit;
|
||||||
private static Integer maxPlayers = 8;
|
private static Integer maxPlayers = 8;
|
||||||
|
|
||||||
|
|
||||||
private static List<Token> allTokens;
|
|
||||||
private static List<Token> tokensInPlay;
|
private static List<Token> tokensInPlay;
|
||||||
|
private static RandomSpawn randomSpawn;
|
||||||
|
|
||||||
private static List<NewMessageListener> newMessageListeners;
|
private static List<NewMessageListener> newMessageListeners;
|
||||||
|
|
||||||
@@ -81,26 +117,22 @@ public class GameState implements Runnable {
|
|||||||
windSpeed = 10000d;
|
windSpeed = 10000d;
|
||||||
yachts = new HashMap<>();
|
yachts = new HashMap<>();
|
||||||
tokensInPlay = new ArrayList<>();
|
tokensInPlay = new ArrayList<>();
|
||||||
|
|
||||||
players = new ArrayList<>();
|
players = new ArrayList<>();
|
||||||
GameState.hostIpAddress = hostIpAddress;
|
GameState.hostIpAddress = hostIpAddress;
|
||||||
customizationFlag = false;
|
customizationFlag = false;
|
||||||
playerHasLeftFlag = false;
|
playerHasLeftFlag = false;
|
||||||
speedMultiplier = 1.0;
|
serverSpeedMultiplier = 1.0;
|
||||||
currentStage = GameStages.LOBBYING;
|
currentStage = GameStages.LOBBYING;
|
||||||
isRaceStarted = false;
|
isRaceStarted = false;
|
||||||
//set this when game stage changes to prerace
|
|
||||||
previousUpdateTime = System.currentTimeMillis();
|
previousUpdateTime = System.currentTimeMillis();
|
||||||
markOrder = new MarkOrder(); //This could be instantiated at some point with a select map?
|
markOrder = new MarkOrder(); //This could be instantiated at some point with a select map?
|
||||||
newMessageListeners = new ArrayList<>();
|
newMessageListeners = new ArrayList<>();
|
||||||
allTokens = makeTokens();
|
marks = new MarkOrder().getAllMarks();
|
||||||
|
randomSpawn = new RandomSpawn(markOrder.getOrderedUniqueCompoundMarks());
|
||||||
|
|
||||||
resetStartTime();
|
resetStartTime();
|
||||||
|
|
||||||
new Thread(this, "GameState").start(); //Run the auto updates on the game state
|
|
||||||
|
|
||||||
marks = new MarkOrder().getAllMarks();
|
|
||||||
setCourseLimit("/server_config/race.xml");
|
setCourseLimit("/server_config/race.xml");
|
||||||
|
new Thread(this, "GameState").start(); //Run the auto updates on the game state
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setCourseLimit(String url) {
|
private void setCourseLimit(String url) {
|
||||||
@@ -118,29 +150,10 @@ public class GameState implements Runnable {
|
|||||||
courseLimit = XMLParser.parseRace(document).getCourseLimit();
|
courseLimit = XMLParser.parseRace(document).getCourseLimit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make a pre defined set of tokensInPlay. //TODO wmu16 - Should read from some file for each
|
|
||||||
* race ideally
|
|
||||||
*
|
|
||||||
* @return A list of possible tokensInPlay for this race
|
|
||||||
*/
|
|
||||||
private ArrayList<Token> makeTokens() {
|
|
||||||
Token token1 = new Token(TokenType.BOOST, 57.66946, 11.83154);
|
|
||||||
Token token2 = new Token(TokenType.BOOST, 57.66877, 11.83382);
|
|
||||||
Token token3 = new Token(TokenType.BOOST, 57.66914, 11.83965);
|
|
||||||
Token token4 = new Token(TokenType.BOOST, 57.66684, 11.83214);
|
|
||||||
return new ArrayList<>(Arrays.asList(token1, token2, token3, token4));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getHostIpAddress() {
|
public static String getHostIpAddress() {
|
||||||
return hostIpAddress;
|
return hostIpAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<Mark> getMarks() {
|
|
||||||
return Collections.unmodifiableSet(marks);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Player> getPlayers() {
|
public static List<Player> getPlayers() {
|
||||||
return players;
|
return players;
|
||||||
}
|
}
|
||||||
@@ -241,16 +254,75 @@ public class GameState implements Runnable {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
System.out.println("[GameState] interrupted exception");
|
System.out.println("[GameState] interrupted exception");
|
||||||
}
|
}
|
||||||
if (currentStage == GameStages.PRE_RACE || currentStage == GameStages.RACING) {
|
if (currentStage == GameStages.PRE_RACE) {
|
||||||
update();
|
update();
|
||||||
|
if (System.currentTimeMillis() > startTime) {
|
||||||
|
startSpawningTokens();
|
||||||
|
startUpdatingWind();
|
||||||
|
GameState.setCurrentStage(GameStages.RACING);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentStage == GameStages.RACING) {
|
if (currentStage == GameStages.RACING) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start spawning coins every 60s after the first minute
|
||||||
|
*/
|
||||||
|
private void startSpawningTokens() {
|
||||||
|
Timer timer = new Timer("Token Spawning Timer");
|
||||||
|
timer.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
spawnNewToken();
|
||||||
|
notifyMessageListeners(MessageFactory.getRaceXML());
|
||||||
|
}
|
||||||
|
}, 0, TOKEN_SPAWN_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: 29/08/17 wmu16 - This sort of update should be in game state
|
||||||
|
private static void startUpdatingWind() {
|
||||||
|
Timer timer = new Timer("Wind Updating Timer");
|
||||||
|
timer.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
updateWind();
|
||||||
|
}
|
||||||
|
}, 0, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void updateWind() {
|
||||||
|
Integer direction = GameState.getWindDirection().intValue();
|
||||||
|
Integer windSpeed = GameState.getWindSpeedMMS().intValue();
|
||||||
|
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
if (Math.floorMod(random.nextInt(), 2) == 0) {
|
||||||
|
direction += random.nextInt(4);
|
||||||
|
windSpeed += random.nextInt(20) + 459;
|
||||||
|
} else {
|
||||||
|
direction -= random.nextInt(4);
|
||||||
|
windSpeed -= random.nextInt(20) + 459;
|
||||||
|
}
|
||||||
|
|
||||||
|
direction = Math.floorMod(direction, 360);
|
||||||
|
|
||||||
|
if (windSpeed > MAX_WIND_SPEED) {
|
||||||
|
windSpeed -= random.nextInt(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (windSpeed <= MIN_WIND_SPEED) {
|
||||||
|
windSpeed += random.nextInt(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameState.setWindSpeed(Double.valueOf(windSpeed));
|
||||||
|
GameState.setWindDirection(direction.doubleValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void updateBoat(Integer sourceId, BoatAction actionType) {
|
public static void updateBoat(Integer sourceId, BoatAction actionType) {
|
||||||
ServerYacht playerYacht = yachts.get(sourceId);
|
ServerYacht playerYacht = yachts.get(sourceId);
|
||||||
switch (actionType) {
|
switch (actionType) {
|
||||||
@@ -272,6 +344,12 @@ public class GameState implements Runnable {
|
|||||||
case DOWNWIND:
|
case DOWNWIND:
|
||||||
playerYacht.turnDownwind();
|
playerYacht.turnDownwind();
|
||||||
break;
|
break;
|
||||||
|
case CONTINUOUSLY_TURNING:
|
||||||
|
playerYacht.setContinuouslyTurning(true);
|
||||||
|
break;
|
||||||
|
case DEFAULT_TURNING:
|
||||||
|
playerYacht.setContinuouslyTurning(false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,14 +357,11 @@ public class GameState implements Runnable {
|
|||||||
* Randomly select a subset of tokensInPlay from a pre defined superset
|
* Randomly select a subset of tokensInPlay from a pre defined superset
|
||||||
* Broadasts a new race status message to show this update
|
* Broadasts a new race status message to show this update
|
||||||
*/
|
*/
|
||||||
public static void spawnNewToken() {
|
private void spawnNewToken() {
|
||||||
Random random = new Random();
|
|
||||||
tokensInPlay.clear();
|
tokensInPlay.clear();
|
||||||
|
Token token = randomSpawn.getRandomTokenLocation();
|
||||||
//Get a random token location with random type
|
// token.assignType(TokenType.WIND_WALKER);
|
||||||
Token token = allTokens.get(random.nextInt(allTokens.size()));
|
logger.debug("Spawned token of type " + token.getTokenType());
|
||||||
token.assignRandomType();
|
|
||||||
|
|
||||||
tokensInPlay.add(token);
|
tokensInPlay.add(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,14 +379,12 @@ public class GameState implements Runnable {
|
|||||||
|
|
||||||
Double timeInterval = (System.currentTimeMillis() - previousUpdateTime) / 1000000.0;
|
Double timeInterval = (System.currentTimeMillis() - previousUpdateTime) / 1000000.0;
|
||||||
previousUpdateTime = System.currentTimeMillis();
|
previousUpdateTime = System.currentTimeMillis();
|
||||||
if (System.currentTimeMillis() > startTime) {
|
|
||||||
GameState.setCurrentStage(GameStages.RACING);
|
|
||||||
}
|
|
||||||
for (ServerYacht yacht : yachts.values()) {
|
for (ServerYacht yacht : yachts.values()) {
|
||||||
updateVelocity(yacht);
|
updateVelocity(yacht);
|
||||||
checkPowerUpTimeout(yacht);
|
|
||||||
yacht.runAutoPilot();
|
yacht.runAutoPilot();
|
||||||
yacht.updateLocation(timeInterval);
|
yacht.updateLocation(timeInterval);
|
||||||
|
preformTokenUpdates(yacht); //This update must be done before collision. Sorta hacky
|
||||||
checkCollision(yacht);
|
checkCollision(yacht);
|
||||||
if (yacht.getBoatStatus() != BoatStatus.FINISHED) {
|
if (yacht.getBoatStatus() != BoatStatus.FINISHED) {
|
||||||
checkForLegProgression(yacht);
|
checkForLegProgression(yacht);
|
||||||
@@ -325,17 +398,136 @@ public class GameState implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void checkPowerUpTimeout(ServerYacht yacht) {
|
/**
|
||||||
if (yacht.getPowerUp() != null) {
|
* All token functionality entry points is taken care of here. So can be disabled and enabled
|
||||||
if (System.currentTimeMillis() - yacht.getPowerUpStartTime() > POWERUP_TIMEOUT_MS) {
|
* easily
|
||||||
yacht.powerDown();
|
*
|
||||||
sendServerMessage(yacht.getSourceId(), yacht.getBoatName() + "'s power-up token expired");
|
* @param yacht The yacht to perform token checks on
|
||||||
logger.debug("Yacht: " + yacht.getShortName() + " powered down!");
|
*/
|
||||||
|
private void preformTokenUpdates(ServerYacht yacht) {
|
||||||
|
Token collidedToken = checkTokenPickUp(yacht);
|
||||||
|
if (collidedToken != null) {
|
||||||
|
tokensInPlay.remove(collidedToken);
|
||||||
|
powerUpYacht(yacht, collidedToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPowerUpTimeout(yacht);
|
||||||
|
TokenType powerUp = yacht.getPowerUp();
|
||||||
|
|
||||||
|
if (powerUp != null) {
|
||||||
|
switch (powerUp) {
|
||||||
|
case WIND_WALKER:
|
||||||
|
windWalk(yacht);
|
||||||
|
break;
|
||||||
|
case BUMPER:
|
||||||
|
ServerYacht collidedYacht = checkYachtCollision(yacht, true);
|
||||||
|
if (collidedYacht != null) {
|
||||||
|
yacht.powerDown();
|
||||||
|
boatTempShutDown(collidedYacht);
|
||||||
|
notifyMessageListeners(MessageFactory.makePowerDownMessage(yacht));
|
||||||
|
notifyMessageListeners(
|
||||||
|
MessageFactory.makeStatusEffectMessage(collidedYacht, powerUp));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RANDOM:
|
||||||
|
yacht.setPowerUpSpeedMultiplier(BAD_RANDOM_SPEED_PENALTY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Powers up a thisYacht with the given token type.
|
||||||
|
*
|
||||||
|
* @param thisYacht The yacht to be powered up
|
||||||
|
* @param collidedToken The token which this thisYacht collided with
|
||||||
|
*/
|
||||||
|
private void powerUpYacht(ServerYacht thisYacht, Token collidedToken) {
|
||||||
|
//The random token has a 50% chance of becoming another token else becoming a speed detriment!
|
||||||
|
if (collidedToken.getTokenType() == TokenType.RANDOM && new Random().nextBoolean()) {
|
||||||
|
collidedToken.realiseRandom();
|
||||||
|
}
|
||||||
|
|
||||||
|
//If another yacht has the wind walker token, They should be powered down. Only one allowed!
|
||||||
|
else if (collidedToken.getTokenType() == TokenType.WIND_WALKER) {
|
||||||
|
for (ServerYacht otherYacht : yachts.values()) {
|
||||||
|
if (otherYacht != thisYacht && otherYacht.getPowerUp() == TokenType.WIND_WALKER) {
|
||||||
|
powerDownYacht(otherYacht);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thisYacht.powerUp(collidedToken.getTokenType());
|
||||||
|
String logMessage =
|
||||||
|
thisYacht.getBoatName() + " has picked up a " + collidedToken.getTokenType().getName()
|
||||||
|
+ " token";
|
||||||
|
notifyMessageListeners(
|
||||||
|
MessageFactory.makeChatterMessage(thisYacht.getSourceId(), logMessage));
|
||||||
|
notifyMessageListeners(MessageFactory.getRaceXML());
|
||||||
|
notifyMessageListeners(MessageFactory.makePickupMessage(thisYacht, collidedToken));
|
||||||
|
logger.debug(
|
||||||
|
"Yacht: " + thisYacht.getShortName() + " got powerup " + collidedToken.getTokenType());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void powerDownYacht(ServerYacht yacht) {
|
||||||
|
String logMessage =
|
||||||
|
yacht.getBoatName() + "'s " + yacht.getPowerUp().getName() + " expired";
|
||||||
|
notifyMessageListeners(
|
||||||
|
MessageFactory.makeChatterMessage(yacht.getSourceId(), logMessage));
|
||||||
|
notifyMessageListeners(MessageFactory.makePowerDownMessage(yacht));
|
||||||
|
logger.debug("Yacht: " + yacht.getShortName() + " powered down!");
|
||||||
|
|
||||||
|
yacht.powerDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: 23/09/17 wmu16 - This is a hacky way to have the boat power down. Need some sort of separation between token and status effect :/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables the given boat for BUMPER_DISABLE_TIME ms.
|
||||||
|
*
|
||||||
|
* @param yacht The yacht to disable
|
||||||
|
*/
|
||||||
|
private void boatTempShutDown(ServerYacht yacht) {
|
||||||
|
yacht.setPowerUpSpeedMultiplier(0d);
|
||||||
|
Timer shutDownTimer = new Timer("Shutdown Timer");
|
||||||
|
shutDownTimer.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
yacht.powerDown(); //Note this actually resets the boat to normal.
|
||||||
|
}
|
||||||
|
}, BUMPER_DISABLE_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks how long a powerup has been active for. If it has exceeded its timeout, it powers the
|
||||||
|
* yacht down.
|
||||||
|
*
|
||||||
|
* @param yacht The yacht to check to power down
|
||||||
|
*/
|
||||||
|
private void checkPowerUpTimeout(ServerYacht yacht) {
|
||||||
|
if (yacht.getPowerUp() != null) {
|
||||||
|
if (System.currentTimeMillis() - yacht.getPowerUpStartTime() > yacht.getPowerUp()
|
||||||
|
.getTimeout()) {
|
||||||
|
powerDownYacht(yacht);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function changes the wind to be at an angle that causes the yacht in question to be at
|
||||||
|
* its fastest velocity
|
||||||
|
*
|
||||||
|
* @param yacht The yacht to fix the wind for
|
||||||
|
*/
|
||||||
|
private void windWalk(ServerYacht yacht) {
|
||||||
|
Double optimalAngle = PolarTable.getOptimalAngle();
|
||||||
|
Double heading = yacht.getHeading();
|
||||||
|
windDirection = (double) Math.floorMod(Math.round(heading + optimalAngle), 360L);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the yacht has crossed the course limit
|
* Check if the yacht has crossed the course limit
|
||||||
*
|
*
|
||||||
@@ -357,13 +549,15 @@ public class GameState implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks all tokensInPlay to see if a yacht has picked one up
|
* Checks all tokensInPlay to see if a yacht has picked one up. If so, the yacht is powered up
|
||||||
* @return Token which was collided with
|
* in the appropriate way
|
||||||
* @param serverYacht The yacht to check for collision with a token
|
* @param yacht The yacht to check for collision with a token
|
||||||
|
*
|
||||||
|
* @return The token collided with
|
||||||
*/
|
*/
|
||||||
private static Token checkTokenPickUp(ServerYacht serverYacht) {
|
private Token checkTokenPickUp(ServerYacht yacht) {
|
||||||
for (Token token : tokensInPlay) {
|
for (Token token : tokensInPlay) {
|
||||||
Double distance = GeoUtility.getDistance(token, serverYacht.getLocation());
|
Double distance = GeoUtility.getDistance(token, yacht.getLocation());
|
||||||
if (distance < YACHT_COLLISION_DISTANCE) {
|
if (distance < YACHT_COLLISION_DISTANCE) {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
@@ -386,9 +580,8 @@ public class GameState implements Runnable {
|
|||||||
*/
|
*/
|
||||||
public static void checkCollision(ServerYacht serverYacht) {
|
public static void checkCollision(ServerYacht serverYacht) {
|
||||||
//Yacht Collision
|
//Yacht Collision
|
||||||
ServerYacht collidedYacht = checkYachtCollision(serverYacht);
|
ServerYacht collidedYacht = checkYachtCollision(serverYacht, false);
|
||||||
Mark collidedMark = checkMarkCollision(serverYacht);
|
Mark collidedMark = checkMarkCollision(serverYacht);
|
||||||
Token collidedToken = checkTokenPickUp(serverYacht);
|
|
||||||
|
|
||||||
if (collidedYacht != null) {
|
if (collidedYacht != null) {
|
||||||
GeoPoint originalLocation = serverYacht.getLocation();
|
GeoPoint originalLocation = serverYacht.getLocation();
|
||||||
@@ -431,50 +624,36 @@ public class GameState implements Runnable {
|
|||||||
);
|
);
|
||||||
notifyMessageListeners(MessageFactory.makeCollisionMessage(serverYacht));
|
notifyMessageListeners(MessageFactory.makeCollisionMessage(serverYacht));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Token Collision
|
|
||||||
if (collidedToken != null) {
|
|
||||||
if (collidedToken.getTokenType() == TokenType.RANDOM) {
|
|
||||||
collidedToken.realiseRandom();
|
|
||||||
}
|
|
||||||
sendServerMessage(serverYacht.getSourceId(),
|
|
||||||
serverYacht.getBoatName() + " has picked up a " + collidedToken.getTokenType()
|
|
||||||
.getName() + " token");
|
|
||||||
tokensInPlay.remove(collidedToken);
|
|
||||||
serverYacht.powerUp(collidedToken.getTokenType());
|
|
||||||
logger.debug("Yacht: " + serverYacht.getShortName() + " got powerup " + collidedToken
|
|
||||||
.getTokenType());
|
|
||||||
notifyMessageListeners(MessageFactory.getRaceXML());
|
|
||||||
notifyMessageListeners(MessageFactory.makePickupMessage(serverYacht, collidedToken));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void updateVelocity(ServerYacht yacht) {
|
private void updateVelocity(ServerYacht yacht) {
|
||||||
Double trueWindAngle = Math.abs(windDirection - yacht.getHeading());
|
Double trueWindAngle = Math.abs(windDirection - yacht.getHeading());
|
||||||
Double boatSpeedInKnots = PolarTable.getBoatSpeed(getWindSpeedKnots(), trueWindAngle);
|
Double boatSpeedInKnots = PolarTable.getBoatSpeed(getWindSpeedKnots(), trueWindAngle);
|
||||||
Double maxBoatSpeed = GeoUtility.knotsToMMS(boatSpeedInKnots) * speedMultiplier;
|
Double maxBoatSpeed =
|
||||||
if (yacht.getPowerUp() != null) {
|
GeoUtility.knotsToMMS(boatSpeedInKnots) * serverSpeedMultiplier * yacht
|
||||||
if (yacht.getPowerUp().equals(TokenType.BOOST)) {
|
.getPowerUpSpeedMultiplier() * yacht.getBoatTypeSpeedMultiplier();
|
||||||
maxBoatSpeed *= VELOCITY_BOOST_MULTIPLIER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Double currentVelocity = yacht.getCurrentVelocity();
|
Double currentVelocity = yacht.getCurrentVelocity();
|
||||||
// TODO: 15/08/17 remove magic numbers from these equations.
|
// TODO: 15/08/17 remove magic numbers from these equations.
|
||||||
if (yacht.getSailIn()) {
|
if (yacht.getSailIn()) {
|
||||||
if (currentVelocity < maxBoatSpeed - 500) {
|
if (currentVelocity < maxBoatSpeed - 500) {
|
||||||
yacht.changeVelocity(maxBoatSpeed / 100);
|
yacht.changeVelocity(
|
||||||
|
(maxBoatSpeed / 100) * yacht.getBoatTypeAccelerationMultiplier());
|
||||||
} else if (currentVelocity > maxBoatSpeed + 500) {
|
} else if (currentVelocity > maxBoatSpeed + 500) {
|
||||||
yacht.changeVelocity(-currentVelocity / 200);
|
yacht.changeVelocity(
|
||||||
|
(-currentVelocity / 200) * yacht.getBoatTypeAccelerationMultiplier());
|
||||||
} else {
|
} else {
|
||||||
yacht.setCurrentVelocity(maxBoatSpeed);
|
yacht
|
||||||
|
.setCurrentVelocity((maxBoatSpeed) * yacht.getBoatTypeAccelerationMultiplier());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (currentVelocity > 3000) {
|
if (currentVelocity > 3000) {
|
||||||
yacht.changeVelocity(-currentVelocity / 200);
|
yacht.changeVelocity(
|
||||||
|
(-currentVelocity / 200) * yacht.getBoatTypeAccelerationMultiplier());
|
||||||
} else if (currentVelocity > 100) {
|
} else if (currentVelocity > 100) {
|
||||||
yacht.changeVelocity(-currentVelocity / 50);
|
yacht.changeVelocity(
|
||||||
|
(-currentVelocity / 50) * yacht.getBoatTypeAccelerationMultiplier());
|
||||||
} else if (currentVelocity <= 100) {
|
} else if (currentVelocity <= 100) {
|
||||||
yacht.setCurrentVelocity(0d);
|
yacht.setCurrentVelocity(0d);
|
||||||
}
|
}
|
||||||
@@ -537,7 +716,10 @@ public class GameState implements Runnable {
|
|||||||
|
|
||||||
if (hasProgressed) {
|
if (hasProgressed) {
|
||||||
if (currentMarkSeqID != 0 && !markOrder.isLastMark(currentMarkSeqID)) {
|
if (currentMarkSeqID != 0 && !markOrder.isLastMark(currentMarkSeqID)) {
|
||||||
sendServerMessage(yacht.getSourceId(), yacht.getBoatName() + " passed leg " + yacht.getLegNumber());
|
|
||||||
|
String logMessage = yacht.getBoatName() + " passed leg " + yacht.getLegNumber();
|
||||||
|
notifyMessageListeners(
|
||||||
|
MessageFactory.makeChatterMessage(yacht.getSourceId(), logMessage));
|
||||||
}
|
}
|
||||||
yacht.incrementLegNumber();
|
yacht.incrementLegNumber();
|
||||||
sendMarkRoundingMessage(yacht);
|
sendMarkRoundingMessage(yacht);
|
||||||
@@ -573,7 +755,9 @@ public class GameState implements Runnable {
|
|||||||
if (crossedLine == 2 && isClockwiseCross || crossedLine == 1 && !isClockwiseCross) {
|
if (crossedLine == 2 && isClockwiseCross || crossedLine == 1 && !isClockwiseCross) {
|
||||||
yacht.setClosestCurrentMark(mark1);
|
yacht.setClosestCurrentMark(mark1);
|
||||||
yacht.setBoatStatus(BoatStatus.RACING);
|
yacht.setBoatStatus(BoatStatus.RACING);
|
||||||
sendServerMessage(yacht.getSourceId(), yacht.getBoatName() + " passed start line");
|
String logMessage = yacht.getBoatName() + " passed start line";
|
||||||
|
notifyMessageListeners(
|
||||||
|
MessageFactory.makeChatterMessage(yacht.getSourceId(), logMessage));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -677,7 +861,10 @@ public class GameState implements Runnable {
|
|||||||
if (crossedLine == 1 && isClockwiseCross || crossedLine == 2 && !isClockwiseCross) {
|
if (crossedLine == 1 && isClockwiseCross || crossedLine == 2 && !isClockwiseCross) {
|
||||||
yacht.setClosestCurrentMark(mark1);
|
yacht.setClosestCurrentMark(mark1);
|
||||||
yacht.setBoatStatus(BoatStatus.FINISHED);
|
yacht.setBoatStatus(BoatStatus.FINISHED);
|
||||||
sendServerMessage(yacht.getSourceId(), yacht.getBoatName() + " passed finish line");
|
|
||||||
|
String logMessage = yacht.getBoatName() + " passed finish line";
|
||||||
|
notifyMessageListeners(
|
||||||
|
MessageFactory.makeChatterMessage(yacht.getSourceId(), logMessage));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -700,16 +887,20 @@ public class GameState implements Runnable {
|
|||||||
String name = new String(customizeData);
|
String name = new String(customizeData);
|
||||||
playerYacht.setBoatName(name);
|
playerYacht.setBoatName(name);
|
||||||
} else if (requestType.equals(CustomizeRequestType.COLOR)) {
|
} else if (requestType.equals(CustomizeRequestType.COLOR)) {
|
||||||
|
//This low level stuff shouldnt be here alistair! In fact no logic LIKE THIS should! - wmu16
|
||||||
int red = customizeData[0] & 0xFF;
|
int red = customizeData[0] & 0xFF;
|
||||||
int green = customizeData[1] & 0xFF;
|
int green = customizeData[1] & 0xFF;
|
||||||
int blue = customizeData[2] & 0xFF;
|
int blue = customizeData[2] & 0xFF;
|
||||||
Color yachtColor = Color.rgb(red, green, blue);
|
Color yachtColor = Color.rgb(red, green, blue);
|
||||||
playerYacht.setBoatColor(yachtColor);
|
playerYacht.setBoatColor(yachtColor);
|
||||||
|
} else if (requestType.equals(CustomizeRequestType.SHAPE)) {
|
||||||
|
String type = new String(customizeData);
|
||||||
|
playerYacht.setBoatType(BoatMeshType.valueOf(type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Mark checkMarkCollision(ServerYacht yacht) {
|
private static Mark checkMarkCollision(ServerYacht yacht) {
|
||||||
Set<Mark> marksInRace = GameState.getMarks();
|
Set<Mark> marksInRace = new HashSet<>(marks);
|
||||||
for (Mark mark : marksInRace) {
|
for (Mark mark : marksInRace) {
|
||||||
if (GeoUtility.getDistance(yacht.getLocation(), mark)
|
if (GeoUtility.getDistance(yacht.getLocation(), mark)
|
||||||
<= MARK_COLLISION_DISTANCE) {
|
<= MARK_COLLISION_DISTANCE) {
|
||||||
@@ -738,15 +929,22 @@ public class GameState implements Runnable {
|
|||||||
* Collision detection which iterates through all the yachts and check if any yacht collided
|
* Collision detection which iterates through all the yachts and check if any yacht collided
|
||||||
* with this yacht. Return collided yacht or null if no collision.
|
* with this yacht. Return collided yacht or null if no collision.
|
||||||
*
|
*
|
||||||
|
* UPDATE: HACK!!! wmu16 - forBumperCollision is (the goddamn dirtiest) dirty flag to fix a
|
||||||
|
* weird bug where the bumper collision would not be registerd but the knock back collision would.
|
||||||
|
* In other words, only set the 'forBumperCollision' flag true if used for the bumper power up.
|
||||||
|
*
|
||||||
* @return yacht to compare to all other yachts.
|
* @return yacht to compare to all other yachts.
|
||||||
*/
|
*/
|
||||||
private static ServerYacht checkYachtCollision(ServerYacht yacht) {
|
private static ServerYacht checkYachtCollision(ServerYacht yacht, Boolean forBumperCollision) {
|
||||||
|
Double collisionDistance =
|
||||||
|
(forBumperCollision) ? YACHT_COLLISION_DISTANCE + 2.5 : YACHT_COLLISION_DISTANCE;
|
||||||
|
|
||||||
for (ServerYacht otherYacht : GameState.getYachts().values()) {
|
for (ServerYacht otherYacht : GameState.getYachts().values()) {
|
||||||
if (otherYacht != yacht) {
|
if (otherYacht != yacht) {
|
||||||
Double distance = GeoUtility
|
Double distance = GeoUtility
|
||||||
.getDistance(otherYacht.getLocation(), yacht.getLocation());
|
.getDistance(otherYacht.getLocation(), yacht.getLocation());
|
||||||
if (distance < YACHT_COLLISION_DISTANCE) {
|
;
|
||||||
|
if (distance < collisionDistance) {
|
||||||
return otherYacht;
|
return otherYacht;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -782,13 +980,6 @@ public class GameState implements Runnable {
|
|||||||
roundingMark.getSourceID()));
|
roundingMark.getSourceID()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void sendServerMessage(Integer messageType, String message) {
|
|
||||||
notifyMessageListeners(new ChatterMessage(
|
|
||||||
messageType, "SERVER: " + message
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void processChatter(ChatterMessage chatterMessage, boolean isHost) {
|
public static void processChatter(ChatterMessage chatterMessage, boolean isHost) {
|
||||||
String chatterText = chatterMessage.getMessage();
|
String chatterText = chatterMessage.getMessage();
|
||||||
String[] words = chatterText.split("\\s+");
|
String[] words = chatterText.split("\\s+");
|
||||||
@@ -796,17 +987,19 @@ public class GameState implements Runnable {
|
|||||||
switch (words[2].trim()) {
|
switch (words[2].trim()) {
|
||||||
case "/speed":
|
case "/speed":
|
||||||
try {
|
try {
|
||||||
setSpeedMultiplier(Double.valueOf(words[3]));
|
serverSpeedMultiplier = Double.valueOf(words[3]);
|
||||||
sendServerMessage(chatterMessage.getMessage_type(),
|
String logMessage = "Speed modifier set to x" + words[3];
|
||||||
"Speed modifier set to x" + words[3]);
|
notifyMessageListeners(MessageFactory
|
||||||
|
.makeChatterMessage(chatterMessage.getMessageType(), logMessage));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger logger = LoggerFactory.getLogger(GameState.class);
|
Logger logger = LoggerFactory.getLogger(GameState.class);
|
||||||
logger.error("cannot parse >speed value");
|
logger.error("cannot parse >speed value");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case "/finish":
|
case "/finish":
|
||||||
sendServerMessage(chatterMessage.getMessage_type(),
|
String logMessage = "Game will now finish";
|
||||||
"Game will now finish");
|
notifyMessageListeners(MessageFactory
|
||||||
|
.makeChatterMessage(chatterMessage.getMessageType(), logMessage));
|
||||||
endRace();
|
endRace();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -863,11 +1056,7 @@ public class GameState implements Runnable {
|
|||||||
currentStage = GameStages.FINISHED;
|
currentStage = GameStages.FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setSpeedMultiplier (double multiplier) {
|
public static double getServerSpeedMultiplier() {
|
||||||
speedMultiplier = multiplier;
|
return serverSpeedMultiplier;
|
||||||
}
|
|
||||||
|
|
||||||
public static double getSpeedMultiplier () {
|
|
||||||
return speedMultiplier;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,9 +37,6 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
|
|||||||
private static final int PORT = 4942;
|
private static final int PORT = 4942;
|
||||||
private static final Integer CLIENT_UPDATES_PER_SECOND = 60;
|
private static final Integer CLIENT_UPDATES_PER_SECOND = 60;
|
||||||
|
|
||||||
private static final int MAX_WIND_SPEED = 12000;
|
|
||||||
private static final int MIN_WIND_SPEED = 8000;
|
|
||||||
|
|
||||||
private boolean terminated;
|
private boolean terminated;
|
||||||
|
|
||||||
private Thread thread;
|
private Thread thread;
|
||||||
@@ -101,8 +98,6 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
|
|||||||
GameState.addMessageEventListener(this::broadcastMessage);
|
GameState.addMessageEventListener(this::broadcastMessage);
|
||||||
terminated = false;
|
terminated = false;
|
||||||
thread = new Thread(this, "MainServer");
|
thread = new Thread(this, "MainServer");
|
||||||
startUpdatingWind();
|
|
||||||
startSpawningTokens();
|
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,63 +182,6 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void updateWind(){
|
|
||||||
Integer direction = GameState.getWindDirection().intValue();
|
|
||||||
Integer windSpeed = GameState.getWindSpeedMMS().intValue();
|
|
||||||
|
|
||||||
Random random = new Random();
|
|
||||||
|
|
||||||
if (Math.floorMod(random.nextInt(), 2) == 0){
|
|
||||||
direction += random.nextInt(4);
|
|
||||||
windSpeed += random.nextInt(20) + 459;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
direction -= random.nextInt(4);
|
|
||||||
windSpeed -= random.nextInt(20) + 459;
|
|
||||||
}
|
|
||||||
|
|
||||||
direction = Math.floorMod(direction, 360);
|
|
||||||
|
|
||||||
if (windSpeed > MAX_WIND_SPEED){
|
|
||||||
windSpeed -= random.nextInt(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (windSpeed <= MIN_WIND_SPEED){
|
|
||||||
windSpeed += random.nextInt(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
GameState.setWindSpeed(Double.valueOf(windSpeed));
|
|
||||||
GameState.setWindDirection(direction.doubleValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: 29/08/17 wmu16 - This sort of update should be in game state
|
|
||||||
private static void startUpdatingWind(){
|
|
||||||
Timer timer = new Timer();
|
|
||||||
timer.schedule(new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
updateWind();
|
|
||||||
}
|
|
||||||
}, 0, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start spawning coins every 60s after the first minute
|
|
||||||
*/
|
|
||||||
private void startSpawningTokens() {
|
|
||||||
Timer timer = new Timer();
|
|
||||||
timer.schedule(new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
GameState.spawnNewToken();
|
|
||||||
broadcastMessage(MessageFactory.getRaceXML());
|
|
||||||
}
|
|
||||||
}, 10000, 60000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A client has tried to connect to the server
|
* A client has tried to connect to the server
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import seng302.gameServer.messages.BoatLocationMessage;
|
import seng302.gameServer.messages.BoatLocationMessage;
|
||||||
import seng302.gameServer.messages.BoatSubMessage;
|
import seng302.gameServer.messages.BoatSubMessage;
|
||||||
|
import seng302.gameServer.messages.ChatterMessage;
|
||||||
import seng302.gameServer.messages.RaceStartNotificationType;
|
import seng302.gameServer.messages.RaceStartNotificationType;
|
||||||
import seng302.gameServer.messages.RaceStartStatusMessage;
|
import seng302.gameServer.messages.RaceStartStatusMessage;
|
||||||
import seng302.gameServer.messages.RaceStatus;
|
import seng302.gameServer.messages.RaceStatus;
|
||||||
@@ -136,6 +137,14 @@ public class MessageFactory {
|
|||||||
return new YachtEventCodeMessage(serverYacht.getSourceId(), YachtEventType.COLLISION);
|
return new YachtEventCodeMessage(serverYacht.getSourceId(), YachtEventType.COLLISION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a message to be sent out whenever a yacht picks up a boost
|
||||||
|
*
|
||||||
|
* @param serverYacht The yacht that has picked up a power up
|
||||||
|
* @param token The token which they picked up
|
||||||
|
* @return The corresponding YachtEventCodeMessage
|
||||||
|
*/
|
||||||
public static YachtEventCodeMessage makePickupMessage(ServerYacht serverYacht, Token token) {
|
public static YachtEventCodeMessage makePickupMessage(ServerYacht serverYacht, Token token) {
|
||||||
YachtEventType yachtEventType = null;
|
YachtEventType yachtEventType = null;
|
||||||
switch (token.getTokenType()) {
|
switch (token.getTokenType()) {
|
||||||
@@ -157,4 +166,39 @@ public class MessageFactory {
|
|||||||
}
|
}
|
||||||
return new YachtEventCodeMessage(serverYacht.getSourceId(), yachtEventType);
|
return new YachtEventCodeMessage(serverYacht.getSourceId(), yachtEventType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a message representing a certain buff / debuff for a given yacht. For now this is
|
||||||
|
* just for the bumper debuff so the affected boat is aware that it has been crashed. This could
|
||||||
|
* however be extended to render affects for all boats given a certain debuff.
|
||||||
|
*
|
||||||
|
* @param yacht The yacht affected by some status
|
||||||
|
* @param token The token indicating what status they have
|
||||||
|
* @return A YachtEventCodeMessage
|
||||||
|
*/
|
||||||
|
public static YachtEventCodeMessage makeStatusEffectMessage(ServerYacht yacht,
|
||||||
|
TokenType token) {
|
||||||
|
YachtEventType yachtEventType = null;
|
||||||
|
switch (token) {
|
||||||
|
case BUMPER:
|
||||||
|
yachtEventType = YachtEventType.BUMPER_CRASH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return new YachtEventCodeMessage(yacht.getSourceId(), yachtEventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a message to be sent out when a given yacht powers down (From a boost of any type)
|
||||||
|
*
|
||||||
|
* @param yacht The yacht that is powering down
|
||||||
|
* @return A YachtEventCodeMessage representing this action
|
||||||
|
*/
|
||||||
|
public static YachtEventCodeMessage makePowerDownMessage(ServerYacht yacht) {
|
||||||
|
return new YachtEventCodeMessage(yacht.getSourceId(), YachtEventType.POWER_DOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ChatterMessage makeChatterMessage(Integer messageType, String message) {
|
||||||
|
return new ChatterMessage(messageType, "SERVER: " + message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package seng302.gameServer;
|
package seng302.gameServer;
|
||||||
|
|
||||||
import seng302.discoveryServer.util.ServerListing;
|
|
||||||
import seng302.discoveryServer.DiscoveryServerClient;
|
|
||||||
|
|
||||||
import javax.jmdns.JmDNS;
|
import javax.jmdns.JmDNS;
|
||||||
import javax.jmdns.ServiceInfo;
|
import javax.jmdns.ServiceInfo;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -35,15 +32,12 @@ public class ServerAdvertiser {
|
|||||||
private static ServerAdvertiser instance = null;
|
private static ServerAdvertiser instance = null;
|
||||||
private static JmDNS jmdnsInstance = null;
|
private static JmDNS jmdnsInstance = null;
|
||||||
private ServiceInfo serviceInfo; // Note: Whenever this is changed, our service will be re-registered on the network.
|
private ServiceInfo serviceInfo; // Note: Whenever this is changed, our service will be re-registered on the network.
|
||||||
private DiscoveryServerClient repositoryClient;
|
|
||||||
|
|
||||||
private Hashtable<String ,String> props;
|
private Hashtable<String ,String> props;
|
||||||
|
|
||||||
private ServerAdvertiser() throws IOException{
|
private ServerAdvertiser() throws IOException{
|
||||||
jmdnsInstance = JmDNS.create(InetAddress.getByName(getLocalHostIp()));
|
jmdnsInstance = JmDNS.create(InetAddress.getByName(getLocalHostIp()));
|
||||||
|
|
||||||
repositoryClient = new DiscoveryServerClient();
|
|
||||||
|
|
||||||
props = new Hashtable<>();
|
props = new Hashtable<>();
|
||||||
props.put("map", "");
|
props.put("map", "");
|
||||||
props.put("spacesLeft", "0");
|
props.put("spacesLeft", "0");
|
||||||
@@ -132,9 +126,6 @@ public class ServerAdvertiser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
ServerListing serverListing = new ServerListing(serverName, props.get("map"), getLocalHostIp(), portNo, Integer.parseInt(props.get("capacity")));
|
|
||||||
repositoryClient.register(serverListing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,10 +7,6 @@ public class ServerDescription {
|
|||||||
private String serverName;
|
private String serverName;
|
||||||
private String mapName;
|
private String mapName;
|
||||||
private Integer numPlayers;
|
private Integer numPlayers;
|
||||||
private Long lastUpdated;
|
|
||||||
private Long lastRefreshed;
|
|
||||||
|
|
||||||
private static Long EXPIRY_INTERVAL = 5000L;
|
|
||||||
|
|
||||||
public ServerDescription(String serverName, String mapName, Integer numPlayers, Integer capacity, String address, Integer portNum){
|
public ServerDescription(String serverName, String mapName, Integer numPlayers, Integer capacity, String address, Integer portNum){
|
||||||
this.serverName = serverName;
|
this.serverName = serverName;
|
||||||
@@ -19,7 +15,6 @@ public class ServerDescription {
|
|||||||
this.address = address;
|
this.address = address;
|
||||||
this.portNum = portNum;
|
this.portNum = portNum;
|
||||||
this.capacity = capacity;
|
this.capacity = capacity;
|
||||||
lastUpdated = System.currentTimeMillis();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -85,20 +80,4 @@ public class ServerDescription {
|
|||||||
return this.getName().hashCode() + this.getAddress().hashCode() +
|
return this.getName().hashCode() + this.getAddress().hashCode() +
|
||||||
this.portNumber().hashCode() + this.getMapName().hashCode();
|
this.portNumber().hashCode() + this.getMapName().hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean hasExpired(){
|
|
||||||
return System.currentTimeMillis() - lastUpdated > EXPIRY_INTERVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean serverShouldBeRemoved() {
|
|
||||||
if (lastRefreshed == null) return false;
|
|
||||||
|
|
||||||
System.out.println("SBR" + (System.currentTimeMillis() - lastRefreshed > EXPIRY_INTERVAL));
|
|
||||||
return System.currentTimeMillis() - lastRefreshed > EXPIRY_INTERVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void hasBeenRefreshed(){
|
|
||||||
System.out.println("Was refreshed");
|
|
||||||
lastRefreshed = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import seng302.model.stream.packets.PacketType;
|
|||||||
import seng302.model.stream.packets.StreamPacket;
|
import seng302.model.stream.packets.StreamPacket;
|
||||||
import seng302.model.stream.xml.generator.RaceXMLTemplate;
|
import seng302.model.stream.xml.generator.RaceXMLTemplate;
|
||||||
import seng302.utilities.XMLGenerator;
|
import seng302.utilities.XMLGenerator;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class describing a single connection to a Client for the purposes of sending and receiving on
|
* A class describing a single connection to a Client for the purposes of sending and receiving on
|
||||||
@@ -77,7 +78,6 @@ public class ServerToClientThread implements Runnable {
|
|||||||
private List<ConnectionListener> connectionListeners = new ArrayList<>();
|
private List<ConnectionListener> connectionListeners = new ArrayList<>();
|
||||||
private DisconnectListener disconnectListener;
|
private DisconnectListener disconnectListener;
|
||||||
|
|
||||||
private ServerYacht yacht;
|
|
||||||
private Player player;
|
private Player player;
|
||||||
|
|
||||||
public ServerToClientThread(Socket socket) {
|
public ServerToClientThread(Socket socket) {
|
||||||
@@ -100,33 +100,12 @@ public class ServerToClientThread implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setUpPlayer(){
|
private void setUpPlayer(){
|
||||||
BufferedReader fn;
|
String shortName = "p" + sourceId;
|
||||||
String fName = "";
|
String longName = "player " + sourceId;
|
||||||
BufferedReader ln;
|
|
||||||
String lName = "";
|
|
||||||
|
|
||||||
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(
|
ServerYacht yacht = new ServerYacht(
|
||||||
"Yacht", sourceId, sourceId.toString(), fName, fName + " " + lName, "NZ"
|
BoatMeshType.DINGHY, sourceId, sourceId.toString(), shortName, longName, "NZ");
|
||||||
);
|
|
||||||
|
|
||||||
player = new Player(socket, yacht);
|
player = new Player(socket, yacht);
|
||||||
GameState.addYacht(sourceId, yacht);
|
GameState.addYacht(sourceId, yacht);
|
||||||
@@ -317,10 +296,6 @@ public class ServerToClientThread implements Runnable {
|
|||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerYacht getYacht() {
|
|
||||||
return yacht;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addConnectionListener(ConnectionListener listener) {
|
public void addConnectionListener(ConnectionListener listener) {
|
||||||
connectionListeners.add(listener);
|
connectionListeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ public enum BoatAction {
|
|||||||
TACK_GYBE(4),
|
TACK_GYBE(4),
|
||||||
UPWIND(5),
|
UPWIND(5),
|
||||||
DOWNWIND(6),
|
DOWNWIND(6),
|
||||||
MAINTAIN_HEADING(7);
|
MAINTAIN_HEADING(7),
|
||||||
|
CONTINUOUSLY_TURNING(8),
|
||||||
|
DEFAULT_TURNING(9);
|
||||||
|
|
||||||
private final int type;
|
private final int type;
|
||||||
private static final Map<Integer, BoatAction> intToTypeMap = new HashMap<>();
|
private static final Map<Integer, BoatAction> intToTypeMap = new HashMap<>();
|
||||||
|
|||||||
@@ -5,19 +5,19 @@ package seng302.gameServer.messages;
|
|||||||
*/
|
*/
|
||||||
public class BoatActionMessage extends Message{
|
public class BoatActionMessage extends Message{
|
||||||
private final MessageType MESSAGE_TYPE = MessageType.BOAT_ACTION;
|
private final MessageType MESSAGE_TYPE = MessageType.BOAT_ACTION;
|
||||||
private final int MESSAGE_SIZE = 1;
|
private final int MESSAGE_SIZE = 5;
|
||||||
private BoatAction actionType;
|
private BoatAction actionType;
|
||||||
|
|
||||||
public BoatActionMessage(BoatAction actionType) {
|
public BoatActionMessage(BoatAction actionType, int sourceId) {
|
||||||
this.actionType = actionType;
|
this.actionType = actionType;
|
||||||
setHeader(new Header(MessageType.BOAT_ACTION, 0, (short) 1)); // the second variable is the source id
|
setHeader(new Header(MessageType.BOAT_ACTION, sourceId, (short) MESSAGE_SIZE)); // the second variable is the source id
|
||||||
allocateBuffer();
|
allocateBuffer();
|
||||||
writeHeaderToBuffer();
|
writeHeaderToBuffer();
|
||||||
// Write message fields
|
// Write message fields
|
||||||
putInt(actionType.getValue(), 1);
|
putInt(actionType.getValue(), 1);
|
||||||
|
putInt(sourceId, 4);
|
||||||
writeCRC();
|
writeCRC();
|
||||||
rewind();
|
rewind();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class ChatterMessage extends Message {
|
|||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMessage_type() {
|
public int getMessageType() {
|
||||||
return message_type;
|
return message_type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,7 @@ public enum MessageType {
|
|||||||
REGISTRATION_REQUEST(101),
|
REGISTRATION_REQUEST(101),
|
||||||
REGISTRATION_RESPONSE(102),
|
REGISTRATION_RESPONSE(102),
|
||||||
CUSTOMIZATION_REQUEST(103),
|
CUSTOMIZATION_REQUEST(103),
|
||||||
CUSTOMIZATION_RESPONSE(104),
|
CUSTOMIZATION_RESPONSE(104);
|
||||||
REPO_REGISTRATION_REQUEST(201),
|
|
||||||
ROOM_CODE_REQUEST(202),
|
|
||||||
LOBBY_REQUEST(203);
|
|
||||||
|
|
||||||
|
|
||||||
private int code;
|
private int code;
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ package seng302.gameServer.messages;
|
|||||||
public class RegistrationRequestMessage extends Message {
|
public class RegistrationRequestMessage extends Message {
|
||||||
private static int MESSAGE_LENGTH = 2;
|
private static int MESSAGE_LENGTH = 2;
|
||||||
|
|
||||||
public RegistrationRequestMessage(ClientType type){
|
public RegistrationRequestMessage(ClientType type, int clientID){
|
||||||
setHeader(new Header(MessageType.REGISTRATION_REQUEST, 1, (short) getSize()));
|
setHeader(new Header(MessageType.REGISTRATION_REQUEST, clientID, (short) getSize()));
|
||||||
|
|
||||||
allocateBuffer();
|
allocateBuffer();
|
||||||
writeHeaderToBuffer();
|
writeHeaderToBuffer();
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
package seng302.gameServer.messages;
|
|
||||||
|
|
||||||
public class RoomCodeRequest extends Message{
|
|
||||||
private int size = 0;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RoomCodeRequest(String roomCode){
|
|
||||||
size = roomCode.length() + 6;
|
|
||||||
|
|
||||||
setHeader(new Header(MessageType.ROOM_CODE_REQUEST, 0x01, (short)getSize()));
|
|
||||||
allocateBuffer();
|
|
||||||
writeHeaderToBuffer();
|
|
||||||
|
|
||||||
putInt(roomCode.length(), 6);
|
|
||||||
putBytes(roomCode.getBytes());
|
|
||||||
|
|
||||||
writeCRC();
|
|
||||||
rewind();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
package seng302.gameServer.messages;
|
|
||||||
|
|
||||||
import seng302.discoveryServer.util.ServerListing;
|
|
||||||
|
|
||||||
public class ServerRegistrationMessage extends Message {
|
|
||||||
private int size;
|
|
||||||
|
|
||||||
public ServerRegistrationMessage(ServerListing serverListing) {
|
|
||||||
String serverName = serverListing.getServerName();
|
|
||||||
String mapName = serverListing.getMapName();
|
|
||||||
String address = serverListing.getAddress();
|
|
||||||
int port = serverListing.getPortNumber();
|
|
||||||
int players = serverListing.getPortNumber();
|
|
||||||
int capacity = serverListing.getCapacity();
|
|
||||||
String roomCode = serverListing.getRoomCode();
|
|
||||||
|
|
||||||
createMessage(serverName, mapName, address, port, players, capacity, roomCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServerRegistrationMessage(String serverName, String mapName, String address, int port, int players, int capacity, String roomCode){
|
|
||||||
createMessage(serverName, mapName, address, port, players, capacity, roomCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createMessage(String serverName, String mapName, String address, int port, int players, int capacity, String roomCode){
|
|
||||||
size = serverName.getBytes().length + mapName.length() + address.length() + roomCode.length() + 36;
|
|
||||||
|
|
||||||
setHeader(new Header(MessageType.REPO_REGISTRATION_REQUEST, 0x01, (short) getSize()));
|
|
||||||
allocateBuffer();
|
|
||||||
writeHeaderToBuffer();
|
|
||||||
|
|
||||||
int nameLength = serverName.length();
|
|
||||||
int mapNameLength = mapName.length();
|
|
||||||
int addressLength = address.length();
|
|
||||||
int roomCodeLength = roomCode.length();
|
|
||||||
|
|
||||||
// Put fields here
|
|
||||||
putInt(nameLength, 6);
|
|
||||||
putInt(mapNameLength, 6);
|
|
||||||
putInt(addressLength, 6);
|
|
||||||
putInt(roomCodeLength, 6);
|
|
||||||
|
|
||||||
putInt(port, 4);
|
|
||||||
putInt(players, 4);
|
|
||||||
putInt(capacity, 4);
|
|
||||||
|
|
||||||
putBytes(serverName.getBytes());
|
|
||||||
putBytes(mapName.getBytes());
|
|
||||||
putBytes(address.getBytes());
|
|
||||||
putBytes(roomCode.getBytes());
|
|
||||||
|
|
||||||
writeCRC();
|
|
||||||
rewind();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package seng302.gameServer.messages;
|
package seng302.gameServer.messages;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by wmu16 on 11/09/17.
|
* Enum for different event types for the yacht
|
||||||
*/
|
*/
|
||||||
public enum YachtEventType {
|
public enum YachtEventType {
|
||||||
COLLISION(33),
|
COLLISION(33),
|
||||||
@@ -9,7 +9,10 @@ public enum YachtEventType {
|
|||||||
TOKEN_BUMPER(35),
|
TOKEN_BUMPER(35),
|
||||||
TOKEN_HANDLING(36),
|
TOKEN_HANDLING(36),
|
||||||
TOKEN_WIND_WALKER(37),
|
TOKEN_WIND_WALKER(37),
|
||||||
TOKEN_RANDOM(38);
|
TOKEN_RANDOM(38),
|
||||||
|
POWER_DOWN(39),
|
||||||
|
BUMPER_CRASH(40);
|
||||||
|
|
||||||
|
|
||||||
private int code;
|
private int code;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
|
import java.util.Timer;
|
||||||
import javafx.beans.property.ReadOnlyDoubleProperty;
|
import javafx.beans.property.ReadOnlyDoubleProperty;
|
||||||
import javafx.beans.property.ReadOnlyDoubleWrapper;
|
import javafx.beans.property.ReadOnlyDoubleWrapper;
|
||||||
import javafx.beans.property.ReadOnlyIntegerProperty;
|
import javafx.beans.property.ReadOnlyIntegerProperty;
|
||||||
@@ -19,6 +20,7 @@ import jdk.nashorn.internal.objects.annotations.Function;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import seng302.model.token.TokenType;
|
import seng302.model.token.TokenType;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,15 +41,30 @@ public class ClientYacht extends Observable {
|
|||||||
void notifyRounding(ClientYacht yacht, int legNumber);
|
void notifyRounding(ClientYacht yacht, int legNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ColorChangeListener {
|
||||||
|
|
||||||
|
void notifyColorChange(ClientYacht yacht);
|
||||||
|
}
|
||||||
|
|
||||||
|
//This notifies RaceViewController so it can display icon - wmu16
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface PowerUpListener {
|
public interface PowerUpListener {
|
||||||
void notifyPowerUp(ClientYacht yacht, TokenType tokenType);
|
void notifyPowerUp(ClientYacht yacht, TokenType tokenType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//This notifies RaceViewController so it can remove token icon - wmu16
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface PowerDownListener {
|
||||||
|
void notifyPowerDown(ClientYacht yacht);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(ClientYacht.class);
|
private Logger logger = LoggerFactory.getLogger(ClientYacht.class);
|
||||||
|
|
||||||
|
|
||||||
private String boatType;
|
private BoatMeshType boatType;
|
||||||
private Integer sourceId;
|
private Integer sourceId;
|
||||||
private String hullID; //matches HullNum in the XML spec.
|
private String hullID; //matches HullNum in the XML spec.
|
||||||
private String shortName;
|
private String shortName;
|
||||||
@@ -57,7 +74,7 @@ public class ClientYacht extends Observable {
|
|||||||
private TokenType powerUp;
|
private TokenType powerUp;
|
||||||
|
|
||||||
private Long estimateTimeAtFinish;
|
private Long estimateTimeAtFinish;
|
||||||
private Boolean sailIn = false;
|
private Boolean sailIn = true;
|
||||||
private Integer currentMarkSeqID = 0;
|
private Integer currentMarkSeqID = 0;
|
||||||
private Long markRoundTime;
|
private Long markRoundTime;
|
||||||
private Long timeTillNext;
|
private Long timeTillNext;
|
||||||
@@ -67,18 +84,24 @@ public class ClientYacht extends Observable {
|
|||||||
private Integer boatStatus;
|
private Integer boatStatus;
|
||||||
private Double currentVelocity;
|
private Double currentVelocity;
|
||||||
|
|
||||||
|
Timer t;
|
||||||
|
|
||||||
private BoatObject boatObject;
|
private BoatObject boatObject;
|
||||||
|
|
||||||
private List<YachtLocationListener> locationListeners = new ArrayList<>();
|
private List<YachtLocationListener> locationListeners = new ArrayList<>();
|
||||||
private List<MarkRoundingListener> markRoundingListeners = new ArrayList<>();
|
private List<MarkRoundingListener> markRoundingListeners = new ArrayList<>();
|
||||||
private List<PowerUpListener> powerUpListeners = new ArrayList<>();
|
private List<PowerUpListener> powerUpListeners = new ArrayList<>();
|
||||||
|
private List<PowerDownListener> powerDownListeners = new ArrayList<>();
|
||||||
|
private List<ColorChangeListener> colorChangeListeners = new ArrayList<>();
|
||||||
|
|
||||||
private ReadOnlyDoubleWrapper velocityProperty = new ReadOnlyDoubleWrapper();
|
private ReadOnlyDoubleWrapper velocityProperty = new ReadOnlyDoubleWrapper();
|
||||||
private ReadOnlyLongWrapper timeTillNextProperty = new ReadOnlyLongWrapper();
|
private ReadOnlyLongWrapper timeTillNextProperty = new ReadOnlyLongWrapper();
|
||||||
private ReadOnlyLongWrapper timeSinceLastMarkProperty = new ReadOnlyLongWrapper();
|
private ReadOnlyLongWrapper timeSinceLastMarkProperty = new ReadOnlyLongWrapper();
|
||||||
private ReadOnlyIntegerWrapper placingProperty = new ReadOnlyIntegerWrapper();
|
private ReadOnlyIntegerWrapper placingProperty = new ReadOnlyIntegerWrapper();
|
||||||
|
private ReadOnlyDoubleWrapper headingProperty = new ReadOnlyDoubleWrapper();
|
||||||
private Color colour;
|
private Color colour;
|
||||||
|
|
||||||
public ClientYacht(String boatType, Integer sourceId, String hullID, String shortName,
|
public ClientYacht(BoatMeshType boatType, Integer sourceId, String hullID, String shortName,
|
||||||
String boatName, String country) {
|
String boatName, String country) {
|
||||||
this.boatType = boatType;
|
this.boatType = boatType;
|
||||||
this.sourceId = sourceId;
|
this.sourceId = sourceId;
|
||||||
@@ -88,6 +111,7 @@ public class ClientYacht extends Observable {
|
|||||||
this.country = country;
|
this.country = country;
|
||||||
this.location = new GeoPoint(57.670341, 11.826856);
|
this.location = new GeoPoint(57.670341, 11.826856);
|
||||||
this.heading = 120.0; //In degrees
|
this.heading = 120.0; //In degrees
|
||||||
|
this.headingProperty.set(this.heading);
|
||||||
this.currentVelocity = 0d;
|
this.currentVelocity = 0d;
|
||||||
this.boatStatus = 1;
|
this.boatStatus = 1;
|
||||||
this.colour = Color.rgb(0, 0, 0, 1.0);
|
this.colour = Color.rgb(0, 0, 0, 1.0);
|
||||||
@@ -102,7 +126,7 @@ public class ClientYacht extends Observable {
|
|||||||
super.addObserver(o);
|
super.addObserver(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBoatType() {
|
public BoatMeshType getBoatType() {
|
||||||
return boatType;
|
return boatType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,6 +237,21 @@ public class ClientYacht extends Observable {
|
|||||||
this.position = position;
|
this.position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Powers down the boat and notifies the raceViewController to display
|
||||||
|
*/
|
||||||
|
public void powerDown() {
|
||||||
|
this.powerUp = null;
|
||||||
|
for (PowerDownListener listener : powerDownListeners) {
|
||||||
|
listener.notifyPowerDown(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* powers up the boat and notifies the raceViewController to display
|
||||||
|
*
|
||||||
|
* @param tokenType The type of token that this boat is being powered up with
|
||||||
|
*/
|
||||||
public void setPowerUp(TokenType tokenType) {
|
public void setPowerUp(TokenType tokenType) {
|
||||||
this.powerUp = tokenType;
|
this.powerUp = tokenType;
|
||||||
for (PowerUpListener listener : powerUpListeners) {
|
for (PowerUpListener listener : powerUpListeners) {
|
||||||
@@ -246,6 +285,7 @@ public class ClientYacht extends Observable {
|
|||||||
|
|
||||||
public void setHeading(Double heading) {
|
public void setHeading(Double heading) {
|
||||||
this.heading = heading;
|
this.heading = heading;
|
||||||
|
setHeadingProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -272,12 +312,15 @@ public class ClientYacht extends Observable {
|
|||||||
|
|
||||||
public void setColour(Color colour) {
|
public void setColour(Color colour) {
|
||||||
this.colour = colour;
|
this.colour = colour;
|
||||||
|
for (ColorChangeListener listener : colorChangeListeners) {
|
||||||
|
listener.notifyColorChange(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void updateLocation(double lat, double lng, double heading, double velocity) {
|
public void updateLocation(double lat, double lng, double heading, double velocity) {
|
||||||
setLocation(lat, lng);
|
setLocation(lat, lng);
|
||||||
this.heading = heading;
|
this.heading = heading;
|
||||||
|
setHeadingProperty();
|
||||||
this.currentVelocity = velocity;
|
this.currentVelocity = velocity;
|
||||||
updateVelocityProperty(velocity);
|
updateVelocityProperty(velocity);
|
||||||
for (YachtLocationListener yll : locationListeners) {
|
for (YachtLocationListener yll : locationListeners) {
|
||||||
@@ -285,6 +328,10 @@ public class ClientYacht extends Observable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setHeadingProperty() {
|
||||||
|
headingProperty.set(heading);
|
||||||
|
}
|
||||||
|
|
||||||
public void addLocationListener(YachtLocationListener listener) {
|
public void addLocationListener(YachtLocationListener listener) {
|
||||||
locationListeners.add(listener);
|
locationListeners.add(listener);
|
||||||
}
|
}
|
||||||
@@ -297,6 +344,14 @@ public class ClientYacht extends Observable {
|
|||||||
powerUpListeners.add(listener);
|
powerUpListeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addPowerDownListener(PowerDownListener listener) {
|
||||||
|
powerDownListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addColorChangeListener(ColorChangeListener listener) {
|
||||||
|
colorChangeListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
public void removeMarkRoundingListener(MarkRoundingListener listener) {
|
public void removeMarkRoundingListener(MarkRoundingListener listener) {
|
||||||
markRoundingListeners.remove(listener);
|
markRoundingListeners.remove(listener);
|
||||||
}
|
}
|
||||||
@@ -325,4 +380,9 @@ public class ClientYacht extends Observable {
|
|||||||
public BoatObject getBoatObject() {
|
public BoatObject getBoatObject() {
|
||||||
return this.boatObject;
|
return this.boatObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReadOnlyDoubleWrapper getHeadingProperty() {
|
||||||
|
return headingProperty;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package seng302.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
|
||||||
|
public class GameKeyBind {
|
||||||
|
|
||||||
|
private static GameKeyBind instance;
|
||||||
|
private Map<KeyCode, KeyAction> keyToActionMap;
|
||||||
|
private Map<KeyAction, KeyCode> actionToKeyMap;
|
||||||
|
private Boolean continuouslyTurning;
|
||||||
|
|
||||||
|
|
||||||
|
private GameKeyBind() {
|
||||||
|
setToDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToDefault() {
|
||||||
|
actionToKeyMap = new HashMap<>();
|
||||||
|
keyToActionMap = new HashMap<>();
|
||||||
|
continuouslyTurning = false;
|
||||||
|
// default key bindings
|
||||||
|
ArrayList<KeyCode> keys = new ArrayList<>();
|
||||||
|
keys.add(KeyCode.Z);
|
||||||
|
keys.add(KeyCode.X);
|
||||||
|
keys.add(KeyCode.SPACE);
|
||||||
|
keys.add(KeyCode.SHIFT);
|
||||||
|
keys.add(KeyCode.ENTER);
|
||||||
|
keys.add(KeyCode.PAGE_UP);
|
||||||
|
keys.add(KeyCode.PAGE_DOWN);
|
||||||
|
keys.add(KeyCode.F1);
|
||||||
|
keys.add(KeyCode.D);
|
||||||
|
keys.add(KeyCode.A);
|
||||||
|
keys.add(KeyCode.W);
|
||||||
|
keys.add(KeyCode.S);
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
actionToKeyMap.put(KeyAction.getType(i + 1), keys.get(i));
|
||||||
|
keyToActionMap.put(keys.get(i), KeyAction.getType(i + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GameKeyBind getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new GameKeyBind();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyCode getKeyCode(KeyAction keyAction) {
|
||||||
|
return instance.actionToKeyMap.get(keyAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyAction getKeyAction(KeyCode keyCode) {
|
||||||
|
return instance.keyToActionMap.get(keyCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds a key to a key action
|
||||||
|
*
|
||||||
|
* @return true if successfully bind
|
||||||
|
*/
|
||||||
|
public boolean bindKeyToAction(KeyCode keyCode, KeyAction keyAction) {
|
||||||
|
if (instance.keyToActionMap.containsKey(keyCode)) {
|
||||||
|
// if the key has been bound to other action, return false
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
instance.keyToActionMap.put(keyCode, keyAction); // add key -> action
|
||||||
|
KeyCode oldKeyCode = instance.actionToKeyMap
|
||||||
|
.get(keyAction); // get old key for the action
|
||||||
|
instance.keyToActionMap.remove(oldKeyCode); // remove the old key -> action
|
||||||
|
instance.actionToKeyMap
|
||||||
|
.replace(keyAction, keyCode); // replace the old key by the newer one
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleTurningMode() {
|
||||||
|
continuouslyTurning = !continuouslyTurning;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isContinuouslyTurning() {
|
||||||
|
return continuouslyTurning;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package seng302.model;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public enum KeyAction {
|
||||||
|
ZOOM_IN(1),
|
||||||
|
ZOOM_OUT(2),
|
||||||
|
VMG(3),
|
||||||
|
SAILS_STATE(4),
|
||||||
|
TACK_GYBE(5),
|
||||||
|
UPWIND(6),
|
||||||
|
DOWNWIND(7),
|
||||||
|
VIEW(8),
|
||||||
|
RIGHT(9),
|
||||||
|
LEFT(10),
|
||||||
|
FORWARD(11),
|
||||||
|
BACKWARD(12);
|
||||||
|
|
||||||
|
private final int type;
|
||||||
|
private static final Map<Integer, KeyAction> intToTypeMap = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
for (KeyAction type : KeyAction.values()) {
|
||||||
|
intToTypeMap.put(type.getValue(), type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyAction(int type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KeyAction getType(int value) {
|
||||||
|
return intToTypeMap.get(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,9 @@ import java.io.BufferedReader;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A static class for parsing and storing the polars. Will parse the whole polar table and also store the optimised
|
* A static class for parsing and storing the polars. Will parse the whole polar table and also store the optimised
|
||||||
@@ -17,6 +19,7 @@ public final class PolarTable {
|
|||||||
private static HashMap<Double, HashMap<Double, Double>> polarTable;
|
private static HashMap<Double, HashMap<Double, Double>> polarTable;
|
||||||
private static HashMap<Double, HashMap<Double, Double>> upwindOptimal;
|
private static HashMap<Double, HashMap<Double, Double>> upwindOptimal;
|
||||||
private static HashMap<Double, HashMap<Double, Double>> downwindOptimal;
|
private static HashMap<Double, HashMap<Double, Double>> downwindOptimal;
|
||||||
|
private static Double optimalAngle;
|
||||||
|
|
||||||
private static int upTwaIndex;
|
private static int upTwaIndex;
|
||||||
private static int dnTwaIndex;
|
private static int dnTwaIndex;
|
||||||
@@ -33,11 +36,13 @@ public final class PolarTable {
|
|||||||
upwindOptimal = new HashMap<>();
|
upwindOptimal = new HashMap<>();
|
||||||
downwindOptimal = new HashMap<>();
|
downwindOptimal = new HashMap<>();
|
||||||
|
|
||||||
String line;
|
String line = null;
|
||||||
|
String check;
|
||||||
Boolean isHeaderLine = true;
|
Boolean isHeaderLine = true;
|
||||||
|
|
||||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(polarFile))) {
|
try (BufferedReader br = new BufferedReader(new InputStreamReader(polarFile))) {
|
||||||
while ((line = br.readLine()) != null) {
|
while ((check = br.readLine()) != null) {
|
||||||
|
line = check;
|
||||||
String[] thisLine = line.split(",");
|
String[] thisLine = line.split(",");
|
||||||
|
|
||||||
//Initial line in file
|
//Initial line in file
|
||||||
@@ -66,7 +71,10 @@ public final class PolarTable {
|
|||||||
upwindOptimal.put(thisWindSpeed, thisUpWindPolar);
|
upwindOptimal.put(thisWindSpeed, thisUpWindPolar);
|
||||||
downwindOptimal.put(thisWindSpeed, thisDnWindPolar);
|
downwindOptimal.put(thisWindSpeed, thisDnWindPolar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
getMaxSpeedAngle(line);
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("[PolarTable] IO exception");
|
System.out.println("[PolarTable] IO exception");
|
||||||
@@ -74,6 +82,27 @@ public final class PolarTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Passes the final line of the polar table and iterates over the speeds for each
|
||||||
|
* angle, velocity pair to find the angle that produces the highest velocity
|
||||||
|
*
|
||||||
|
* @param line The last line of the polar file
|
||||||
|
*/
|
||||||
|
private static void getMaxSpeedAngle(String line) {
|
||||||
|
String[] theLastLine = line.split(",");
|
||||||
|
Double maxWindVal = Double.parseDouble(theLastLine[0]);
|
||||||
|
Double optimalAngle = Double.parseDouble(theLastLine[1]);
|
||||||
|
Double maxSpeed = Double.parseDouble(theLastLine[2]);
|
||||||
|
for (Map.Entry<Double, Double> entry : polarTable.get(maxWindVal).entrySet()) {
|
||||||
|
if (entry.getValue() > maxSpeed) {
|
||||||
|
maxSpeed = entry.getValue();
|
||||||
|
optimalAngle = entry.getKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PolarTable.optimalAngle = optimalAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the header line of a polar file
|
* Parses the header line of a polar file
|
||||||
@@ -85,14 +114,18 @@ public final class PolarTable {
|
|||||||
String thisItem = thisLine[i];
|
String thisItem = thisLine[i];
|
||||||
if (thisItem.toLowerCase().startsWith("uptwa")) {
|
if (thisItem.toLowerCase().startsWith("uptwa")) {
|
||||||
upTwaIndex = i;
|
upTwaIndex = i;
|
||||||
}
|
} else if (thisItem.toLowerCase().startsWith("dntwa")) {
|
||||||
else if (thisItem.toLowerCase().startsWith("dntwa")) {
|
|
||||||
dnTwaIndex = i;
|
dnTwaIndex = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Double getOptimalAngle() {
|
||||||
|
return optimalAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The entire polar table
|
* @return The entire polar table
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package seng302.model;
|
package seng302.model;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -8,10 +9,7 @@ import seng302.gameServer.messages.BoatStatus;
|
|||||||
import seng302.model.mark.Mark;
|
import seng302.model.mark.Mark;
|
||||||
import seng302.model.token.TokenType;
|
import seng302.model.token.TokenType;
|
||||||
import seng302.utilities.GeoUtility;
|
import seng302.utilities.GeoUtility;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Observable;
|
|
||||||
import java.util.Observer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Yacht class for the racing boat. <p> Class created to store more variables (eg. boat statuses)
|
* Yacht class for the racing boat. <p> Class created to store more variables (eg. boat statuses)
|
||||||
@@ -20,12 +18,14 @@ import java.util.Observer;
|
|||||||
*/
|
*/
|
||||||
public class ServerYacht {
|
public class ServerYacht {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(ClientYacht.class);
|
private Logger logger = LoggerFactory.getLogger(ServerYacht.class);
|
||||||
|
|
||||||
public static final Double TURN_STEP = 5.0;
|
|
||||||
|
|
||||||
//Boat info
|
//Boat info
|
||||||
private String boatType;
|
private BoatMeshType boatType;
|
||||||
|
private Double turnStep = 5.0;
|
||||||
|
private Double boatTypeSpeedMultiplier = 1.0;
|
||||||
|
private Double boatTypeTurnStepMultiplier = 1.0;
|
||||||
|
private Double boatTypeAccelerationMultiplier = 1.0;
|
||||||
private Integer sourceId;
|
private Integer sourceId;
|
||||||
private String hullID; //matches HullNum in the XML spec.
|
private String hullID; //matches HullNum in the XML spec.
|
||||||
private String shortName;
|
private String shortName;
|
||||||
@@ -55,11 +55,15 @@ public class ServerYacht {
|
|||||||
//PowerUp
|
//PowerUp
|
||||||
private TokenType powerUp;
|
private TokenType powerUp;
|
||||||
private Long powerUpStartTime;
|
private Long powerUpStartTime;
|
||||||
|
private Double powerUpSpeedMultiplier;
|
||||||
|
private Integer powerUpHandlingMultiplier;
|
||||||
|
|
||||||
|
//turning mode
|
||||||
|
private Boolean continuouslyTurning;
|
||||||
|
|
||||||
public ServerYacht(String boatType, Integer sourceId, String hullID, String shortName,
|
public ServerYacht(BoatMeshType boatType, Integer sourceId, String hullID, String shortName,
|
||||||
String boatName, String country) {
|
String boatName, String country) {
|
||||||
this.boatType = boatType;
|
setBoatType(boatType);
|
||||||
this.boatStatus = BoatStatus.PRESTART;
|
this.boatStatus = BoatStatus.PRESTART;
|
||||||
this.sourceId = sourceId;
|
this.sourceId = sourceId;
|
||||||
this.hullID = hullID;
|
this.hullID = hullID;
|
||||||
@@ -76,10 +80,12 @@ public class ServerYacht {
|
|||||||
this.legNumber = 0;
|
this.legNumber = 0;
|
||||||
this.boatColor = Colors.getColor(sourceId - 1);
|
this.boatColor = Colors.getColor(sourceId - 1);
|
||||||
this.powerUp = null;
|
this.powerUp = null;
|
||||||
|
this.powerUpSpeedMultiplier = 1d;
|
||||||
|
this.powerUpHandlingMultiplier = 1;
|
||||||
this.hasEnteredRoundingZone = false;
|
this.hasEnteredRoundingZone = false;
|
||||||
this.hasPassedLine = false;
|
this.hasPassedLine = false;
|
||||||
this.hasPassedThroughGate = false;
|
this.hasPassedThroughGate = false;
|
||||||
|
this.continuouslyTurning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -106,13 +112,33 @@ public class ServerYacht {
|
|||||||
location = geoPoint;
|
location = geoPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Powers up a yacht with a given yacht, only after powering it down first to avoid double power
|
||||||
|
* ups
|
||||||
|
*
|
||||||
|
* @param powerUp The given power up
|
||||||
|
*/
|
||||||
public void powerUp(TokenType powerUp) {
|
public void powerUp(TokenType powerUp) {
|
||||||
|
powerDown();
|
||||||
|
switch (powerUp) {
|
||||||
|
case BOOST:
|
||||||
|
powerUpSpeedMultiplier = GameState.VELOCITY_BOOST_MULTIPLIER;
|
||||||
|
break;
|
||||||
|
case HANDLING:
|
||||||
|
powerUpHandlingMultiplier = GameState.HANDLING_BOOST_MULTIPLIER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
this.powerUp = powerUp;
|
this.powerUp = powerUp;
|
||||||
powerUpStartTime = System.currentTimeMillis();
|
powerUpStartTime = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Powers down a yacht, returning its power multipliers back to 1
|
||||||
|
*/
|
||||||
public void powerDown() {
|
public void powerDown() {
|
||||||
this.powerUp = null;
|
this.powerUp = null;
|
||||||
|
this.powerUpSpeedMultiplier = 1d;
|
||||||
|
this.powerUpHandlingMultiplier = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getPowerUpStartTime() {
|
public Long getPowerUpStartTime() {
|
||||||
@@ -129,7 +155,7 @@ public class ServerYacht {
|
|||||||
* @param amount the amount by which to adjust the boat heading.
|
* @param amount the amount by which to adjust the boat heading.
|
||||||
*/
|
*/
|
||||||
public void adjustHeading(Double amount) {
|
public void adjustHeading(Double amount) {
|
||||||
Double newVal = heading + amount;
|
Double newVal = heading + amount * powerUpHandlingMultiplier * boatTypeTurnStepMultiplier;
|
||||||
lastHeading = heading;
|
lastHeading = heading;
|
||||||
heading = (double) Math.floorMod(newVal.longValue(), 360L);
|
heading = (double) Math.floorMod(newVal.longValue(), 360L);
|
||||||
}
|
}
|
||||||
@@ -152,11 +178,11 @@ public class ServerYacht {
|
|||||||
/**
|
/**
|
||||||
* Enables the boats auto pilot feature, which will move the boat towards a given heading.
|
* Enables the boats auto pilot feature, which will move the boat towards a given heading.
|
||||||
*
|
*
|
||||||
* @param thisHeading The heading to move the boat towards.
|
* @param newHeading The heading to move the boat towards.
|
||||||
*/
|
*/
|
||||||
private void setAutoPilot(Double thisHeading) {
|
private void setAutoPilot(Double newHeading) {
|
||||||
isAuto = true;
|
isAuto = true;
|
||||||
autoHeading = thisHeading;
|
autoHeading = newHeading;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -174,8 +200,9 @@ public class ServerYacht {
|
|||||||
if (isAuto) {
|
if (isAuto) {
|
||||||
turnTowardsHeading(autoHeading);
|
turnTowardsHeading(autoHeading);
|
||||||
if (Math.abs(heading - autoHeading)
|
if (Math.abs(heading - autoHeading)
|
||||||
<= TURN_STEP) { //Cancel when within 1 turn step of target.
|
<= turnStep*1.5) {
|
||||||
isAuto = false;
|
isAuto = false;
|
||||||
|
setHeading(autoHeading);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,44 +214,52 @@ public class ServerYacht {
|
|||||||
public void turnUpwind() {
|
public void turnUpwind() {
|
||||||
disableAutoPilot();
|
disableAutoPilot();
|
||||||
Double normalizedHeading = normalizeHeading();
|
Double normalizedHeading = normalizeHeading();
|
||||||
if (normalizedHeading == 0) {
|
if (continuouslyTurning) {
|
||||||
if (lastHeading < 180) {
|
adjustHeading(turnStep);
|
||||||
adjustHeading(-TURN_STEP);
|
|
||||||
} else {
|
|
||||||
adjustHeading(TURN_STEP);
|
|
||||||
}
|
|
||||||
} else if (normalizedHeading == 180) {
|
|
||||||
if (lastHeading < 180) {
|
|
||||||
adjustHeading(TURN_STEP);
|
|
||||||
} else {
|
|
||||||
adjustHeading(-TURN_STEP);
|
|
||||||
}
|
|
||||||
} else if (normalizedHeading < 180) {
|
|
||||||
adjustHeading(-TURN_STEP);
|
|
||||||
} else {
|
} else {
|
||||||
adjustHeading(TURN_STEP);
|
if (normalizedHeading == 0) {
|
||||||
|
if (lastHeading < 180) {
|
||||||
|
adjustHeading(-turnStep);
|
||||||
|
} else {
|
||||||
|
adjustHeading(turnStep);
|
||||||
|
}
|
||||||
|
} else if (normalizedHeading == 180) {
|
||||||
|
if (lastHeading < 180) {
|
||||||
|
adjustHeading(turnStep);
|
||||||
|
} else {
|
||||||
|
adjustHeading(-turnStep);
|
||||||
|
}
|
||||||
|
} else if (normalizedHeading < 180) {
|
||||||
|
adjustHeading(-turnStep);
|
||||||
|
} else {
|
||||||
|
adjustHeading(turnStep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void turnDownwind() {
|
public void turnDownwind() {
|
||||||
disableAutoPilot();
|
disableAutoPilot();
|
||||||
Double normalizedHeading = normalizeHeading();
|
Double normalizedHeading = normalizeHeading();
|
||||||
if (normalizedHeading == 0) {
|
if (continuouslyTurning) {
|
||||||
if (lastHeading < 180) {
|
adjustHeading(-turnStep);
|
||||||
adjustHeading(TURN_STEP);
|
|
||||||
} else {
|
|
||||||
adjustHeading(-TURN_STEP);
|
|
||||||
}
|
|
||||||
} else if (normalizedHeading == 180) {
|
|
||||||
if (lastHeading < 180) {
|
|
||||||
adjustHeading(-TURN_STEP);
|
|
||||||
} else {
|
|
||||||
adjustHeading(TURN_STEP);
|
|
||||||
}
|
|
||||||
} else if (normalizedHeading < 180) {
|
|
||||||
adjustHeading(TURN_STEP);
|
|
||||||
} else {
|
} else {
|
||||||
adjustHeading(-TURN_STEP);
|
if (normalizedHeading == 0) {
|
||||||
|
if (lastHeading < 180) {
|
||||||
|
adjustHeading(turnStep);
|
||||||
|
} else {
|
||||||
|
adjustHeading(-turnStep);
|
||||||
|
}
|
||||||
|
} else if (normalizedHeading == 180) {
|
||||||
|
if (lastHeading < 180) {
|
||||||
|
adjustHeading(-turnStep);
|
||||||
|
} else {
|
||||||
|
adjustHeading(turnStep);
|
||||||
|
}
|
||||||
|
} else if (normalizedHeading < 180) {
|
||||||
|
adjustHeading(turnStep);
|
||||||
|
} else {
|
||||||
|
adjustHeading(-turnStep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +288,7 @@ public class ServerYacht {
|
|||||||
|
|
||||||
// Take optimal heading and turn into a boat heading rather than a wind heading.
|
// Take optimal heading and turn into a boat heading rather than a wind heading.
|
||||||
optimalHeading =
|
optimalHeading =
|
||||||
optimalHeading + GameState.getWindDirection();
|
(optimalHeading + GameState.getWindDirection()) % 360;
|
||||||
|
|
||||||
setAutoPilot(optimalHeading);
|
setAutoPilot(optimalHeading);
|
||||||
}
|
}
|
||||||
@@ -268,9 +303,9 @@ public class ServerYacht {
|
|||||||
private void turnTowardsHeading(Double newHeading) {
|
private void turnTowardsHeading(Double newHeading) {
|
||||||
Double newVal = heading - newHeading;
|
Double newVal = heading - newHeading;
|
||||||
if (Math.floorMod(newVal.longValue(), 360L) > 180) {
|
if (Math.floorMod(newVal.longValue(), 360L) > 180) {
|
||||||
adjustHeading(TURN_STEP / 5);
|
adjustHeading(turnStep / 5);
|
||||||
} else {
|
} else {
|
||||||
adjustHeading(-TURN_STEP / 5);
|
adjustHeading(-turnStep / 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,4 +456,43 @@ public class ServerYacht {
|
|||||||
return boatColor;
|
return boatColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBoatType(BoatMeshType boatType) {
|
||||||
|
this.boatTypeAccelerationMultiplier = boatType.accelerationMultiplier;
|
||||||
|
this.boatTypeSpeedMultiplier = boatType.maxSpeedMultiplier;
|
||||||
|
this.boatTypeTurnStepMultiplier = boatType.turnStep;
|
||||||
|
this.boatType = boatType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getBoatTypeSpeedMultiplier() {
|
||||||
|
return boatTypeSpeedMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getBoatTypeAccelerationMultiplier() {
|
||||||
|
return boatTypeAccelerationMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public BoatMeshType getBoatType() {
|
||||||
|
return boatType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContinuouslyTurning(Boolean continuouslyTurning) {
|
||||||
|
this.continuouslyTurning = continuouslyTurning;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getPowerUpSpeedMultiplier() {
|
||||||
|
return powerUpSpeedMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPowerUpSpeedMultiplier(Double powerUpSpeedMultiplier) {
|
||||||
|
this.powerUpSpeedMultiplier = powerUpSpeedMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPowerUpHandlingMultiplier() {
|
||||||
|
return powerUpHandlingMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPowerUpHandlingMultiplier(Integer powerUpHandlingMultiplier) {
|
||||||
|
this.powerUpHandlingMultiplier = powerUpHandlingMultiplier;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,9 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
public class MarkOrder {
|
public class MarkOrder {
|
||||||
private List<CompoundMark> raceMarkOrder;
|
private List<CompoundMark> raceMarkOrder;
|
||||||
|
private List<CompoundMark> orderedUniqueCompoundMarks;
|
||||||
private Logger logger = LoggerFactory.getLogger(MarkOrder.class);
|
private Logger logger = LoggerFactory.getLogger(MarkOrder.class);
|
||||||
private Set<Mark> allMarks;
|
private List<Mark> allMarks;
|
||||||
|
|
||||||
public MarkOrder(){
|
public MarkOrder(){
|
||||||
loadRaceProperties();
|
loadRaceProperties();
|
||||||
@@ -44,6 +45,10 @@ public class MarkOrder {
|
|||||||
return Collections.unmodifiableList(raceMarkOrder);
|
return Collections.unmodifiableList(raceMarkOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<CompoundMark> getOrderedUniqueCompoundMarks() {
|
||||||
|
return orderedUniqueCompoundMarks;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param seqID The seqID of the current mark the boat is heading to
|
* @param seqID The seqID of the current mark the boat is heading to
|
||||||
* @return A Boolean indicating if this coming mark is the last one (finish line)
|
* @return A Boolean indicating if this coming mark is the last one (finish line)
|
||||||
@@ -75,8 +80,8 @@ public class MarkOrder {
|
|||||||
return raceMarkOrder.get(currentSeqID + 1);
|
return raceMarkOrder.get(currentSeqID + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Mark> getAllMarks(){
|
public List<Mark> getAllMarks() {
|
||||||
return Collections.unmodifiableSet(allMarks);
|
return Collections.unmodifiableList(allMarks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,7 +94,7 @@ public class MarkOrder {
|
|||||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||||
DocumentBuilder db;
|
DocumentBuilder db;
|
||||||
Document doc;
|
Document doc;
|
||||||
allMarks = new HashSet<>();
|
allMarks = new ArrayList<>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
db = dbf.newDocumentBuilder();
|
db = dbf.newDocumentBuilder();
|
||||||
@@ -105,6 +110,7 @@ public class MarkOrder {
|
|||||||
logger.debug("Loaded RaceXML for mark order");
|
logger.debug("Loaded RaceXML for mark order");
|
||||||
List<Corner> corners = data.getMarkSequence();
|
List<Corner> corners = data.getMarkSequence();
|
||||||
Map<Integer, CompoundMark> marks = data.getCompoundMarks();
|
Map<Integer, CompoundMark> marks = data.getCompoundMarks();
|
||||||
|
orderedUniqueCompoundMarks = new ArrayList<>(marks.values());
|
||||||
List<CompoundMark> course = new ArrayList<>();
|
List<CompoundMark> course = new ArrayList<>();
|
||||||
for (Corner corner : corners){
|
for (Corner corner : corners){
|
||||||
CompoundMark compoundMark = marks.get(corner.getCompoundMarkID());
|
CompoundMark compoundMark = marks.get(corner.getCompoundMarkID());
|
||||||
|
|||||||
@@ -20,9 +20,7 @@ public enum PacketType {
|
|||||||
RACE_REGISTRATION_REQUEST,
|
RACE_REGISTRATION_REQUEST,
|
||||||
RACE_REGISTRATION_RESPONSE,
|
RACE_REGISTRATION_RESPONSE,
|
||||||
RACE_CUSTOMIZATION_REQUEST,
|
RACE_CUSTOMIZATION_REQUEST,
|
||||||
RACE_CUSTOMIZATION_RESPONSE,
|
RACE_CUSTOMIZATION_RESPONSE;
|
||||||
|
|
||||||
SERVER_REGISTRATION, ROOM_CODE_REQUEST, LOBBY_REQUEST;
|
|
||||||
|
|
||||||
public static PacketType assignPacketType(int packetType, byte[] payload){
|
public static PacketType assignPacketType(int packetType, byte[] payload){
|
||||||
switch(packetType){
|
switch(packetType){
|
||||||
@@ -67,10 +65,6 @@ public enum PacketType {
|
|||||||
return RACE_CUSTOMIZATION_REQUEST;
|
return RACE_CUSTOMIZATION_REQUEST;
|
||||||
case 104:
|
case 104:
|
||||||
return RACE_CUSTOMIZATION_RESPONSE;
|
return RACE_CUSTOMIZATION_RESPONSE;
|
||||||
case 201:
|
|
||||||
return SERVER_REGISTRATION;
|
|
||||||
case 202:
|
|
||||||
return ROOM_CODE_REQUEST;
|
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
return OTHER;
|
return OTHER;
|
||||||
|
|||||||
@@ -15,11 +15,24 @@ public class Token extends GeoPoint {
|
|||||||
private TokenType tokenType;
|
private TokenType tokenType;
|
||||||
private Random random = new Random();
|
private Random random = new Random();
|
||||||
|
|
||||||
|
//Constructor for creating a specific type client side
|
||||||
public Token(TokenType tokenType, double lat, double lng) {
|
public Token(TokenType tokenType, double lat, double lng) {
|
||||||
super(lat, lng);
|
super(lat, lng);
|
||||||
this.tokenType = tokenType;
|
this.tokenType = tokenType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Making random type server side
|
||||||
|
public Token(double lat, double lng) {
|
||||||
|
super(lat, lng);
|
||||||
|
assignRandomType();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Making random type server side
|
||||||
|
public Token(GeoPoint geoPoint) {
|
||||||
|
super(geoPoint.getLat(), geoPoint.getLng());
|
||||||
|
assignRandomType();
|
||||||
|
}
|
||||||
|
|
||||||
public TokenType getTokenType() {
|
public TokenType getTokenType() {
|
||||||
return tokenType;
|
return tokenType;
|
||||||
}
|
}
|
||||||
@@ -40,5 +53,10 @@ public class Token extends GeoPoint {
|
|||||||
tokenType = tokenTypeList.get(random.nextInt(tokenTypeList.size()));
|
tokenType = tokenTypeList.get(random.nextInt(tokenTypeList.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exists for testing purposes only
|
||||||
|
*/
|
||||||
|
public void assignType(TokenType tokenType) {
|
||||||
|
this.tokenType = tokenType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package seng302.utilities;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import seng302.model.GeoPoint;
|
||||||
|
import seng302.model.mark.CompoundMark;
|
||||||
|
import seng302.model.token.Token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class for generating and spawning tokens in random locations
|
||||||
|
* Created by wmu16 on 27/09/17.
|
||||||
|
*/
|
||||||
|
public class RandomSpawn {
|
||||||
|
|
||||||
|
private static final Integer DEGREES_IN_CIRCLE = 360;
|
||||||
|
|
||||||
|
private HashMap<GeoPoint, Double> spawnRadii;
|
||||||
|
private Random random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param markOrder this must be the ORDERED list of marks. Better yet UNIQUE to avoid over
|
||||||
|
* computation
|
||||||
|
*/
|
||||||
|
public RandomSpawn(List<CompoundMark> markOrder) {
|
||||||
|
this.spawnRadii = new HashMap<>();
|
||||||
|
random = new Random();
|
||||||
|
|
||||||
|
spawnRadii = generateSpawnRadii(markOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HashMap<GeoPoint, Double> generateSpawnRadii(List<CompoundMark> markOrder) {
|
||||||
|
HashMap<GeoPoint, Double> spawnRadii = new HashMap<>();
|
||||||
|
for (int i = 0; i < markOrder.size() - 1; i++) {
|
||||||
|
GeoPoint spawnCentre = GeoUtility.getDirtyMidPoint(
|
||||||
|
markOrder.get(i).getMidPoint(),
|
||||||
|
markOrder.get(i + 1).getMidPoint());
|
||||||
|
|
||||||
|
Double distance = GeoUtility.getDistance(spawnCentre, markOrder.get(i).getMidPoint());
|
||||||
|
spawnRadii.put(spawnCentre, distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
return spawnRadii;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A random token type at a random location in a random radii of the set of possible
|
||||||
|
* radii
|
||||||
|
*/
|
||||||
|
public Token getRandomTokenLocation() {
|
||||||
|
Object[] keys = spawnRadii.keySet().toArray();
|
||||||
|
GeoPoint randomSpawnCentre = (GeoPoint) keys[random.nextInt(keys.length)];
|
||||||
|
Double spawnRadius = spawnRadii.get(randomSpawnCentre);
|
||||||
|
Double randomDistance = spawnRadius * random.nextDouble();
|
||||||
|
Double randomAngle = random.nextDouble() * DEGREES_IN_CIRCLE;
|
||||||
|
GeoPoint randomLocation = GeoUtility
|
||||||
|
.getGeoCoordinate(randomSpawnCentre, randomAngle, randomDistance);
|
||||||
|
return new Token(randomLocation);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,8 +14,10 @@ public class Sounds {
|
|||||||
private static MediaPlayer soundEffect;
|
private static MediaPlayer soundEffect;
|
||||||
private static MediaPlayer soundPlayer;
|
private static MediaPlayer soundPlayer;
|
||||||
private static MediaPlayer hoverSoundPlayer;
|
private static MediaPlayer hoverSoundPlayer;
|
||||||
|
private static MediaPlayer crashSoundPlayer;
|
||||||
|
|
||||||
private static boolean hoverInitialized = false;
|
private static boolean hoverInitialized = false;
|
||||||
|
private static boolean crashInitialized = false;
|
||||||
private static boolean musicMuted = false;
|
private static boolean musicMuted = false;
|
||||||
private static boolean soundEffectsMuted = false;
|
private static boolean soundEffectsMuted = false;
|
||||||
|
|
||||||
@@ -155,11 +157,17 @@ public class Sounds {
|
|||||||
|
|
||||||
public static void playCrashSound() {
|
public static void playCrashSound() {
|
||||||
if (!soundEffectsMuted) {
|
if (!soundEffectsMuted) {
|
||||||
Media crashSound = new Media(
|
if (!crashInitialized) {
|
||||||
Sounds.class.getClassLoader().getResource("sounds/Large-metal-door-slam.mp3")
|
Media pickupSound = new Media(
|
||||||
.toString());
|
Sounds.class.getClassLoader().getResource("sounds/Large-metal-door-slam.mp3")
|
||||||
soundPlayer = new MediaPlayer(crashSound);
|
.toString());
|
||||||
soundPlayer.play();
|
crashSoundPlayer = new MediaPlayer(pickupSound);
|
||||||
|
crashInitialized = true;
|
||||||
|
}
|
||||||
|
if (crashSoundPlayer != null) {
|
||||||
|
crashSoundPlayer.stop();
|
||||||
|
}
|
||||||
|
crashSoundPlayer.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,10 +184,10 @@ public class Sounds {
|
|||||||
public static void playHoverSound() {
|
public static void playHoverSound() {
|
||||||
if (!soundEffectsMuted) {
|
if (!soundEffectsMuted) {
|
||||||
if (!hoverInitialized) {
|
if (!hoverInitialized) {
|
||||||
Media crashSound = new Media(
|
Media hoverSound = new Media(
|
||||||
Sounds.class.getClassLoader().getResource("sounds/Error-sound-effect.mp3")
|
Sounds.class.getClassLoader().getResource("sounds/Error-sound-effect.mp3")
|
||||||
.toString());
|
.toString());
|
||||||
hoverSoundPlayer = new MediaPlayer(crashSound);
|
hoverSoundPlayer = new MediaPlayer(hoverSound);
|
||||||
hoverInitialized = true;
|
hoverInitialized = true;
|
||||||
}
|
}
|
||||||
hoverSoundPlayer.setVolume(0.5);
|
hoverSoundPlayer.setVolume(0.5);
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ import java.util.ArrayList;
|
|||||||
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.Random;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
import seng302.model.ClientYacht;
|
import seng302.model.ClientYacht;
|
||||||
|
import seng302.model.Colors;
|
||||||
import seng302.model.Limit;
|
import seng302.model.Limit;
|
||||||
import seng302.model.mark.CompoundMark;
|
import seng302.model.mark.CompoundMark;
|
||||||
import seng302.model.mark.Corner;
|
import seng302.model.mark.Corner;
|
||||||
@@ -18,6 +20,7 @@ import seng302.model.stream.xml.parser.RaceXMLData;
|
|||||||
import seng302.model.stream.xml.parser.RegattaXMLData;
|
import seng302.model.stream.xml.parser.RegattaXMLData;
|
||||||
import seng302.model.token.Token;
|
import seng302.model.token.Token;
|
||||||
import seng302.model.token.TokenType;
|
import seng302.model.token.TokenType;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utilities for parsing XML documents
|
* Utilities for parsing XML documents
|
||||||
@@ -138,17 +141,27 @@ public class XMLParser {
|
|||||||
Node currentBoat = boatsList.item(i);
|
Node currentBoat = boatsList.item(i);
|
||||||
if (currentBoat.getNodeName().equals("Boat")) {
|
if (currentBoat.getNodeName().equals("Boat")) {
|
||||||
// Boat boat = new Boat(currentBoat);
|
// Boat boat = new Boat(currentBoat);
|
||||||
|
BoatMeshType boatMeshType;
|
||||||
|
try {
|
||||||
|
boatMeshType = BoatMeshType.valueOf(XMLParser.getNodeAttributeString(currentBoat, "Type"));
|
||||||
|
} catch (IllegalArgumentException e){
|
||||||
|
boatMeshType = BoatMeshType.DINGHY;
|
||||||
|
}
|
||||||
|
Color color;
|
||||||
|
try {
|
||||||
|
color = Color.web(getNodeAttributeString(currentBoat, "Color"));
|
||||||
|
} catch (NullPointerException npe) {
|
||||||
|
color = Colors.getColor(new Random().nextInt(8));
|
||||||
|
}
|
||||||
ClientYacht yacht = new ClientYacht(
|
ClientYacht yacht = new ClientYacht(
|
||||||
XMLParser.getNodeAttributeString(currentBoat, "Type"),
|
boatMeshType,
|
||||||
XMLParser.getNodeAttributeInt(currentBoat, "SourceID"),
|
XMLParser.getNodeAttributeInt(currentBoat, "SourceID"),
|
||||||
XMLParser.getNodeAttributeString(currentBoat, "HullNum"),
|
XMLParser.getNodeAttributeString(currentBoat, "HullNum"),
|
||||||
XMLParser.getNodeAttributeString(currentBoat, "ShortName"),
|
XMLParser.getNodeAttributeString(currentBoat, "ShortName"),
|
||||||
XMLParser.getNodeAttributeString(currentBoat, "BoatName"),
|
XMLParser.getNodeAttributeString(currentBoat, "BoatName"),
|
||||||
XMLParser.getNodeAttributeString(currentBoat, "Country"));
|
XMLParser.getNodeAttributeString(currentBoat, "Country"));
|
||||||
yacht.setColour(Color.web(getNodeAttributeString(currentBoat, "Color")));
|
yacht.setColour(color);
|
||||||
if (yacht.getBoatType().equals("Yacht")) {
|
competingBoats.put(yacht.getSourceId(), yacht);
|
||||||
competingBoats.put(yacht.getSourceId(), yacht);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return competingBoats;
|
return competingBoats;
|
||||||
@@ -196,17 +209,20 @@ public class XMLParser {
|
|||||||
*/
|
*/
|
||||||
private static List<Token> extractTokens(Element docEle) {
|
private static List<Token> extractTokens(Element docEle) {
|
||||||
List<Token> tokens = new ArrayList<>();
|
List<Token> tokens = new ArrayList<>();
|
||||||
NodeList tokenList = docEle.getElementsByTagName("Tokens").item(0).getChildNodes();
|
try {
|
||||||
for (int i = 0; i < tokenList.getLength(); i++) {
|
NodeList tokenList = docEle.getElementsByTagName("Tokens").item(0).getChildNodes();
|
||||||
Node tokenNode = tokenList.item(i);
|
for (int i = 0; i < tokenList.getLength(); i++) {
|
||||||
if (tokenNode.getNodeName().equals("Token")) {
|
Node tokenNode = tokenList.item(i);
|
||||||
String tokenType = getNodeAttributeString(tokenNode, "TokenType");
|
if (tokenNode.getNodeName().equals("Token")) {
|
||||||
Double lat = getNodeAttributeDouble(tokenNode, "TargetLat");
|
String tokenType = getNodeAttributeString(tokenNode, "TokenType");
|
||||||
Double lng = getNodeAttributeDouble(tokenNode, "TargetLng");
|
Double lat = getNodeAttributeDouble(tokenNode, "TargetLat");
|
||||||
tokens.add(new Token(TokenType.valueOf(tokenType), lat, lng));
|
Double lng = getNodeAttributeDouble(tokenNode, "TargetLng");
|
||||||
|
tokens.add(new Token(TokenType.valueOf(tokenType), lat, lng));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (NullPointerException npe) {
|
||||||
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ public class ClientToServerThread implements Runnable {
|
|||||||
* Sends a request to the server asking for a source ID
|
* Sends a request to the server asking for a source ID
|
||||||
*/
|
*/
|
||||||
private void sendRegistrationRequest() {
|
private void sendRegistrationRequest() {
|
||||||
RegistrationRequestMessage requestMessage = new RegistrationRequestMessage(ClientType.PLAYER);
|
RegistrationRequestMessage requestMessage = new RegistrationRequestMessage(ClientType.PLAYER, clientId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
os.write(requestMessage.getBuffer());
|
os.write(requestMessage.getBuffer());
|
||||||
@@ -193,7 +193,6 @@ public class ClientToServerThread implements Runnable {
|
|||||||
private void processRegistrationResponse(StreamPacket packet){
|
private void processRegistrationResponse(StreamPacket packet){
|
||||||
int sourceId = (int) Message.bytesToLong(Arrays.copyOfRange(packet.getPayload(), 0, 3));
|
int sourceId = (int) Message.bytesToLong(Arrays.copyOfRange(packet.getPayload(), 0, 3));
|
||||||
int statusCode = (int) Message.bytesToLong(Arrays.copyOfRange(packet.getPayload(), 4,5));
|
int statusCode = (int) Message.bytesToLong(Arrays.copyOfRange(packet.getPayload(), 4,5));
|
||||||
|
|
||||||
RegistrationResponseStatus status = RegistrationResponseStatus.getResponseStatus(statusCode);
|
RegistrationResponseStatus status = RegistrationResponseStatus.getResponseStatus(statusCode);
|
||||||
|
|
||||||
if (status.equals(RegistrationResponseStatus.SUCCESS_PLAYING)){
|
if (status.equals(RegistrationResponseStatus.SUCCESS_PLAYING)){
|
||||||
@@ -243,7 +242,7 @@ public class ClientToServerThread implements Runnable {
|
|||||||
new TimerTask() {
|
new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
sendBoatActionMessage(new BoatActionMessage(BoatAction.DOWNWIND));
|
sendBoatActionMessage(new BoatActionMessage(BoatAction.DOWNWIND, clientId));
|
||||||
}
|
}
|
||||||
}, 0, PACKET_SENDING_INTERVAL_MS
|
}, 0, PACKET_SENDING_INTERVAL_MS
|
||||||
);
|
);
|
||||||
@@ -256,14 +255,14 @@ public class ClientToServerThread implements Runnable {
|
|||||||
new TimerTask() {
|
new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
sendBoatActionMessage(new BoatActionMessage(BoatAction.UPWIND));
|
sendBoatActionMessage(new BoatActionMessage(BoatAction.UPWIND, clientId));
|
||||||
}
|
}
|
||||||
}, 0, PACKET_SENDING_INTERVAL_MS
|
}, 0, PACKET_SENDING_INTERVAL_MS
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sendBoatActionMessage(new BoatActionMessage(actionType));
|
sendBoatActionMessage(new BoatActionMessage(actionType, clientId));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,15 +10,16 @@ import java.util.Date;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.control.Alert;
|
|
||||||
import javafx.scene.control.Alert.AlertType;
|
|
||||||
import javafx.scene.input.KeyCode;
|
import javafx.scene.input.KeyCode;
|
||||||
import javafx.scene.input.KeyEvent;
|
import javafx.scene.input.KeyEvent;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
import javafx.util.Pair;
|
import javafx.util.Pair;
|
||||||
import seng302.gameServer.GameStages;
|
import seng302.gameServer.GameStages;
|
||||||
import seng302.gameServer.GameState;
|
import seng302.gameServer.GameState;
|
||||||
@@ -28,6 +29,8 @@ import seng302.gameServer.messages.BoatAction;
|
|||||||
import seng302.gameServer.messages.BoatStatus;
|
import seng302.gameServer.messages.BoatStatus;
|
||||||
import seng302.gameServer.messages.YachtEventType;
|
import seng302.gameServer.messages.YachtEventType;
|
||||||
import seng302.model.ClientYacht;
|
import seng302.model.ClientYacht;
|
||||||
|
import seng302.model.GameKeyBind;
|
||||||
|
import seng302.model.KeyAction;
|
||||||
import seng302.model.RaceState;
|
import seng302.model.RaceState;
|
||||||
import seng302.model.stream.packets.StreamPacket;
|
import seng302.model.stream.packets.StreamPacket;
|
||||||
import seng302.model.stream.parser.MarkRoundingData;
|
import seng302.model.stream.parser.MarkRoundingData;
|
||||||
@@ -45,6 +48,7 @@ import seng302.utilities.XMLParser;
|
|||||||
import seng302.visualiser.controllers.LobbyController;
|
import seng302.visualiser.controllers.LobbyController;
|
||||||
import seng302.visualiser.controllers.RaceViewController;
|
import seng302.visualiser.controllers.RaceViewController;
|
||||||
import seng302.visualiser.controllers.ViewManager;
|
import seng302.visualiser.controllers.ViewManager;
|
||||||
|
import seng302.visualiser.controllers.dialogs.PopupDialogController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is a client side instance of a yacht racing game in JavaFX. The game is instantiated
|
* This class is a client side instance of a yacht racing game in JavaFX. The game is instantiated
|
||||||
@@ -67,6 +71,8 @@ public class GameClient {
|
|||||||
|
|
||||||
private ArrayList<ClientYacht> finishedBoats = new ArrayList<>();
|
private ArrayList<ClientYacht> finishedBoats = new ArrayList<>();
|
||||||
|
|
||||||
|
private GameKeyBind gameKeyBind; // all the key binding setting.
|
||||||
|
|
||||||
private ObservableList<String> clientLobbyList = FXCollections.observableArrayList();
|
private ObservableList<String> clientLobbyList = FXCollections.observableArrayList();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,6 +82,7 @@ public class GameClient {
|
|||||||
*/
|
*/
|
||||||
public GameClient(Pane holder) {
|
public GameClient(Pane holder) {
|
||||||
this.holderPane = holder;
|
this.holderPane = holder;
|
||||||
|
this.gameKeyBind = GameKeyBind.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,10 +172,12 @@ public class GameClient {
|
|||||||
|
|
||||||
private void showConnectionError (String message) {
|
private void showConnectionError (String message) {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
Alert alert = new Alert(AlertType.ERROR);
|
PopupDialogController controller = ViewManager.getInstance().showPopupDialog();
|
||||||
alert.setHeaderText("Connection Error");
|
controller.setHeader("Oops");
|
||||||
alert.setContentText(message);
|
controller.setContent(message);
|
||||||
alert.showAndWait();
|
controller.setOptionButtonText("GO HOME");
|
||||||
|
controller
|
||||||
|
.setOptionButtonEventHandler(event -> ViewManager.getInstance().goToStartView());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,16 +378,16 @@ public class GameClient {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (e.getCode()) {
|
|
||||||
case SPACE: // align with vmg
|
if (gameKeyBind.getKeyCode(KeyAction.VMG) == e.getCode()) { // align with vmg
|
||||||
socketThread.sendBoatAction(BoatAction.VMG); break;
|
socketThread.sendBoatAction(BoatAction.VMG);
|
||||||
case PAGE_UP: // upwind
|
} else if (gameKeyBind.getKeyCode(KeyAction.UPWIND) == e.getCode()) { // upwind
|
||||||
socketThread.sendBoatAction(BoatAction.UPWIND); break;
|
socketThread.sendBoatAction(BoatAction.UPWIND);
|
||||||
case PAGE_DOWN: // downwind
|
} else if (gameKeyBind.getKeyCode(KeyAction.DOWNWIND) == e.getCode()) { // downwind
|
||||||
socketThread.sendBoatAction(BoatAction.DOWNWIND); break;
|
socketThread.sendBoatAction(BoatAction.DOWNWIND);
|
||||||
case ENTER: // tack/gybe
|
} else if (gameKeyBind.getKeyCode(KeyAction.TACK_GYBE) == e.getCode()) { // tack/gybe
|
||||||
// if chat box is active take whatever is in there and send it to server
|
// if chat box is active take whatever is in there and send it to server
|
||||||
socketThread.sendBoatAction(BoatAction.TACK_GYBE); break;
|
socketThread.sendBoatAction(BoatAction.TACK_GYBE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,15 +396,17 @@ public class GameClient {
|
|||||||
if (raceView.isChatInputFocused()) {
|
if (raceView.isChatInputFocused()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (e.getCode()) {
|
|
||||||
//TODO 12/07/17 Determine the sail state and send the appropriate packet (eg. if sails are in, send a sail out packet)
|
if (gameKeyBind.getKeyCode(KeyAction.SAILS_STATE) == e.getCode()) { // sails in/sails out
|
||||||
case SHIFT: // sails in/sails out
|
if (allBoatsMap.get(socketThread.getClientId()).getSailIn()) {
|
||||||
|
socketThread.sendBoatAction(BoatAction.SAILS_OUT);
|
||||||
|
} else {
|
||||||
socketThread.sendBoatAction(BoatAction.SAILS_IN);
|
socketThread.sendBoatAction(BoatAction.SAILS_IN);
|
||||||
allBoatsMap.get(socketThread.getClientId()).toggleSail();
|
}
|
||||||
break;
|
allBoatsMap.get(socketThread.getClientId()).toggleSail();
|
||||||
case PAGE_UP:
|
} else if (gameKeyBind.getKeyCode(KeyAction.UPWIND) == e.getCode()
|
||||||
case PAGE_DOWN:
|
|| gameKeyBind.getKeyCode(KeyAction.DOWNWIND) == e.getCode()) {
|
||||||
socketThread.sendBoatAction(BoatAction.MAINTAIN_HEADING); break;
|
socketThread.sendBoatAction(BoatAction.MAINTAIN_HEADING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,9 +421,16 @@ public class GameClient {
|
|||||||
* @param yachtEventData The YachtEvent data packet
|
* @param yachtEventData The YachtEvent data packet
|
||||||
*/
|
*/
|
||||||
private void processYachtEvent(YachtEventData yachtEventData) {
|
private void processYachtEvent(YachtEventData yachtEventData) {
|
||||||
|
ClientYacht thisYacht = allBoatsMap.get(yachtEventData.getSubjectId().intValue());
|
||||||
|
|
||||||
if (yachtEventData.getEventId() == YachtEventType.COLLISION.getCode()) {
|
if (yachtEventData.getEventId() == YachtEventType.COLLISION.getCode()) {
|
||||||
showCollisionAlert(yachtEventData);
|
showCollisionAlert(thisYacht);
|
||||||
} else {
|
} else if (yachtEventData.getEventId() == YachtEventType.POWER_DOWN.getCode()) {
|
||||||
|
thisYacht.powerDown();
|
||||||
|
Sounds.playTokenPickupSound(); // TODO: 23/09/17 This should be power down sound
|
||||||
|
} else if (yachtEventData.getEventId() == YachtEventType.BUMPER_CRASH.getCode()) {
|
||||||
|
showDisableAlert(thisYacht);
|
||||||
|
} else { //Else all token pickup types
|
||||||
TokenType tokenType = null;
|
TokenType tokenType = null;
|
||||||
if (yachtEventData.getEventId() == YachtEventType.TOKEN_VELOCITY.getCode()) {
|
if (yachtEventData.getEventId() == YachtEventType.TOKEN_VELOCITY.getCode()) {
|
||||||
tokenType = TokenType.BOOST;
|
tokenType = TokenType.BOOST;
|
||||||
@@ -426,36 +444,36 @@ public class GameClient {
|
|||||||
tokenType = TokenType.WIND_WALKER;
|
tokenType = TokenType.WIND_WALKER;
|
||||||
}
|
}
|
||||||
|
|
||||||
showTokenPickUp(tokenType);
|
Sounds.playTokenPickupSound();
|
||||||
allBoatsMap.get(yachtEventData.getSubjectId().intValue()).setPowerUp(tokenType);
|
thisYacht.setPowerUp(tokenType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns a disabled boat black until the bumper affect wears off
|
||||||
|
*
|
||||||
|
* @param yacht The yacht to show as disabled
|
||||||
|
*/
|
||||||
|
private void showDisableAlert(ClientYacht yacht) {
|
||||||
|
Color originalColor = yacht.getColour();
|
||||||
|
yacht.setColour(Color.BLACK);
|
||||||
|
|
||||||
|
Timer disableTimer = new Timer("Disable Timer");
|
||||||
|
disableTimer.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
yacht.setColour(originalColor);
|
||||||
|
}
|
||||||
|
}, GameState.BUMPER_DISABLE_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells race view to show a collision animation.
|
* Tells race view to show a collision animation.
|
||||||
*/
|
*/
|
||||||
private void showCollisionAlert(YachtEventData yachtEventData) {
|
private void showCollisionAlert(ClientYacht yacht) {
|
||||||
Sounds.playCrashSound();
|
Sounds.playCrashSound();
|
||||||
raceState.storeCollision(
|
raceState.storeCollision(yacht);
|
||||||
allBoatsMap.get(
|
|
||||||
yachtEventData.getSubjectId().intValue()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: 11/09/17 wmu16 - Add in functionality to viually indicate a pickup to a user
|
|
||||||
private void showTokenPickUp(TokenType tokenType) {
|
|
||||||
Sounds.playTokenPickupSound();
|
|
||||||
switch (tokenType) {
|
|
||||||
case BOOST:
|
|
||||||
break;
|
|
||||||
case HANDLING:
|
|
||||||
break;
|
|
||||||
case WIND_WALKER:
|
|
||||||
break;
|
|
||||||
case BUMPER:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void formatAndSendChatMessage(String rawChat) {
|
private void formatAndSendChatMessage(String rawChat) {
|
||||||
@@ -490,4 +508,14 @@ public class GameClient {
|
|||||||
public Map<Integer, ClientYacht> getAllBoatsMap() {
|
public Map<Integer, ClientYacht> getAllBoatsMap() {
|
||||||
return allBoatsMap;
|
return allBoatsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendToggleTurningModePacket() {
|
||||||
|
if (socketThread != null) {
|
||||||
|
if (gameKeyBind.isContinuouslyTurning()) {
|
||||||
|
socketThread.sendBoatAction(BoatAction.CONTINUOUSLY_TURNING);
|
||||||
|
} else {
|
||||||
|
socketThread.sendBoatAction(BoatAction.DEFAULT_TURNING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package seng302.visualiser;
|
package seng302.visualiser;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -9,6 +10,7 @@ import javafx.animation.AnimationTimer;
|
|||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.geometry.Point2D;
|
import javafx.geometry.Point2D;
|
||||||
import javafx.geometry.Point3D;
|
import javafx.geometry.Point3D;
|
||||||
|
import javafx.scene.Camera;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.PerspectiveCamera;
|
import javafx.scene.PerspectiveCamera;
|
||||||
@@ -21,7 +23,9 @@ import javafx.scene.transform.Scale;
|
|||||||
import javafx.scene.transform.Translate;
|
import javafx.scene.transform.Translate;
|
||||||
import seng302.gameServer.messages.RoundingSide;
|
import seng302.gameServer.messages.RoundingSide;
|
||||||
import seng302.model.ClientYacht;
|
import seng302.model.ClientYacht;
|
||||||
|
import seng302.model.GameKeyBind;
|
||||||
import seng302.model.GeoPoint;
|
import seng302.model.GeoPoint;
|
||||||
|
import seng302.model.KeyAction;
|
||||||
import seng302.model.Limit;
|
import seng302.model.Limit;
|
||||||
import seng302.model.mark.CompoundMark;
|
import seng302.model.mark.CompoundMark;
|
||||||
import seng302.model.mark.Corner;
|
import seng302.model.mark.Corner;
|
||||||
@@ -47,20 +51,19 @@ import seng302.visualiser.fxObjects.assets_3D.ModelType;
|
|||||||
|
|
||||||
public class GameView3D {
|
public class GameView3D {
|
||||||
|
|
||||||
|
|
||||||
private final double FOV = 60;
|
private final double FOV = 60;
|
||||||
private final double DEFAULT_CAMERA_DEPTH = -125;
|
|
||||||
private final double DEFAULT_CAMERA_X = 0;
|
private final double DEFAULT_CAMERA_X = 0;
|
||||||
private final double DEFAULT_CAMERA_Y = 155;
|
private final double DEFAULT_CAMERA_Y = 155;
|
||||||
|
|
||||||
private Group root3D;
|
private Group root3D;
|
||||||
private SubScene view;
|
private SubScene view;
|
||||||
// ParallelCamera camera;
|
|
||||||
private PerspectiveCamera camera;
|
|
||||||
private PerspectiveCamera camera2;
|
|
||||||
private PerspectiveCamera camera3;
|
|
||||||
private Group gameObjects;
|
private Group gameObjects;
|
||||||
|
|
||||||
|
// Cameras
|
||||||
|
private PerspectiveCamera isometricCam;
|
||||||
|
private PerspectiveCamera topDownCam;
|
||||||
|
private PerspectiveCamera chaseCam;
|
||||||
|
|
||||||
private double bufferSize = 0;
|
private double bufferSize = 0;
|
||||||
private double canvasWidth = 200;
|
private double canvasWidth = 200;
|
||||||
private double canvasHeight = 200;
|
private double canvasHeight = 200;
|
||||||
@@ -95,28 +98,22 @@ public class GameView3D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GameView3D () {
|
public GameView3D () {
|
||||||
camera = new IsometricCamera(DEFAULT_CAMERA_X, DEFAULT_CAMERA_Y, DEFAULT_CAMERA_DEPTH);
|
isometricCam = new IsometricCamera(DEFAULT_CAMERA_X, DEFAULT_CAMERA_Y);
|
||||||
camera.setFarClip(600);
|
topDownCam = new TopDownCamera();
|
||||||
camera.setNearClip(0.1);
|
chaseCam = new ChaseCamera();
|
||||||
camera.setFieldOfView(FOV);
|
|
||||||
|
|
||||||
camera2 = new TopDownCamera();
|
for (PerspectiveCamera pc : Arrays.asList(isometricCam, topDownCam, chaseCam)) {
|
||||||
camera2.setFarClip(600);
|
pc.setFarClip(600);
|
||||||
camera2.setNearClip(0.1);
|
pc.setNearClip(0.1);
|
||||||
camera2.setFieldOfView(FOV);
|
pc.setFieldOfView(FOV);
|
||||||
|
}
|
||||||
camera3 = new ChaseCamera();
|
|
||||||
camera3.setFarClip(600);
|
|
||||||
camera3.setNearClip(0.1);
|
|
||||||
camera3.setFieldOfView(FOV);
|
|
||||||
|
|
||||||
gameObjects = new Group();
|
gameObjects = new Group();
|
||||||
root3D = new Group(camera, gameObjects);
|
root3D = new Group(isometricCam, gameObjects);
|
||||||
view = new SubScene(
|
view = new SubScene(
|
||||||
root3D, 1000, 1000, true, SceneAntialiasing.BALANCED
|
root3D, 1000, 1000, true, SceneAntialiasing.BALANCED
|
||||||
);
|
);
|
||||||
view.setCamera(camera);
|
view.setCamera(isometricCam);
|
||||||
camera.getTransforms().add(new Rotate(30, new Point3D(1,0,0)));
|
|
||||||
|
|
||||||
gameObjects.getChildren().addAll(
|
gameObjects.getChildren().addAll(
|
||||||
ModelFactory.importModel(ModelType.OCEAN).getAssets(),
|
ModelFactory.importModel(ModelType.OCEAN).getAssets(),
|
||||||
@@ -351,7 +348,6 @@ public class GameView3D {
|
|||||||
* it to distanceScaleFactor Returns the max horizontal distance of the map.
|
* it to distanceScaleFactor Returns the max horizontal distance of the map.
|
||||||
*/
|
*/
|
||||||
private double scaleRaceExtremities() {
|
private double scaleRaceExtremities() {
|
||||||
|
|
||||||
double vertAngle = Math.abs(
|
double vertAngle = Math.abs(
|
||||||
GeoUtility.getBearingRad(minLatPoint, maxLatPoint)
|
GeoUtility.getBearingRad(minLatPoint, maxLatPoint)
|
||||||
);
|
);
|
||||||
@@ -419,48 +415,44 @@ public class GameView3D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void cameraMovement(KeyEvent event) {
|
public void cameraMovement(KeyEvent event) {
|
||||||
switch (event.getCode()) {
|
GameKeyBind keyBinds = GameKeyBind.getInstance();
|
||||||
case NUMPAD8:
|
KeyAction keyPressed = keyBinds.getKeyAction(event.getCode());
|
||||||
view.getCamera().getTransforms().addAll(new Rotate(0.5, new Point3D(1, 0, 0)));
|
if (keyPressed != null) {
|
||||||
break;
|
switch (keyPressed) {
|
||||||
case NUMPAD2:
|
case ZOOM_IN:
|
||||||
view.getCamera().getTransforms().addAll(new Rotate(-0.5, new Point3D(1, 0, 0)));
|
((RaceCamera) view.getCamera()).zoomIn();
|
||||||
break;
|
break;
|
||||||
case NUMPAD4:
|
case ZOOM_OUT:
|
||||||
view.getCamera().getTransforms().addAll(new Rotate(-0.5, new Point3D(0, 1, 0)));
|
((RaceCamera) view.getCamera()).zoomOut();
|
||||||
break;
|
break;
|
||||||
case NUMPAD6:
|
case FORWARD:
|
||||||
view.getCamera().getTransforms().addAll(new Rotate(0.5, new Point3D(0, 1, 0)));
|
((RaceCamera) view.getCamera()).panUp();
|
||||||
break;
|
break;
|
||||||
case Z:
|
case BACKWARD:
|
||||||
((RaceCamera) view.getCamera()).zoomIn();
|
((RaceCamera) view.getCamera()).panDown();
|
||||||
break;
|
break;
|
||||||
case X:
|
case LEFT:
|
||||||
((RaceCamera) view.getCamera()).zoomOut();
|
((RaceCamera) view.getCamera()).panLeft();
|
||||||
break;
|
break;
|
||||||
case W:
|
case RIGHT:
|
||||||
view.getCamera().getTransforms().addAll(new Translate(0, -1, 0));
|
((RaceCamera) view.getCamera()).panRight();
|
||||||
break;
|
break;
|
||||||
case S:
|
case VIEW:
|
||||||
view.getCamera().getTransforms().addAll(new Translate(0, 1, 0));
|
toggleCamera();
|
||||||
break;
|
break;
|
||||||
case A:
|
}
|
||||||
view.getCamera().getTransforms().addAll(new Translate(-1, 0, 0));
|
}
|
||||||
break;
|
}
|
||||||
case D:
|
|
||||||
view.getCamera().getTransforms().addAll(new Translate(1, 0, 0));
|
private void toggleCamera() {
|
||||||
break;
|
Camera currCamera = view.getCamera();
|
||||||
case F1:
|
|
||||||
if (view.getCamera().equals(camera)) {
|
if (currCamera.equals(isometricCam)) {
|
||||||
view.setCamera(camera2);
|
view.setCamera(topDownCam);
|
||||||
if (view.getCamera() instanceof TopDownCamera) {
|
} else if (currCamera.equals(topDownCam)) {
|
||||||
((RaceCamera) view.getCamera()).zoomIn();
|
view.setCamera(chaseCam);
|
||||||
}
|
} else {
|
||||||
} else if (view.getCamera().equals(camera2)) {
|
view.setCamera(isometricCam);
|
||||||
view.setCamera(camera3);
|
|
||||||
} else {
|
|
||||||
view.setCamera(camera);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,21 +478,19 @@ public class GameView3D {
|
|||||||
final List<Group> wakes = new ArrayList<>();
|
final List<Group> wakes = new ArrayList<>();
|
||||||
for (ClientYacht clientYacht : yachts) {
|
for (ClientYacht clientYacht : yachts) {
|
||||||
Color colour = clientYacht.getColour();
|
Color colour = clientYacht.getColour();
|
||||||
newBoat = new BoatObject();
|
newBoat = new BoatObject(clientYacht.getBoatType());
|
||||||
newBoat.setFill(colour);
|
newBoat.setFill(colour);
|
||||||
boatObjects.put(clientYacht, newBoat);
|
boatObjects.put(clientYacht, newBoat);
|
||||||
wakesGroup.getChildren().add(newBoat.getWake());
|
wakesGroup.getChildren().add(newBoat.getWake());
|
||||||
wakes.add(newBoat.getWake());
|
wakes.add(newBoat.getWake());
|
||||||
boatObjectGroup.getChildren().add(newBoat);
|
boatObjectGroup.getChildren().add(newBoat);
|
||||||
clientYacht.addLocationListener((boat, lat, lon, heading, sailIn, velocity) -> {
|
clientYacht.addLocationListener(this::updateBoatLocation);
|
||||||
BoatObject bo = boatObjects.get(boat);
|
clientYacht.addColorChangeListener(this::updateBoatColor);
|
||||||
Point2D p2d = findScaledXY(lat, lon);
|
|
||||||
bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity, sailIn, windDir);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (clientYacht.getSourceId().equals(
|
if (clientYacht.getSourceId().equals(
|
||||||
ViewManager.getInstance().getGameClient().getServerThread().getClientId())) {
|
ViewManager.getInstance().getGameClient().getServerThread().getClientId())) {
|
||||||
((ChaseCamera) camera3).setPlayerBoat(newBoat);
|
((ChaseCamera) chaseCam).setPlayerBoat(newBoat);
|
||||||
|
((TopDownCamera) topDownCam).setPlayerBoat(newBoat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
@@ -513,6 +503,23 @@ public class GameView3D {
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the boatObjects color with that of the clientYachts object. Used in notification from
|
||||||
|
* a listener on this attribute in clientYacht to re paint the boat mesh
|
||||||
|
*
|
||||||
|
* @param clientYacht The yacht to update the colour for
|
||||||
|
*/
|
||||||
|
private void updateBoatColor(ClientYacht clientYacht) {
|
||||||
|
boatObjects.get(clientYacht).setFill(clientYacht.getColour());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateBoatLocation(ClientYacht boat, Double lat, Double lon, Double heading,
|
||||||
|
Boolean sailIn, Double velocity) {
|
||||||
|
BoatObject bo = boatObjects.get(boat);
|
||||||
|
Point2D p2d = findScaledXY(lat, lon);
|
||||||
|
bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity, sailIn, windDir);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a border to the GameView and rescales to the size of the border, does not rescale if a
|
* Adds a border to the GameView and rescales to the size of the border, does not rescale if a
|
||||||
* border already exists. Assumes the border is larger than the course.
|
* border already exists. Assumes the border is larger than the course.
|
||||||
@@ -620,6 +627,7 @@ public class GameView3D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setBoatAsPlayer (ClientYacht playerYacht) {
|
public void setBoatAsPlayer (ClientYacht playerYacht) {
|
||||||
|
playerYacht.toggleSail();
|
||||||
playerBoatAnimationTimer = new AnimationTimer() {
|
playerBoatAnimationTimer = new AnimationTimer() {
|
||||||
|
|
||||||
double count = 60;
|
double count = 60;
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ import seng302.gameServer.ServerDescription;
|
|||||||
import javax.jmdns.JmDNS;
|
import javax.jmdns.JmDNS;
|
||||||
import javax.jmdns.ServiceEvent;
|
import javax.jmdns.ServiceEvent;
|
||||||
import javax.jmdns.ServiceListener;
|
import javax.jmdns.ServiceListener;
|
||||||
import javax.jmdns.impl.JmDNSImpl;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static seng302.gameServer.ServerAdvertiser.getLocalHostIp;
|
import static seng302.gameServer.ServerAdvertiser.getLocalHostIp;
|
||||||
|
|
||||||
@@ -17,7 +18,6 @@ import static seng302.gameServer.ServerAdvertiser.getLocalHostIp;
|
|||||||
* Listens for servers on the local network
|
* Listens for servers on the local network
|
||||||
*/
|
*/
|
||||||
public class ServerListener{
|
public class ServerListener{
|
||||||
private static Integer SERVICE_REFRESH_INTERVAL = 5 * 1000;
|
|
||||||
private static ServerListener instance;
|
private static ServerListener instance;
|
||||||
private ServerListenerDelegate delegate;
|
private ServerListenerDelegate delegate;
|
||||||
private JmDNS jmdns = null;
|
private JmDNS jmdns = null;
|
||||||
@@ -91,16 +91,8 @@ public class ServerListener{
|
|||||||
|
|
||||||
private ServerListener() throws IOException {
|
private ServerListener() throws IOException {
|
||||||
jmdns = JmDNS.create(InetAddress.getByName(getLocalHostIp()));
|
jmdns = JmDNS.create(InetAddress.getByName(getLocalHostIp()));
|
||||||
|
|
||||||
listener = new GameServeMonitor();
|
listener = new GameServeMonitor();
|
||||||
jmdns.addServiceListener(ServerAdvertiser.SERVICE_TYPE, listener);
|
jmdns.addServiceListener(ServerAdvertiser.SERVICE_TYPE, listener);
|
||||||
|
|
||||||
/*new Timer().schedule(new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
}, 50, SERVICE_REFRESH_INTERVAL);*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ServerListener getInstance() throws IOException {
|
public static ServerListener getInstance() throws IOException {
|
||||||
@@ -118,25 +110,4 @@ public class ServerListener{
|
|||||||
public void setDelegate(ServerListenerDelegate delegate){
|
public void setDelegate(ServerListenerDelegate delegate){
|
||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh(){
|
|
||||||
ArrayList<ServerDescription> servers = new ArrayList<>(listener.servers);
|
|
||||||
|
|
||||||
for (ServerDescription serverDescription : servers){
|
|
||||||
if (serverDescription.hasExpired()){
|
|
||||||
jmdns.requestServiceInfo(ServerAdvertiser.SERVICE_TYPE, serverDescription.getName());
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
serverDescription.hasBeenRefreshed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ServerDescription server : servers){
|
|
||||||
if (server.serverShouldBeRemoved()){
|
|
||||||
listener.servers.remove(server);
|
|
||||||
delegate.serverRemoved(new ArrayList<ServerDescription>(listener.servers));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package seng302.visualiser.cameras;
|
package seng302.visualiser.cameras;
|
||||||
|
|
||||||
import javafx.beans.value.ChangeListener;
|
import java.util.Arrays;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.property.DoubleProperty;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.geometry.Point3D;
|
import javafx.geometry.Point3D;
|
||||||
import javafx.scene.PerspectiveCamera;
|
import javafx.scene.PerspectiveCamera;
|
||||||
@@ -13,77 +13,118 @@ import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
|||||||
|
|
||||||
public class ChaseCamera extends PerspectiveCamera implements RaceCamera {
|
public class ChaseCamera extends PerspectiveCamera implements RaceCamera {
|
||||||
|
|
||||||
|
private final Double VERTICAL_PAN_LIMIT = 20.0;
|
||||||
|
private final Double NEAR_ZOOM_LIMIT = -15.0;
|
||||||
|
private final Double FAR_ZOOM_LIMIT = -125.0;
|
||||||
|
|
||||||
|
private final Double ZOOM_STEP = 2.5;
|
||||||
|
private final Double PAN_STEP = 2.5;
|
||||||
|
|
||||||
private ObservableList<Transform> transforms;
|
private ObservableList<Transform> transforms;
|
||||||
private BoatObject playerBoat;
|
private BoatObject playerBoat;
|
||||||
|
|
||||||
|
private Double zoomFactor;
|
||||||
|
private Double horizontalPan;
|
||||||
|
private Double verticalPan;
|
||||||
|
|
||||||
|
|
||||||
public ChaseCamera() {
|
public ChaseCamera() {
|
||||||
super(true);
|
super(true);
|
||||||
transforms = this.getTransforms();
|
transforms = this.getTransforms();
|
||||||
|
|
||||||
|
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
|
||||||
|
this.horizontalPan = 0.0;
|
||||||
|
this.verticalPan = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a player boat object to observe and update the camera with.
|
||||||
|
*
|
||||||
|
* @param playerBoat The player boat to be observed.
|
||||||
|
*/
|
||||||
public void setPlayerBoat(BoatObject playerBoat) {
|
public void setPlayerBoat(BoatObject playerBoat) {
|
||||||
this.playerBoat = playerBoat;
|
this.playerBoat = playerBoat;
|
||||||
|
|
||||||
this.playerBoat.layoutXProperty().addListener(new ChangeListener<Number>() {
|
for (DoubleProperty o : Arrays
|
||||||
@Override
|
.asList(playerBoat.getRotationProperty(), playerBoat.layoutYProperty(),
|
||||||
public void changed(ObservableValue<? extends Number> observable, Number oldValue,
|
playerBoat.layoutXProperty())) {
|
||||||
Number newValue) {
|
o.addListener((obs, oldVal, newVal) -> repositionCamera());
|
||||||
updateCameraX((Double) oldValue, (Double) newValue);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.playerBoat.layoutYProperty().addListener(new ChangeListener<Number>() {
|
|
||||||
@Override
|
|
||||||
public void changed(ObservableValue<? extends Number> observable, Number oldValue,
|
|
||||||
Number newValue) {
|
|
||||||
updateCameraY((Double) oldValue, (Double) newValue);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void updateCameraX(Double oldXValue, Double newXValue) {
|
|
||||||
if (transforms.size() == 0) { // boat is placed and then moved at start,
|
|
||||||
transforms.addAll(
|
|
||||||
new Translate(playerBoat.getLayoutX() - 30, playerBoat.getLayoutY() - 30, -125),
|
|
||||||
new Rotate(80, new Point3D(0, 0, 1))
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
transforms.addAll(new Translate(newXValue - oldXValue, 0, 0));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateCameraY(Double oldYValue, Double newYValue) {
|
/**
|
||||||
transforms.addAll(new Translate(0, (newYValue - oldYValue), 0));
|
* Moves the camera to a new position after some change (Zooming or Panning)
|
||||||
|
*/
|
||||||
|
private void repositionCamera() {
|
||||||
|
transforms.clear();
|
||||||
|
transforms.addAll(
|
||||||
|
new Translate(playerBoat.getLayoutX(), playerBoat.getLayoutY(), 0),
|
||||||
|
new Rotate(playerBoat.getRotationProperty().getValue() + horizontalPan,
|
||||||
|
new Point3D(0, 0, 1)),
|
||||||
|
new Rotate(60 + verticalPan, new Point3D(1, 0, 0)),
|
||||||
|
new Translate(0, 0, zoomFactor)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts the zoom amount (camera depth) by some adjustment value
|
||||||
|
* @param adjustment the adjustment to be made to the camera
|
||||||
|
*/
|
||||||
|
private void adjustZoomFactor(Double adjustment) {
|
||||||
|
if (zoomFactor + adjustment < NEAR_ZOOM_LIMIT && zoomFactor + adjustment > FAR_ZOOM_LIMIT) {
|
||||||
|
zoomFactor = zoomFactor + adjustment;
|
||||||
|
repositionCamera();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts the Vertical Panning of the Camera
|
||||||
|
* @param adjustment the adjustment to be made to the camera
|
||||||
|
*/
|
||||||
|
private void adjustVerticalPan(Double adjustment) {
|
||||||
|
if (verticalPan + adjustment >= -VERTICAL_PAN_LIMIT
|
||||||
|
&& verticalPan + adjustment <= VERTICAL_PAN_LIMIT) {
|
||||||
|
verticalPan += adjustment;
|
||||||
|
repositionCamera();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts the Horizontal Panning of the Camera.
|
||||||
|
* @param adjustment the adjustment to be made to the camera
|
||||||
|
*/
|
||||||
|
private void adjustHorizontalPan(Double adjustment) {
|
||||||
|
this.horizontalPan += adjustment;
|
||||||
|
repositionCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void zoomIn() {
|
public void zoomIn() {
|
||||||
transforms.addAll(new Translate(0, 0, 1.5));
|
adjustZoomFactor(ZOOM_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void zoomOut() {
|
public void zoomOut() {
|
||||||
transforms.addAll(new Translate(0, 0, -1.5));
|
adjustZoomFactor(-ZOOM_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
These have been left intentionally empty for now. it would be cool to be able to pan around the boat and have the camera move around the boat though.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void panLeft() {
|
public void panLeft() {
|
||||||
|
adjustHorizontalPan(-PAN_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void panRight() {
|
public void panRight() {
|
||||||
|
adjustHorizontalPan(PAN_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void panUp() {
|
public void panUp() {
|
||||||
|
adjustVerticalPan(-PAN_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void panDown() {
|
public void panDown() {
|
||||||
|
adjustVerticalPan(PAN_STEP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,47 +1,113 @@
|
|||||||
package seng302.visualiser.cameras;
|
package seng302.visualiser.cameras;
|
||||||
|
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.geometry.Point3D;
|
||||||
import javafx.scene.PerspectiveCamera;
|
import javafx.scene.PerspectiveCamera;
|
||||||
|
import javafx.scene.transform.Rotate;
|
||||||
import javafx.scene.transform.Transform;
|
import javafx.scene.transform.Transform;
|
||||||
import javafx.scene.transform.Translate;
|
import javafx.scene.transform.Translate;
|
||||||
|
|
||||||
public class IsometricCamera extends PerspectiveCamera implements RaceCamera {
|
public class IsometricCamera extends PerspectiveCamera implements RaceCamera {
|
||||||
|
|
||||||
ObservableList<Transform> transforms;
|
private final Double MIN_X = -120.0;
|
||||||
|
private final Double MAX_X = 125.0;
|
||||||
|
|
||||||
public IsometricCamera(Double cameraStartX, Double cameraStartY, Double cameraDepth) {
|
private final Double MIN_Y = 40.0;
|
||||||
|
private final Double MAX_Y = 170.0;
|
||||||
|
|
||||||
|
private final Double PAN_LIMIT = 160.0;
|
||||||
|
private final Double NEAR_ZOOM_LIMIT = -50.0;
|
||||||
|
private final Double FAR_ZOOM_LIMIT = -160.0;
|
||||||
|
|
||||||
|
private Double horizontalPan;
|
||||||
|
private Double verticalPan;
|
||||||
|
private Double zoomFactor;
|
||||||
|
|
||||||
|
private ObservableList<Transform> transforms;
|
||||||
|
|
||||||
|
public IsometricCamera(Double cameraStartX, Double cameraStartY) {
|
||||||
super(true);
|
super(true);
|
||||||
transforms = this.getTransforms();
|
transforms = this.getTransforms();
|
||||||
transforms.addAll(new Translate(cameraStartX, cameraStartY, cameraDepth));
|
|
||||||
|
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
|
||||||
|
horizontalPan = cameraStartX;
|
||||||
|
verticalPan = cameraStartY;
|
||||||
|
|
||||||
|
updateCamera();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the camera to a new position after some change (Zooming or Panning)
|
||||||
|
*/
|
||||||
|
private void updateCamera() {
|
||||||
|
transforms.clear();
|
||||||
|
transforms.addAll(
|
||||||
|
new Translate(horizontalPan, verticalPan, zoomFactor),
|
||||||
|
new Rotate(30, new Point3D(1, 0, 0))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts the zoom amount (camera depth) by some adjustment value
|
||||||
|
*
|
||||||
|
* @param adjustment the adjustment to be made to the camera
|
||||||
|
*/
|
||||||
|
private void adjustZoomFactor(Double adjustment) {
|
||||||
|
if (zoomFactor + adjustment < NEAR_ZOOM_LIMIT && zoomFactor + adjustment > FAR_ZOOM_LIMIT) {
|
||||||
|
zoomFactor = zoomFactor + adjustment;
|
||||||
|
updateCamera();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts the Vertical Panning of the Camera
|
||||||
|
* @param adjustment the adjustment to be made to the camera
|
||||||
|
*/
|
||||||
|
private void adjustVerticalPan(Double adjustment) {
|
||||||
|
if (verticalPan + adjustment >= MIN_Y && verticalPan + adjustment <= MAX_Y) {
|
||||||
|
verticalPan += adjustment;
|
||||||
|
updateCamera();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts the Horizontal Panning of the Camera.
|
||||||
|
* @param adjustment the adjustment to be made to the camera
|
||||||
|
*/
|
||||||
|
private void adjustHorizontalPan(Double adjustment) {
|
||||||
|
if (horizontalPan + adjustment >= MIN_X && horizontalPan + adjustment <= MIN_Y) {
|
||||||
|
this.horizontalPan += adjustment;
|
||||||
|
updateCamera();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void zoomIn() {
|
public void zoomIn() {
|
||||||
transforms.addAll(new Translate(0, 0, 1.5));
|
adjustZoomFactor(-2.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void zoomOut() {
|
public void zoomOut() {
|
||||||
transforms.addAll(new Translate(0, 0, -1.5));
|
adjustZoomFactor(2.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void panLeft() {
|
public void panLeft() {
|
||||||
transforms.addAll(new Translate(-1, 0, 0));
|
adjustHorizontalPan(-2.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void panRight() {
|
public void panRight() {
|
||||||
transforms.addAll(new Translate(1, 0, 0));
|
adjustHorizontalPan(2.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void panUp() {
|
public void panUp() {
|
||||||
transforms.addAll(new Translate(0, -1, 0));
|
adjustVerticalPan(-2.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void panDown() {
|
public void panDown() {
|
||||||
transforms.addAll(new Translate(0, 1, 0));
|
adjustVerticalPan(2.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,48 +1,123 @@
|
|||||||
package seng302.visualiser.cameras;
|
package seng302.visualiser.cameras;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import javafx.beans.property.DoubleProperty;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.scene.PerspectiveCamera;
|
import javafx.scene.PerspectiveCamera;
|
||||||
import javafx.scene.transform.Transform;
|
import javafx.scene.transform.Transform;
|
||||||
import javafx.scene.transform.Translate;
|
import javafx.scene.transform.Translate;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
||||||
|
|
||||||
public class TopDownCamera extends PerspectiveCamera implements RaceCamera {
|
public class TopDownCamera extends PerspectiveCamera implements RaceCamera {
|
||||||
|
|
||||||
ObservableList<Transform> transforms;
|
private final Double PAN_LIMIT = 30.0;
|
||||||
|
private final Double NEAR_ZOOM_LIMIT = -30.0;
|
||||||
|
private final Double FAR_ZOOM_LIMIT = -130.0;
|
||||||
|
private final Double ZOOM_STEP = 2.5;
|
||||||
|
|
||||||
|
private ObservableList<Transform> transforms;
|
||||||
|
private BoatObject playerBoat;
|
||||||
|
|
||||||
|
private Double zoomFactor;
|
||||||
|
private Double horizontalPan;
|
||||||
|
private Double verticalPan;
|
||||||
|
|
||||||
public TopDownCamera() {
|
public TopDownCamera() {
|
||||||
super(true);
|
super(true);
|
||||||
transforms = this.getTransforms();
|
transforms = this.getTransforms();
|
||||||
transforms.add(new Translate(0, 0, -125));
|
|
||||||
|
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
|
||||||
|
horizontalPan = 0.0;
|
||||||
|
verticalPan = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a player boat object to observe and update the camera with.
|
||||||
|
*
|
||||||
|
* @param playerBoat The player boat to be observed.
|
||||||
|
*/
|
||||||
|
public void setPlayerBoat(BoatObject playerBoat) {
|
||||||
|
this.playerBoat = playerBoat;
|
||||||
|
|
||||||
|
for (DoubleProperty o : Arrays
|
||||||
|
.asList(playerBoat.layoutXProperty(), playerBoat.layoutYProperty())) {
|
||||||
|
o.addListener((obs, oldVal, newVal) -> updateCamera());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the camera to a new position after some change (Zooming or Panning)
|
||||||
|
*/
|
||||||
|
private void updateCamera() {
|
||||||
|
transforms.clear();
|
||||||
|
transforms.addAll(
|
||||||
|
new Translate(playerBoat.getLayoutX() + horizontalPan,
|
||||||
|
playerBoat.getLayoutY() + verticalPan, zoomFactor)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts the zoom amount (camera depth) by some adjustment value
|
||||||
|
* @param adjustment the adjustment to be made to the camera
|
||||||
|
*/
|
||||||
|
private void adjustZoomFactor(Double adjustment) {
|
||||||
|
if (zoomFactor + adjustment < NEAR_ZOOM_LIMIT && zoomFactor + adjustment > FAR_ZOOM_LIMIT) {
|
||||||
|
zoomFactor = zoomFactor + adjustment;
|
||||||
|
updateCamera();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts the Vertical Panning of the Camera
|
||||||
|
* @param adjustment the adjustment to be made to the camera
|
||||||
|
*/
|
||||||
|
private void adjustVerticalPan(Double adjustment) {
|
||||||
|
if (verticalPan + adjustment >= -PAN_LIMIT && verticalPan + adjustment <= PAN_LIMIT) {
|
||||||
|
verticalPan += adjustment;
|
||||||
|
updateCamera();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts the Horizontal Panning of the Camera.
|
||||||
|
* @param adjustment the adjustment to be made to the camera
|
||||||
|
*/
|
||||||
|
private void adjustHorizontalPan(Double adjustment) {
|
||||||
|
if (horizontalPan + adjustment >= -PAN_LIMIT && horizontalPan + adjustment <= PAN_LIMIT) {
|
||||||
|
horizontalPan += adjustment;
|
||||||
|
updateCamera();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void zoomIn() {
|
public void zoomIn() {
|
||||||
transforms.addAll(new Translate(0, 0, 1.5));
|
adjustZoomFactor(ZOOM_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void zoomOut() {
|
public void zoomOut() {
|
||||||
transforms.addAll(new Translate(0, 0, -1.5));
|
adjustZoomFactor(-ZOOM_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void panLeft() {
|
public void panLeft() {
|
||||||
transforms.addAll(new Translate(-1, 0, 0));
|
adjustHorizontalPan(-1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void panRight() {
|
public void panRight() {
|
||||||
transforms.addAll(new Translate(1, 0, 0));
|
adjustHorizontalPan(1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void panUp() {
|
public void panUp() {
|
||||||
transforms.addAll(new Translate(0, -1, 0));
|
adjustVerticalPan(-1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void panDown() {
|
public void panDown() {
|
||||||
transforms.addAll(new Translate(0, 1, 0));
|
adjustVerticalPan(1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ public class FinishScreenViewController implements Initializable {
|
|||||||
|
|
||||||
public void switchToStartScreenView() {
|
public void switchToStartScreenView() {
|
||||||
Sounds.playButtonClick();
|
Sounds.playButtonClick();
|
||||||
//TODO merge fix
|
|
||||||
setContentPane("/views/StartScreenView.fxml");
|
setContentPane("/views/StartScreenView.fxml");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import seng302.model.RaceState;
|
|||||||
import seng302.model.mark.CompoundMark;
|
import seng302.model.mark.CompoundMark;
|
||||||
import seng302.model.mark.Corner;
|
import seng302.model.mark.Corner;
|
||||||
import seng302.model.stream.xml.parser.RaceXMLData;
|
import seng302.model.stream.xml.parser.RaceXMLData;
|
||||||
import seng302.discoveryServer.DiscoveryServerClient;
|
|
||||||
import seng302.utilities.Sounds;
|
import seng302.utilities.Sounds;
|
||||||
import seng302.visualiser.GameView;
|
import seng302.visualiser.GameView;
|
||||||
import seng302.visualiser.controllers.cells.PlayerCell;
|
import seng302.visualiser.controllers.cells.PlayerCell;
|
||||||
@@ -30,7 +29,11 @@ import seng302.visualiser.controllers.dialogs.BoatCustomizeController;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
|
|
||||||
public class LobbyController implements Initializable {
|
public class LobbyController implements Initializable {
|
||||||
|
|
||||||
@@ -83,25 +86,21 @@ public class LobbyController implements Initializable {
|
|||||||
serverName.setText(ViewManager.getInstance().getProperty("serverName"));
|
serverName.setText(ViewManager.getInstance().getProperty("serverName"));
|
||||||
mapName.setText(ViewManager.getInstance().getProperty("mapName"));
|
mapName.setText(ViewManager.getInstance().getProperty("mapName"));
|
||||||
|
|
||||||
if (DiscoveryServerClient.getRoomCode() != null){
|
|
||||||
setRoomCode(DiscoveryServerClient.getRoomCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewManager.getInstance().getPlayerList().addListener((ListChangeListener<String>) c -> Platform.runLater(this::refreshPlayerList));
|
ViewManager.getInstance().getPlayerList().addListener((ListChangeListener<String>) c -> Platform.runLater(this::refreshPlayerList));
|
||||||
|
|
||||||
ViewManager.getInstance().getPlayerList().setAll(ViewManager.getInstance().getPlayerList().sorted());
|
ViewManager.getInstance().getPlayerList().setAll(ViewManager.getInstance().getPlayerList().sorted());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
customizeButton.setOnMouseReleased(event -> {
|
||||||
|
customizationDialog = createCustomizeDialog();
|
||||||
|
Sounds.playButtonClick();
|
||||||
|
customizationDialog.show();
|
||||||
|
});
|
||||||
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
Integer playerId = ViewManager.getInstance().getGameClient().getServerThread().getClientId();
|
Integer playerId = ViewManager.getInstance().getGameClient().getServerThread().getClientId();
|
||||||
|
|
||||||
playersColor = Colors.getColor(playerId - 1);
|
playersColor = Colors.getColor(playerId - 1);
|
||||||
customizationDialog = createCustomizeDialog();
|
|
||||||
|
|
||||||
customizeButton.setOnMouseReleased(event -> {
|
|
||||||
Sounds.playButtonClick();
|
|
||||||
customizationDialog.show();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
leaveLobbyButton.setOnMouseEntered(e -> Sounds.playHoverSound());
|
leaveLobbyButton.setOnMouseEntered(e -> Sounds.playHoverSound());
|
||||||
@@ -131,6 +130,8 @@ public class LobbyController implements Initializable {
|
|||||||
controller.setPlayerName(this.playerBoats
|
controller.setPlayerName(this.playerBoats
|
||||||
.get(ViewManager.getInstance().getGameClient().getServerThread().getClientId())
|
.get(ViewManager.getInstance().getGameClient().getServerThread().getClientId())
|
||||||
.getBoatName());
|
.getBoatName());
|
||||||
|
controller.setCurrentBoat(this.playerBoats.get(ViewManager.getInstance().getGameClient().getServerThread().getClientId())
|
||||||
|
.getBoatType().toString());
|
||||||
|
|
||||||
return customizationDialog;
|
return customizationDialog;
|
||||||
}
|
}
|
||||||
@@ -204,7 +205,7 @@ public class LobbyController implements Initializable {
|
|||||||
FXMLLoader loader = new FXMLLoader(
|
FXMLLoader loader = new FXMLLoader(
|
||||||
getClass().getResource("/views/cells/PlayerCell.fxml"));
|
getClass().getResource("/views/cells/PlayerCell.fxml"));
|
||||||
|
|
||||||
loader.setController(new PlayerCell(playerId, yacht.getBoatName(), yacht.getColour()));
|
loader.setController(new PlayerCell(playerId, yacht));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pane = loader.load();
|
pane = loader.load();
|
||||||
@@ -244,8 +245,4 @@ public class LobbyController implements Initializable {
|
|||||||
public void closeCustomizationDialog() {
|
public void closeCustomizationDialog() {
|
||||||
customizationDialog.close();
|
customizationDialog.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRoomCode(String roomCode) {
|
|
||||||
roomLabel.setText("Room#" + roomCode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,12 +48,14 @@ import javafx.scene.shape.Polyline;
|
|||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import javafx.stage.StageStyle;
|
import javafx.stage.StageStyle;
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
import seng302.model.ClientYacht;
|
import seng302.model.ClientYacht;
|
||||||
import seng302.model.ClientYacht.PowerUpListener;
|
import seng302.model.ClientYacht.PowerUpListener;
|
||||||
import seng302.model.RaceState;
|
import seng302.model.RaceState;
|
||||||
import seng302.model.mark.CompoundMark;
|
import seng302.model.mark.CompoundMark;
|
||||||
import seng302.model.mark.Mark;
|
import seng302.model.mark.Mark;
|
||||||
import seng302.model.stream.xml.parser.RaceXMLData;
|
import seng302.model.stream.xml.parser.RaceXMLData;
|
||||||
|
import seng302.model.token.Token;
|
||||||
import seng302.model.token.TokenType;
|
import seng302.model.token.TokenType;
|
||||||
import seng302.utilities.Sounds;
|
import seng302.utilities.Sounds;
|
||||||
import seng302.visualiser.GameView3D;
|
import seng302.visualiser.GameView3D;
|
||||||
@@ -95,7 +97,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
@FXML
|
@FXML
|
||||||
private Label timerLabel;
|
private Label timerLabel;
|
||||||
@FXML
|
@FXML
|
||||||
private StackPane contentAnchorPane;
|
private StackPane contentStackPane;
|
||||||
|
|
||||||
private GridPane contentGridPane;
|
private GridPane contentGridPane;
|
||||||
@FXML
|
@FXML
|
||||||
@@ -119,7 +121,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
@FXML
|
@FXML
|
||||||
private Label positionLabel, boatSpeedLabel, boatHeadingLabel;
|
private Label positionLabel, boatSpeedLabel, boatHeadingLabel;
|
||||||
@FXML
|
@FXML
|
||||||
private ImageView velocityIcon, handlingIcon, windWalkerIcon, bumperIcon;
|
private ImageView velocityIcon, handlingIcon, windWalkerIcon, bumperIcon, badRandomIcon;
|
||||||
|
|
||||||
//Race Data
|
//Race Data
|
||||||
private Map<Integer, ClientYacht> participants;
|
private Map<Integer, ClientYacht> participants;
|
||||||
@@ -140,12 +142,14 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
private JFXDialog finishScreenDialog;
|
private JFXDialog finishScreenDialog;
|
||||||
private FinishDialogController finishDialogController;
|
private FinishDialogController finishDialogController;
|
||||||
|
|
||||||
|
//Icon stuff
|
||||||
|
private Timer blinkingTimer = new Timer();
|
||||||
|
private ImageView iconToDisplay;
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
Sounds.stopMusic();
|
Sounds.stopMusic();
|
||||||
Sounds.playRaceMusic();
|
Sounds.playRaceMusic();
|
||||||
|
|
||||||
finishScreenDialog = createFinishDialog();
|
|
||||||
|
|
||||||
// Load a default important annotation state
|
// Load a default important annotation state
|
||||||
//importantAnnotations = new ImportantAnnotationsState();
|
//importantAnnotations = new ImportantAnnotationsState();
|
||||||
|
|
||||||
@@ -190,9 +194,10 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
// chatHistory.textProperty().addListener((obs, oldValue, newValue) -> {
|
// chatHistory.textProperty().addListener((obs, oldValue, newValue) -> {
|
||||||
// chatHistory.setScrollTop(Double.MAX_VALUE);
|
// chatHistory.setScrollTop(Double.MAX_VALUE);
|
||||||
// });
|
// });
|
||||||
rvAnchorPane.setOnMouseClicked((event) ->
|
|
||||||
rvAnchorPane.requestFocus()
|
contentStackPane.setOnMouseClicked(event -> {
|
||||||
);
|
contentStackPane.requestFocus();
|
||||||
|
});
|
||||||
|
|
||||||
//Makes the chat history non transparent when clicked on
|
//Makes the chat history non transparent when clicked on
|
||||||
chatInput.focusedProperty().addListener(new ChangeListener<Boolean>() {
|
chatInput.focusedProperty().addListener(new ChangeListener<Boolean>() {
|
||||||
@@ -210,26 +215,27 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
|
|
||||||
public void showFinishDialog(ArrayList<ClientYacht> finishedBoats) {
|
public void showFinishDialog(ArrayList<ClientYacht> finishedBoats) {
|
||||||
raceState.setRaceStarted(false);
|
raceState.setRaceStarted(false);
|
||||||
finishDialogController.setFinishedBoats(finishedBoats);
|
createFinishDialog(finishedBoats);
|
||||||
finishScreenDialog.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private JFXDialog createFinishDialog() {
|
/**
|
||||||
|
* Create finishScreenDialog and set up finishDialogController.
|
||||||
|
*/
|
||||||
|
private void createFinishDialog(ArrayList<ClientYacht> finishedBoats) {
|
||||||
FXMLLoader dialog = new FXMLLoader(
|
FXMLLoader dialog = new FXMLLoader(
|
||||||
getClass().getResource("/views/dialogs/RaceFinishDialog.fxml"));
|
getClass().getResource("/views/dialogs/RaceFinishDialog.fxml"));
|
||||||
|
|
||||||
JFXDialog finishScreenDialog = null;
|
Platform.runLater(() -> {
|
||||||
|
try {
|
||||||
try {
|
finishScreenDialog = new JFXDialog(contentStackPane, dialog.load(),
|
||||||
finishScreenDialog = new JFXDialog(contentAnchorPane, dialog.load(),
|
JFXDialog.DialogTransition.CENTER);
|
||||||
JFXDialog.DialogTransition.CENTER);
|
finishDialogController = dialog.getController();
|
||||||
} catch (IOException e) {
|
finishDialogController.setFinishedBoats(finishedBoats);
|
||||||
e.printStackTrace();
|
finishScreenDialog.show();
|
||||||
}
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
finishDialogController = dialog.getController();
|
}
|
||||||
|
});
|
||||||
return finishScreenDialog;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -253,12 +259,13 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
});
|
});
|
||||||
|
|
||||||
player.addPowerUpListener(this::displayPowerUpIcon);
|
player.addPowerUpListener(this::displayPowerUpIcon);
|
||||||
|
player.addPowerDownListener(this::removeIcon);
|
||||||
|
|
||||||
updateOrder(raceState.getPlayerPositions());
|
updateOrder(raceState.getPlayerPositions());
|
||||||
gameView = new GameView3D();
|
gameView = new GameView3D();
|
||||||
// gameView.setFrameRateFXText(fpsDisplay);
|
// gameView.setFrameRateFXText(fpsDisplay);
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
contentAnchorPane.getChildren().add(0, gameView.getAssets());
|
contentStackPane.getChildren().add(0, gameView.getAssets());
|
||||||
((SubScene) gameView.getAssets()).widthProperty()
|
((SubScene) gameView.getAssets()).widthProperty()
|
||||||
.bind(ViewManager.getInstance().getStage().widthProperty());
|
.bind(ViewManager.getInstance().getStage().widthProperty());
|
||||||
((SubScene) gameView.getAssets()).heightProperty()
|
((SubScene) gameView.getAssets()).heightProperty()
|
||||||
@@ -301,7 +308,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
*/
|
*/
|
||||||
private void displayPowerUpIcon(ClientYacht yacht, TokenType tokenType) {
|
private void displayPowerUpIcon(ClientYacht yacht, TokenType tokenType) {
|
||||||
if (yacht == player) {
|
if (yacht == player) {
|
||||||
final ImageView iconToDisplay;
|
if (iconToDisplay != null) {
|
||||||
|
iconToDisplay.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
switch (tokenType) {
|
switch (tokenType) {
|
||||||
case BOOST:
|
case BOOST:
|
||||||
@@ -316,6 +325,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
case BUMPER:
|
case BUMPER:
|
||||||
iconToDisplay = bumperIcon;
|
iconToDisplay = bumperIcon;
|
||||||
break;
|
break;
|
||||||
|
case RANDOM:
|
||||||
|
iconToDisplay = badRandomIcon;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
iconToDisplay = velocityIcon;
|
iconToDisplay = velocityIcon;
|
||||||
}
|
}
|
||||||
@@ -324,7 +336,10 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
iconToDisplay.setVisible(true);
|
iconToDisplay.setVisible(true);
|
||||||
|
|
||||||
//Start blinking icon towards end
|
//Start blinking icon towards end
|
||||||
Timer blinkingTimer = new Timer();
|
if (blinkingTimer != null) {
|
||||||
|
blinkingTimer.cancel();
|
||||||
|
}
|
||||||
|
blinkingTimer = new Timer("Blinking Timer");
|
||||||
blinkingTimer.schedule(new TimerTask() {
|
blinkingTimer.schedule(new TimerTask() {
|
||||||
Boolean isVisible = true;
|
Boolean isVisible = true;
|
||||||
|
|
||||||
@@ -334,16 +349,14 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
iconToDisplay.setVisible(isVisible);
|
iconToDisplay.setVisible(isVisible);
|
||||||
}
|
}
|
||||||
}, (int) (tokenType.getTimeout() * ICON_BLINK_TIMEOUT_RATIO), ICON_BLINK_PERIOD);
|
}, (int) (tokenType.getTimeout() * ICON_BLINK_TIMEOUT_RATIO), ICON_BLINK_PERIOD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Turn icon off after the time out
|
public void removeIcon(ClientYacht yacht) {
|
||||||
Timer switchOffTimer = new Timer();
|
if (yacht == player) {
|
||||||
switchOffTimer.schedule(new TimerTask() {
|
blinkingTimer.cancel();
|
||||||
@Override
|
iconToDisplay.setVisible(false);
|
||||||
public void run() {
|
iconToDisplay = null;
|
||||||
blinkingTimer.cancel();
|
|
||||||
iconToDisplay.setVisible(false);
|
|
||||||
}
|
|
||||||
}, tokenType.getTimeout());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -874,7 +887,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
public String readChatInput() {
|
public String readChatInput() {
|
||||||
String chat = chatInput.getText();
|
String chat = chatInput.getText();
|
||||||
chatInput.clear();
|
chatInput.clear();
|
||||||
rvAnchorPane.requestFocus();
|
contentStackPane.requestFocus();
|
||||||
return chat;
|
return chat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.jfoenix.controls.JFXTextField;
|
|||||||
import com.jfoenix.validation.RequiredFieldValidator;
|
import com.jfoenix.validation.RequiredFieldValidator;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
@@ -15,7 +16,6 @@ import javafx.fxml.FXML;
|
|||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.Alert;
|
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.ScrollPane;
|
import javafx.scene.control.ScrollPane;
|
||||||
import javafx.scene.input.KeyCode;
|
import javafx.scene.input.KeyCode;
|
||||||
@@ -23,14 +23,12 @@ import javafx.scene.layout.StackPane;
|
|||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import seng302.discoveryServer.DiscoveryServer;
|
|
||||||
import seng302.gameServer.ServerDescription;
|
import seng302.gameServer.ServerDescription;
|
||||||
import seng302.discoveryServer.util.ServerListing;
|
|
||||||
import seng302.discoveryServer.DiscoveryServerClient;
|
|
||||||
import seng302.utilities.Sounds;
|
import seng302.utilities.Sounds;
|
||||||
import seng302.visualiser.ServerListener;
|
import seng302.visualiser.ServerListener;
|
||||||
import seng302.visualiser.ServerListenerDelegate;
|
import seng302.visualiser.ServerListenerDelegate;
|
||||||
import seng302.visualiser.controllers.cells.ServerCell;
|
import seng302.visualiser.controllers.cells.ServerCell;
|
||||||
|
import seng302.visualiser.controllers.dialogs.ServerCreationController;
|
||||||
import seng302.visualiser.validators.HostNameFieldValidator;
|
import seng302.visualiser.validators.HostNameFieldValidator;
|
||||||
import seng302.visualiser.validators.NumberRangeValidator;
|
import seng302.visualiser.validators.NumberRangeValidator;
|
||||||
import seng302.visualiser.validators.ValidationTools;
|
import seng302.visualiser.validators.ValidationTools;
|
||||||
@@ -55,14 +53,18 @@ public class ServerListController implements Initializable, ServerListenerDelega
|
|||||||
private JFXTextField serverHostName;
|
private JFXTextField serverHostName;
|
||||||
@FXML
|
@FXML
|
||||||
private JFXTextField serverPortNumber;
|
private JFXTextField serverPortNumber;
|
||||||
@FXML
|
|
||||||
private JFXButton roomConnectButton;
|
|
||||||
@FXML
|
|
||||||
private JFXTextField roomNumber;
|
|
||||||
//---------FXML END---------//
|
//---------FXML END---------//
|
||||||
|
|
||||||
private Label noServersFound;
|
private Label noServersFound;
|
||||||
private Logger logger = LoggerFactory.getLogger(ServerListController.class);
|
private Logger logger = LoggerFactory.getLogger(ServerListController.class);
|
||||||
|
private JFXDialog serverCreationDialog;
|
||||||
|
private List<ServerCreationDialogListener> serverCreationDialogListeners = new ArrayList<>();
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ServerCreationDialogListener {
|
||||||
|
|
||||||
|
void notifyClosure();
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: 12/09/17 ajm412: break this method down, its way too long.
|
// TODO: 12/09/17 ajm412: break this method down, its way too long.
|
||||||
@Override
|
@Override
|
||||||
@@ -72,17 +74,6 @@ public class ServerListController implements Initializable, ServerListenerDelega
|
|||||||
// Set Event Bindings
|
// Set Event Bindings
|
||||||
connectButton.setOnMouseEntered(event -> Sounds.playHoverSound());
|
connectButton.setOnMouseEntered(event -> Sounds.playHoverSound());
|
||||||
serverListHostButton.setOnMouseEntered(event -> Sounds.playHoverSound());
|
serverListHostButton.setOnMouseEntered(event -> Sounds.playHoverSound());
|
||||||
|
|
||||||
roomConnectButton.setOnMouseReleased(event -> {
|
|
||||||
connectToRoomCode(roomNumber.getText());
|
|
||||||
Sounds.playButtonClick();
|
|
||||||
});
|
|
||||||
roomNumber.setOnKeyPressed(event -> {
|
|
||||||
if (event.getCode().equals(KeyCode.ENTER)) {
|
|
||||||
connectToRoomCode(roomNumber.getText());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connectButton.setOnMouseReleased(event -> {
|
connectButton.setOnMouseReleased(event -> {
|
||||||
attemptToDirectConnect();
|
attemptToDirectConnect();
|
||||||
Sounds.playButtonClick();
|
Sounds.playButtonClick();
|
||||||
@@ -131,22 +122,37 @@ public class ServerListController implements Initializable, ServerListenerDelega
|
|||||||
serverListVBox.getChildren().add(noServersFound);
|
serverListVBox.getChildren().add(noServersFound);
|
||||||
|
|
||||||
// Set up dialog for server creation
|
// Set up dialog for server creation
|
||||||
|
serverListHostButton.setOnAction(action -> {
|
||||||
|
showServerCreationDialog();
|
||||||
|
});
|
||||||
|
|
||||||
|
addServerCreationDialogListener(this::closeServerCreationDialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows Server Creation Dialog when "Host" button is clicked.
|
||||||
|
*/
|
||||||
|
private void showServerCreationDialog() {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
FXMLLoader dialogContent = new FXMLLoader(getClass().getResource(
|
FXMLLoader dialogContent = new FXMLLoader(getClass().getResource(
|
||||||
"/views/dialogs/ServerCreationDialog.fxml"));
|
"/views/dialogs/ServerCreationDialog.fxml"));
|
||||||
try {
|
try {
|
||||||
JFXDialog dialog = new JFXDialog(serverListMainStackPane, dialogContent.load(),
|
serverCreationDialog = new JFXDialog(serverListMainStackPane, dialogContent.load(),
|
||||||
DialogTransition.CENTER);
|
DialogTransition.CENTER);
|
||||||
serverListHostButton.setOnAction(action -> {
|
ServerCreationController serverCreationController = dialogContent.getController();
|
||||||
dialog.show();
|
serverCreationController.setListener(serverCreationDialogListeners);
|
||||||
Sounds.playButtonClick();
|
serverCreationDialog.show();
|
||||||
});
|
Sounds.playButtonClick();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.warn("Could not create Server Creation Dialog.");
|
logger.warn("Could not create Server Creation Dialog.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void closeServerCreationDialog() {
|
||||||
|
serverCreationDialog.close();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the connection and attempts to connect to a given hostname and port number.
|
* Validates the connection and attempts to connect to a given hostname and port number.
|
||||||
*/
|
*/
|
||||||
@@ -169,24 +175,6 @@ public class ServerListController implements Initializable, ServerListenerDelega
|
|||||||
return hostNameValid && portNumberValid;
|
return hostNameValid && portNumberValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void connectToRoomCode(String roomCode){
|
|
||||||
try {
|
|
||||||
ServerListing serverListing = new DiscoveryServerClient().getServerForRoomCode(roomCode);
|
|
||||||
ViewManager.getInstance().getGameClient().runAsClient(serverListing.getAddress(), serverListing.getPortNumber());
|
|
||||||
}
|
|
||||||
catch (java.net.ConnectException e){
|
|
||||||
//TODO Add proper dialog
|
|
||||||
logger.warn("Couldn't connect to discovery server");
|
|
||||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
|
||||||
alert.setHeaderText("Couldn't connect to discovery server");
|
|
||||||
alert.setContentText("Couldn't connect to " + DiscoveryServer.DISCOVERY_SERVER);
|
|
||||||
alert.showAndWait();
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
logger.warn("Error discovering room code");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connects the user to a lobby via the Direct Connect form.
|
* Connects the user to a lobby via the Direct Connect form.
|
||||||
*/
|
*/
|
||||||
@@ -233,4 +221,14 @@ public class ServerListController implements Initializable, ServerListenerDelega
|
|||||||
public void serverDetected(ServerDescription serverDescription, List<ServerDescription> servers) {
|
public void serverDetected(ServerDescription serverDescription, List<ServerDescription> servers) {
|
||||||
Platform.runLater(() -> refreshServers(servers));
|
Platform.runLater(() -> refreshServers(servers));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addServerCreationDialogListener(
|
||||||
|
ServerCreationDialogListener serverCreationDialogListener) {
|
||||||
|
serverCreationDialogListeners.add(serverCreationDialogListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeServerCreationDialogListener(
|
||||||
|
ServerCreationDialogListener serverCreationDialogListener) {
|
||||||
|
serverCreationDialogListeners.remove(serverCreationDialogListener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package seng302.visualiser.controllers;
|
|||||||
|
|
||||||
import com.jfoenix.controls.JFXButton;
|
import com.jfoenix.controls.JFXButton;
|
||||||
import com.jfoenix.controls.JFXDecorator;
|
import com.jfoenix.controls.JFXDecorator;
|
||||||
|
import com.jfoenix.controls.JFXDialog;
|
||||||
|
import com.jfoenix.controls.JFXDialog.DialogTransition;
|
||||||
|
import com.jfoenix.controls.JFXSnackbar;
|
||||||
import com.jfoenix.svg.SVGGlyph;
|
import com.jfoenix.svg.SVGGlyph;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -15,6 +18,7 @@ import javafx.scene.Scene;
|
|||||||
import javafx.scene.SceneAntialiasing;
|
import javafx.scene.SceneAntialiasing;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -23,6 +27,8 @@ import seng302.gameServer.ServerAdvertiser;
|
|||||||
import seng302.utilities.BonjourInstallChecker;
|
import seng302.utilities.BonjourInstallChecker;
|
||||||
import seng302.utilities.Sounds;
|
import seng302.utilities.Sounds;
|
||||||
import seng302.visualiser.GameClient;
|
import seng302.visualiser.GameClient;
|
||||||
|
import seng302.visualiser.controllers.dialogs.KeyBindingDialogController;
|
||||||
|
import seng302.visualiser.controllers.dialogs.PopupDialogController;
|
||||||
|
|
||||||
public class ViewManager {
|
public class ViewManager {
|
||||||
|
|
||||||
@@ -32,12 +38,9 @@ public class ViewManager {
|
|||||||
private HashMap<String, String> properties; //TODO is this the best way to do this??
|
private HashMap<String, String> properties; //TODO is this the best way to do this??
|
||||||
private ObservableList<String> playerList;
|
private ObservableList<String> playerList;
|
||||||
private Logger logger = LoggerFactory.getLogger(ViewManager.class);
|
private Logger logger = LoggerFactory.getLogger(ViewManager.class);
|
||||||
|
|
||||||
public Stage getStage() {
|
|
||||||
return stage;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Stage stage;
|
private Stage stage;
|
||||||
|
private JFXSnackbar jfxSnackbar;
|
||||||
|
private JFXDialog keyBindingDialog;
|
||||||
|
|
||||||
private ViewManager() {
|
private ViewManager() {
|
||||||
properties = new HashMap<>();
|
properties = new HashMap<>();
|
||||||
@@ -119,12 +122,31 @@ public class ViewManager {
|
|||||||
//Get the button box
|
//Get the button box
|
||||||
HBox btns = (HBox) decorator.getChildren().get(0);
|
HBox btns = (HBox) decorator.getChildren().get(0);
|
||||||
|
|
||||||
|
//Create settings button -- [WIP]
|
||||||
|
JFXButton btnKeyBinding = new JFXButton();
|
||||||
|
btnKeyBinding.setText(" Key Bindings");
|
||||||
|
btnKeyBinding.setStyle("-fx-text-fill:#fff");
|
||||||
|
btnKeyBinding.getStyleClass().add("jfx-decorator-button");
|
||||||
|
btnKeyBinding.setCursor(Cursor.HAND);
|
||||||
|
btnKeyBinding.setFocusTraversable(false);
|
||||||
|
|
||||||
|
btnKeyBinding.setOnMouseClicked(event -> Platform.runLater(() -> {
|
||||||
|
try {
|
||||||
|
if (!checkDialogOpened(decorator.getChildren())) {
|
||||||
|
showKeyBindingDialog();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.warn("Something went wrong when opening key bind dialog");
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
//Create new button
|
//Create new button
|
||||||
JFXButton btnMute = new JFXButton();
|
JFXButton btnMute = new JFXButton();
|
||||||
btnMute.setText(" Toggle Sound");
|
btnMute.setText(" Toggle Sound");
|
||||||
btnMute.setStyle("-fx-text-fill:#fff");
|
btnMute.setStyle("-fx-text-fill:#fff");
|
||||||
btnMute.getStyleClass().add("jfx-decorator-button");
|
btnMute.getStyleClass().add("jfx-decorator-button");
|
||||||
btnMute.setCursor(Cursor.HAND);
|
btnMute.setCursor(Cursor.HAND);
|
||||||
|
btnMute.setFocusTraversable(false);
|
||||||
|
|
||||||
//Create Graphics
|
//Create Graphics
|
||||||
SVGGlyph spacer = new SVGGlyph(0, "SPACER", "", Color.WHITE);
|
SVGGlyph spacer = new SVGGlyph(0, "SPACER", "", Color.WHITE);
|
||||||
@@ -134,9 +156,13 @@ public class ViewManager {
|
|||||||
SVGGlyph volumeOff = new SVGGlyph(0, "VOLUME_ON",
|
SVGGlyph volumeOff = new SVGGlyph(0, "VOLUME_ON",
|
||||||
"M13.5,9 C13.5,7.2 12.5,5.7 11,5 L11,7.2 L13.5,9.7 L13.5,9 L13.5,9 Z M16,9 C16,9.9 15.8,10.8 15.5,11.6 L17,13.1 C17.7,11.9 18,10.4 18,8.9 C18,4.6 15,1 11,0.1 L11,2.2 C13.9,3.2 16,5.8 16,9 L16,9 Z M1.3,0 L0,1.3 L4.7,6 L0,6 L0,12 L4,12 L9,17 L9,10.3 L13.3,14.6 C12.6,15.1 11.9,15.5 11,15.8 L11,17.9 C12.4,17.6 13.6,17 14.7,16.1 L16.7,18.1 L18,16.8 L9,7.8 L1.3,0 L1.3,0 Z M9,1 L6.9,3.1 L9,5.2 L9,1 L9,1 Z",
|
"M13.5,9 C13.5,7.2 12.5,5.7 11,5 L11,7.2 L13.5,9.7 L13.5,9 L13.5,9 Z M16,9 C16,9.9 15.8,10.8 15.5,11.6 L17,13.1 C17.7,11.9 18,10.4 18,8.9 C18,4.6 15,1 11,0.1 L11,2.2 C13.9,3.2 16,5.8 16,9 L16,9 Z M1.3,0 L0,1.3 L4.7,6 L0,6 L0,12 L4,12 L9,17 L9,10.3 L13.3,14.6 C12.6,15.1 11.9,15.5 11,15.8 L11,17.9 C12.4,17.6 13.6,17 14.7,16.1 L16.7,18.1 L18,16.8 L9,7.8 L1.3,0 L1.3,0 Z M9,1 L6.9,3.1 L9,5.2 L9,1 L9,1 Z",
|
||||||
Color.WHITE);
|
Color.WHITE);
|
||||||
|
SVGGlyph keyBindingGlyph = new SVGGlyph(0, "KEY_BINDING",
|
||||||
|
"M20 5H4c-1.1 0-1.99.9-1.99 2L2 17c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-9 3h2v2h-2V8zm0 3h2v2h-2v-2zM8 8h2v2H8V8zm0 3h2v2H8v-2zm-1 2H5v-2h2v2zm0-3H5V8h2v2zm9 7H8v-2h8v2zm0-4h-2v-2h2v2zm0-3h-2V8h2v2zm3 3h-2v-2h2v2zm0-3h-2V8h2v2z",
|
||||||
|
Color.WHITE);
|
||||||
volumeOn.setSize(16, 16);
|
volumeOn.setSize(16, 16);
|
||||||
volumeOff.setSize(16, 16);
|
volumeOff.setSize(16, 16);
|
||||||
spacer.setSize(40, 16);
|
spacer.setSize(40, 16);
|
||||||
|
keyBindingGlyph.setSize(24, 16);
|
||||||
|
|
||||||
// Determine which graphic should go on the button
|
// Determine which graphic should go on the button
|
||||||
if (Sounds.isMusicMuted() && Sounds.isSoundEffectsMuted()) {
|
if (Sounds.isMusicMuted() && Sounds.isSoundEffectsMuted()) {
|
||||||
@@ -145,9 +171,12 @@ public class ViewManager {
|
|||||||
btnMute.setGraphic(volumeOn);
|
btnMute.setGraphic(volumeOn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btnKeyBinding.setGraphic(keyBindingGlyph);
|
||||||
|
|
||||||
// Add Buttons
|
// Add Buttons
|
||||||
btns.getChildren().add(0, spacer);
|
btns.getChildren().add(0, spacer);
|
||||||
btns.getChildren().add(0, btnMute);
|
btns.getChildren().add(0, btnMute);
|
||||||
|
btns.getChildren().add(0, btnKeyBinding);
|
||||||
btnMute.setOnAction((action) -> {
|
btnMute.setOnAction((action) -> {
|
||||||
Sounds.toggleAllSounds();
|
Sounds.toggleAllSounds();
|
||||||
if (btnMute.getGraphic().equals(volumeOff)) {
|
if (btnMute.getGraphic().equals(volumeOff)) {
|
||||||
@@ -157,6 +186,85 @@ public class ViewManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
jfxSnackbar = new JFXSnackbar(decorator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively find JFXDialog given a starting node. Will traverse children of StackPane.
|
||||||
|
*
|
||||||
|
* @param nodes children nodes to be check.
|
||||||
|
* @return true if node contains JFXDialog.
|
||||||
|
*/
|
||||||
|
private Boolean checkDialogOpened(ObservableList<Node> nodes) {
|
||||||
|
boolean foundJFXDialog = false;
|
||||||
|
for (Node node : nodes) {
|
||||||
|
if (node instanceof JFXDialog) {
|
||||||
|
return true;
|
||||||
|
} else if (node instanceof StackPane) {
|
||||||
|
foundJFXDialog = checkDialogOpened(((StackPane) node).getChildren());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return foundJFXDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showKeyBindingDialog() throws IOException {
|
||||||
|
FXMLLoader dialogContent = new FXMLLoader(getClass().getResource(
|
||||||
|
"/views/dialogs/KeyBindingDialog.fxml"));
|
||||||
|
for (Node node : decorator.getChildren()) {
|
||||||
|
if (node instanceof StackPane) {
|
||||||
|
keyBindingDialog = new JFXDialog((StackPane) node,
|
||||||
|
dialogContent.load(),
|
||||||
|
DialogTransition.CENTER);
|
||||||
|
|
||||||
|
KeyBindingDialogController keyBindingDialogController = dialogContent
|
||||||
|
.getController();
|
||||||
|
keyBindingDialogController.setGameClient(this.gameClient);
|
||||||
|
keyBindingDialog.show();
|
||||||
|
decorator.requestFocus();
|
||||||
|
Sounds.playButtonClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeKeyBindingDialog() {
|
||||||
|
keyBindingDialog.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PopupDialogController showPopupDialog() {
|
||||||
|
FXMLLoader dialogContent = new FXMLLoader(
|
||||||
|
getClass().getResource("/views/dialogs/PopupDialog.fxml"));
|
||||||
|
for (Node node : decorator.getChildren()) {
|
||||||
|
if (node instanceof StackPane) {
|
||||||
|
try {
|
||||||
|
JFXDialog dialog = new JFXDialog((StackPane) node, dialogContent.load(),
|
||||||
|
DialogTransition.CENTER);
|
||||||
|
PopupDialogController popupDialogController = dialogContent.getController();
|
||||||
|
popupDialogController.setPopupDialog(dialog);
|
||||||
|
dialog.show();
|
||||||
|
return popupDialogController;
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Cannot load Popup dialog");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a snackbar at the bottom of the app for 1 second.
|
||||||
|
*
|
||||||
|
* @param snackbarText text to be displayed.
|
||||||
|
*/
|
||||||
|
public void showSnackbar(String snackbarText, boolean isWarning) {
|
||||||
|
if (isWarning) {
|
||||||
|
decorator.getStylesheets()
|
||||||
|
.add(getClass().getResource("/css/dialogs/Snackbar.css").toExternalForm());
|
||||||
|
} else {
|
||||||
|
if (decorator.getStylesheets().size() > 1) {
|
||||||
|
decorator.getStylesheets().remove(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jfxSnackbar.show(snackbarText, 1500);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -221,6 +329,7 @@ public class ViewManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the view to the Lobby Screen
|
* Change the view to the Lobby Screen
|
||||||
|
*
|
||||||
* @param disableReadyButton Boolean value so that clients can't try start a game.
|
* @param disableReadyButton Boolean value so that clients can't try start a game.
|
||||||
* @return A LobbyController object for the Lobby Screen.
|
* @return A LobbyController object for the Lobby Screen.
|
||||||
*/
|
*/
|
||||||
@@ -233,9 +342,8 @@ public class ViewManager {
|
|||||||
logger.error("Could not load lobby view");
|
logger.error("Could not load lobby view");
|
||||||
}
|
}
|
||||||
|
|
||||||
LobbyController lobbyController = loader.getController();
|
|
||||||
|
|
||||||
if (disableReadyButton) {
|
if (disableReadyButton) {
|
||||||
|
LobbyController lobbyController = loader.getController();
|
||||||
lobbyController.disableReadyButton();
|
lobbyController.disableReadyButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,8 +352,10 @@ public class ViewManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the view for the race. Creating a new decorator and destroying the old one.
|
* Sets up the view for the race. Creating a new decorator and destroying the old one.
|
||||||
|
*
|
||||||
* @return A RaceViewController for the race view screen.
|
* @return A RaceViewController for the race view screen.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public RaceViewController loadRaceView() {
|
public RaceViewController loadRaceView() {
|
||||||
FXMLLoader loader = loadFxml("/views/RaceView.fxml");
|
FXMLLoader loader = loadFxml("/views/RaceView.fxml");
|
||||||
// have to create a new stage and set the race view maximized as JFoenix decorator has
|
// have to create a new stage and set the race view maximized as JFoenix decorator has
|
||||||
@@ -267,17 +377,10 @@ public class ViewManager {
|
|||||||
scene.setOnKeyPressed(gameClient::keyPressed);
|
scene.setOnKeyPressed(gameClient::keyPressed);
|
||||||
scene.setOnKeyReleased(gameClient::keyReleased);
|
scene.setOnKeyReleased(gameClient::keyReleased);
|
||||||
|
|
||||||
// uncomment to make it full screen
|
|
||||||
// Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
|
|
||||||
// stage.setX(visualBounds.getMinX());
|
|
||||||
// stage.setY(visualBounds.getMinY());
|
|
||||||
// stage.setWidth(visualBounds.getWidth());
|
|
||||||
// stage.setHeight(visualBounds.getHeight());
|
|
||||||
// stage.setMaximized(true);
|
|
||||||
// stage.setFullScreen(true);
|
|
||||||
|
|
||||||
stage.setMinHeight(500);
|
stage.setMinHeight(500);
|
||||||
stage.setMinWidth(800);
|
stage.setMinWidth(800);
|
||||||
|
stage.setTitle("Party Parrots At Sea");
|
||||||
|
stage.getIcons().add(new Image(getClass().getResourceAsStream("/PP.png")));
|
||||||
stage.setOnCloseRequest(e -> closeAll());
|
stage.setOnCloseRequest(e -> closeAll());
|
||||||
stage.setScene(scene);
|
stage.setScene(scene);
|
||||||
stage.show();
|
stage.show();
|
||||||
@@ -286,7 +389,7 @@ public class ViewManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
while (loader.getController() == null){
|
while (loader.getController() == null) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(50);
|
Thread.sleep(50);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@@ -296,4 +399,9 @@ public class ViewManager {
|
|||||||
|
|
||||||
return loader.getController();
|
return loader.getController();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Stage getStage() {
|
||||||
|
return stage;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import javafx.scene.control.Label;
|
|||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
import seng302.model.ClientYacht;
|
||||||
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
import seng302.visualiser.fxObjects.assets_3D.BoatModel;
|
import seng302.visualiser.fxObjects.assets_3D.BoatModel;
|
||||||
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
|
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
|
||||||
@@ -24,11 +25,13 @@ public class PlayerCell {
|
|||||||
private String name;
|
private String name;
|
||||||
private Color boatColor;
|
private Color boatColor;
|
||||||
private Integer playerId;
|
private Integer playerId;
|
||||||
|
private BoatMeshType boatType;
|
||||||
|
|
||||||
public PlayerCell(Integer playerId, String playerName, Color color) {
|
public PlayerCell(Integer playerId, ClientYacht yacht) {
|
||||||
this.playerId = playerId;
|
this.playerId = playerId;
|
||||||
this.name = playerName;
|
this.name = yacht.getBoatName();
|
||||||
this.boatColor = color;
|
this.boatColor = yacht.getColour();
|
||||||
|
this.boatType = yacht.getBoatType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
@@ -37,7 +40,7 @@ public class PlayerCell {
|
|||||||
// Add Rotating Boat to Player Cell with players color on it.
|
// Add Rotating Boat to Player Cell with players color on it.
|
||||||
Group group = new Group();
|
Group group = new Group();
|
||||||
boatPane.getChildren().add(group);
|
boatPane.getChildren().add(group);
|
||||||
BoatModel bo = ModelFactory.boatIconView(BoatMeshType.DINGHY, this.boatColor);
|
BoatModel bo = ModelFactory.boatIconView(boatType, boatColor);
|
||||||
group.getChildren().add(bo.getAssets());
|
group.getChildren().add(bo.getAssets());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,15 +6,25 @@ import com.jfoenix.controls.JFXTextField;
|
|||||||
import com.jfoenix.validation.RequiredFieldValidator;
|
import com.jfoenix.validation.RequiredFieldValidator;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import javafx.event.ActionEvent;
|
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.Group;
|
||||||
|
import javafx.scene.PointLight;
|
||||||
|
import javafx.scene.control.ProgressBar;
|
||||||
|
import javafx.scene.layout.Background;
|
||||||
|
import javafx.scene.layout.BackgroundFill;
|
||||||
|
import javafx.scene.layout.CornerRadii;
|
||||||
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import seng302.gameServer.messages.CustomizeRequestType;
|
import seng302.gameServer.messages.CustomizeRequestType;
|
||||||
import seng302.utilities.Sounds;
|
import seng302.utilities.Sounds;
|
||||||
import seng302.visualiser.ClientToServerThread;
|
import seng302.visualiser.ClientToServerThread;
|
||||||
import seng302.visualiser.controllers.LobbyController;
|
import seng302.visualiser.controllers.LobbyController;
|
||||||
import seng302.visualiser.controllers.ViewManager;
|
import seng302.visualiser.controllers.ViewManager;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.BoatModel;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
|
||||||
import seng302.visualiser.validators.FieldLengthValidator;
|
import seng302.visualiser.validators.FieldLengthValidator;
|
||||||
import seng302.visualiser.validators.ValidationTools;
|
import seng302.visualiser.validators.ValidationTools;
|
||||||
|
|
||||||
@@ -24,23 +34,35 @@ public class BoatCustomizeController implements Initializable{
|
|||||||
@FXML
|
@FXML
|
||||||
private JFXColorPicker colorPicker;
|
private JFXColorPicker colorPicker;
|
||||||
@FXML
|
@FXML
|
||||||
|
private ProgressBar speedBar;
|
||||||
|
@FXML
|
||||||
|
private ProgressBar accelBar;
|
||||||
|
@FXML
|
||||||
|
private ProgressBar handleBar;
|
||||||
|
@FXML
|
||||||
private JFXButton submitBtn;
|
private JFXButton submitBtn;
|
||||||
@FXML
|
@FXML
|
||||||
private JFXTextField boatName;
|
private JFXTextField boatName;
|
||||||
@FXML
|
@FXML
|
||||||
void colorChanged(ActionEvent event) {
|
private Pane boatPane;
|
||||||
Color color = colorPicker.getValue();
|
@FXML
|
||||||
|
void colorChanged() {
|
||||||
|
refreshBoat();
|
||||||
}
|
}
|
||||||
//---------FXML END---------//
|
//---------FXML END---------//
|
||||||
|
|
||||||
private ClientToServerThread socketThread;
|
private ClientToServerThread socketThread;
|
||||||
private LobbyController lobbyController;
|
private LobbyController lobbyController;
|
||||||
|
private BoatMeshType currentBoat;
|
||||||
|
private Double maxSpeedMultiplier = 1.0;
|
||||||
|
private Double maxTurnRateMultiplier = 1.0;
|
||||||
|
private Double maxAccelerationMultiplier = 1.0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
|
|
||||||
socketThread = ViewManager.getInstance().getGameClient().getServerThread();
|
socketThread = ViewManager.getInstance().getGameClient().getServerThread();
|
||||||
|
findMaxStats();
|
||||||
RequiredFieldValidator playerNameReqValidator = new RequiredFieldValidator();
|
RequiredFieldValidator playerNameReqValidator = new RequiredFieldValidator();
|
||||||
playerNameReqValidator.setMessage("Player name required.");
|
playerNameReqValidator.setMessage("Player name required.");
|
||||||
|
|
||||||
@@ -48,6 +70,8 @@ public class BoatCustomizeController implements Initializable{
|
|||||||
playerNameLengthValidator.setMessage("Player name too long.");
|
playerNameLengthValidator.setMessage("Player name too long.");
|
||||||
|
|
||||||
boatName.setValidators(playerNameLengthValidator, playerNameReqValidator);
|
boatName.setValidators(playerNameLengthValidator, playerNameReqValidator);
|
||||||
|
boatPane.setBackground(
|
||||||
|
new Background(new BackgroundFill(Color.SKYBLUE, CornerRadii.EMPTY, Insets.EMPTY)));
|
||||||
|
|
||||||
submitBtn.setOnMouseReleased(event -> {
|
submitBtn.setOnMouseReleased(event -> {
|
||||||
Sounds.playButtonClick();
|
Sounds.playButtonClick();
|
||||||
@@ -78,7 +102,10 @@ public class BoatCustomizeController implements Initializable{
|
|||||||
colorArray[2] = (byte) blue;
|
colorArray[2] = (byte) blue;
|
||||||
|
|
||||||
socketThread.sendCustomizationRequest(CustomizeRequestType.COLOR, colorArray);
|
socketThread.sendCustomizationRequest(CustomizeRequestType.COLOR, colorArray);
|
||||||
|
socketThread.sendCustomizationRequest(CustomizeRequestType.SHAPE, currentBoat.toString().getBytes());
|
||||||
lobbyController.closeCustomizationDialog();
|
lobbyController.closeCustomizationDialog();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,4 +120,61 @@ public class BoatCustomizeController implements Initializable{
|
|||||||
public void setParentController(LobbyController lobbyController){
|
public void setParentController(LobbyController lobbyController){
|
||||||
this.lobbyController = lobbyController;
|
this.lobbyController = lobbyController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCurrentBoat(String boatType) {
|
||||||
|
currentBoat = BoatMeshType.valueOf(boatType);
|
||||||
|
displayCurrentBoat();
|
||||||
|
refreshStatBars(currentBoat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void nextBoat() {
|
||||||
|
currentBoat = BoatMeshType.getNextBoatType(currentBoat);
|
||||||
|
displayCurrentBoat();
|
||||||
|
refreshStatBars(currentBoat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void prevBoat() {
|
||||||
|
currentBoat = BoatMeshType.getPrevBoatType(currentBoat);
|
||||||
|
displayCurrentBoat();
|
||||||
|
refreshStatBars(currentBoat);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displayCurrentBoat() {
|
||||||
|
boatPane.getChildren().clear();
|
||||||
|
Group group = new Group();
|
||||||
|
boatPane.getChildren().add(group);
|
||||||
|
BoatModel bo = ModelFactory.boatCustomiseView(currentBoat, colorPicker.getValue());
|
||||||
|
group.getChildren().add(bo.getAssets());
|
||||||
|
group.getChildren().add(new PointLight());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshBoat() {
|
||||||
|
boatPane.getChildren().clear();
|
||||||
|
Group group = new Group();
|
||||||
|
boatPane.getChildren().add(group);
|
||||||
|
BoatModel bo = ModelFactory.boatCustomiseView(currentBoat, colorPicker.getValue());
|
||||||
|
group.getChildren().add(bo.getAssets());
|
||||||
|
refreshStatBars(currentBoat);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findMaxStats() {
|
||||||
|
for (BoatMeshType bmt: BoatMeshType.values()) {
|
||||||
|
if (bmt.turnStep > maxTurnRateMultiplier) {
|
||||||
|
maxTurnRateMultiplier = bmt.turnStep;
|
||||||
|
}
|
||||||
|
if (bmt.maxSpeedMultiplier > maxSpeedMultiplier) {
|
||||||
|
maxSpeedMultiplier = bmt.maxSpeedMultiplier;
|
||||||
|
}
|
||||||
|
if (bmt.accelerationMultiplier > maxAccelerationMultiplier) {
|
||||||
|
maxAccelerationMultiplier = bmt.accelerationMultiplier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshStatBars(BoatMeshType bo) {
|
||||||
|
speedBar.setProgress((bo.maxSpeedMultiplier) / maxSpeedMultiplier);
|
||||||
|
accelBar.setProgress(bo.accelerationMultiplier / maxAccelerationMultiplier);
|
||||||
|
handleBar.setProgress(bo.turnStep / maxTurnRateMultiplier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,195 @@
|
|||||||
|
package seng302.visualiser.controllers.dialogs;
|
||||||
|
|
||||||
|
import com.jfoenix.controls.JFXButton;
|
||||||
|
import com.jfoenix.controls.JFXToggleButton;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.Initializable;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.input.KeyEvent;
|
||||||
|
import seng302.model.GameKeyBind;
|
||||||
|
import seng302.model.KeyAction;
|
||||||
|
import seng302.visualiser.GameClient;
|
||||||
|
import seng302.visualiser.controllers.ViewManager;
|
||||||
|
|
||||||
|
public class KeyBindingDialogController implements Initializable {
|
||||||
|
|
||||||
|
//--------FXML BEGIN--------//
|
||||||
|
@FXML
|
||||||
|
private Label keyBindingDialogHeader;
|
||||||
|
@FXML
|
||||||
|
private Label closeLabel;
|
||||||
|
@FXML
|
||||||
|
private JFXButton zoomInbtn;
|
||||||
|
@FXML
|
||||||
|
private JFXButton zoomOutBtn;
|
||||||
|
@FXML
|
||||||
|
private JFXButton vmgBtn;
|
||||||
|
@FXML
|
||||||
|
private JFXButton sailInOutBtn;
|
||||||
|
@FXML
|
||||||
|
private JFXButton tackGybeBtn;
|
||||||
|
@FXML
|
||||||
|
private JFXButton upwindBtn;
|
||||||
|
@FXML
|
||||||
|
private JFXButton downwindBtn;
|
||||||
|
@FXML
|
||||||
|
private JFXButton resetBtn;
|
||||||
|
@FXML
|
||||||
|
private Label upwindLabel;
|
||||||
|
@FXML
|
||||||
|
private Label downwindLabel;
|
||||||
|
@FXML
|
||||||
|
private JFXToggleButton turningToggle;
|
||||||
|
@FXML
|
||||||
|
private JFXButton viewButton;
|
||||||
|
@FXML
|
||||||
|
private JFXButton rightButton;
|
||||||
|
@FXML
|
||||||
|
private JFXButton leftButton;
|
||||||
|
@FXML
|
||||||
|
private JFXButton forwardButton;
|
||||||
|
@FXML
|
||||||
|
private JFXButton backwardButton;
|
||||||
|
//---------FXML END---------//
|
||||||
|
|
||||||
|
private GameKeyBind gameKeyBind;
|
||||||
|
private List<JFXButton> buttons = new ArrayList<>();
|
||||||
|
private Map<Button, KeyAction> buttonActionMap;
|
||||||
|
private GameClient gameClient; // to send turning mode packet
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
|
gameKeyBind = GameKeyBind.getInstance();
|
||||||
|
buttons = new ArrayList<>();
|
||||||
|
Collections.addAll(buttons,
|
||||||
|
zoomInbtn, zoomOutBtn, vmgBtn, sailInOutBtn, tackGybeBtn, upwindBtn, downwindBtn,
|
||||||
|
viewButton, rightButton, leftButton, forwardButton, backwardButton);
|
||||||
|
bindButtonWithAction();
|
||||||
|
loadKeyBind();
|
||||||
|
|
||||||
|
buttons.forEach(button -> {
|
||||||
|
button.setOnMouseEntered(event -> mouseEnter(button));
|
||||||
|
button.setOnMousePressed(event -> buttonPressed(button));
|
||||||
|
button.setOnMouseExited(event -> mouseExit(button));
|
||||||
|
button.setOnKeyPressed(event -> keyPressed(event, button));
|
||||||
|
});
|
||||||
|
|
||||||
|
turningToggle.setOnMouseClicked(event -> toggleTurningMode());
|
||||||
|
|
||||||
|
resetBtn.setOnMouseClicked(event -> {
|
||||||
|
gameKeyBind.setToDefault();
|
||||||
|
loadKeyBind();
|
||||||
|
showSnackBar("All keys reset!", false);
|
||||||
|
});
|
||||||
|
|
||||||
|
closeLabel.setOnMouseClicked(event -> ViewManager.getInstance().closeKeyBindingDialog());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set buttons' label according to GameKeyBind settings
|
||||||
|
*/
|
||||||
|
private void loadKeyBind() {
|
||||||
|
buttons.forEach(
|
||||||
|
button -> button
|
||||||
|
.setText(gameKeyBind.getKeyCode(buttonActionMap.get(button)).getName()));
|
||||||
|
turningToggle.setSelected(gameKeyBind.isContinuouslyTurning());
|
||||||
|
if (gameKeyBind.isContinuouslyTurning()) {
|
||||||
|
upwindLabel.setText("ClOCKWISE TURNING");
|
||||||
|
downwindLabel.setText("ANTICLOCKWISE TURNING");
|
||||||
|
} else {
|
||||||
|
upwindLabel.setText("UPWIND");
|
||||||
|
downwindLabel.setText("DOWNWIND");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind buttons with specific action in a map.
|
||||||
|
*/
|
||||||
|
private void bindButtonWithAction() {
|
||||||
|
buttonActionMap = new HashMap<>();
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
buttonActionMap.put(buttons.get(i), KeyAction.getType(i + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prompt success / failure message for reassigning key action
|
||||||
|
*/
|
||||||
|
private void showSnackBar(String message, Boolean isWarning) {
|
||||||
|
ViewManager.getInstance().showSnackbar(message, isWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a mouse enters the button, the color and font size should change to highlight
|
||||||
|
* @param button
|
||||||
|
*/
|
||||||
|
private void mouseEnter(Button button) {
|
||||||
|
button.setStyle(""
|
||||||
|
+ "-fx-background-color: -fx-pp-theme-color;"
|
||||||
|
+ "-fx-text-fill: -fx-pp-front-color;"
|
||||||
|
+ "-fx-font-size: 15;");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prompt "press key..." to inform users assign a new key bind by pressing a key
|
||||||
|
* @param button
|
||||||
|
*/
|
||||||
|
private void buttonPressed(Button button) {
|
||||||
|
button.setText("PRESS KEY...");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When mouse leaves the button, return the button to the normal state in terms of text,
|
||||||
|
* color and font size
|
||||||
|
* @param button
|
||||||
|
*/
|
||||||
|
private void mouseExit(Button button) {
|
||||||
|
button.setText(GameKeyBind.getInstance().getKeyCode(buttonActionMap.get(button)).getName());
|
||||||
|
button.setStyle(""
|
||||||
|
+ "-fx-background-color: -fx-pp-front-color; "
|
||||||
|
+ "-fx-text-fill: -fx-pp-theme-color; "
|
||||||
|
+ "-fx-font-size: 13;");
|
||||||
|
keyBindingDialogHeader.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a key is pressed, check if the new binding conflicts to any existed settings, if not
|
||||||
|
* assign the selected action with the new key binding to GameKeyBind.
|
||||||
|
* @param event
|
||||||
|
* @param button
|
||||||
|
*/
|
||||||
|
private void keyPressed(KeyEvent event, Button button) {
|
||||||
|
event.consume();
|
||||||
|
KeyAction buttonAction = buttonActionMap.get(button);
|
||||||
|
if (gameKeyBind.bindKeyToAction(event.getCode(), buttonAction)) {
|
||||||
|
showSnackBar(button.getId() + " is set to " + event.getCode().getName(), false);
|
||||||
|
button.setText(gameKeyBind.getKeyCode(buttonAction).getName());
|
||||||
|
} else {
|
||||||
|
loadKeyBind();
|
||||||
|
showSnackBar(event.getCode().getName() + " is already in use", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the turning mode is toggled, update gameKeyBind and send out packet to notify the server
|
||||||
|
*/
|
||||||
|
private void toggleTurningMode() {
|
||||||
|
gameKeyBind.toggleTurningMode();
|
||||||
|
gameClient.sendToggleTurningModePacket();
|
||||||
|
loadKeyBind();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGameClient(GameClient gameClient) {
|
||||||
|
this.gameClient = gameClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package seng302.visualiser.controllers.dialogs;
|
||||||
|
|
||||||
|
import com.jfoenix.controls.JFXButton;
|
||||||
|
import com.jfoenix.controls.JFXDialog;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.Initializable;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.input.MouseEvent;
|
||||||
|
|
||||||
|
public class PopupDialogController implements Initializable {
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label headerLabel;
|
||||||
|
@FXML
|
||||||
|
private Label contentLabel;
|
||||||
|
@FXML
|
||||||
|
private Label closeLabel;
|
||||||
|
@FXML
|
||||||
|
private JFXButton optionButton;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private JFXDialog popupDialog;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.contentLabel.setText(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader(String header) {
|
||||||
|
this.headerLabel.setText(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOptionButton(JFXButton jfxButton) {
|
||||||
|
this.optionButton = jfxButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOptionButtonText(String text) {
|
||||||
|
this.optionButton.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOptionButtonEventHandler(EventHandler<? super MouseEvent> eventHandler) {
|
||||||
|
this.optionButton.setOnMouseClicked(eventHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPopupDialog(JFXDialog popupDialog) {
|
||||||
|
this.popupDialog = popupDialog;
|
||||||
|
this.closeLabel.setOnMouseClicked(event -> this.popupDialog.close());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,14 +5,15 @@ import com.jfoenix.controls.JFXSlider;
|
|||||||
import com.jfoenix.controls.JFXTextField;
|
import com.jfoenix.controls.JFXTextField;
|
||||||
import com.jfoenix.validation.RequiredFieldValidator;
|
import com.jfoenix.validation.RequiredFieldValidator;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.List;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.input.MouseEvent;
|
import javafx.scene.input.MouseEvent;
|
||||||
import seng302.gameServer.ServerDescription;
|
import seng302.gameServer.ServerDescription;
|
||||||
import seng302.utilities.Sounds;
|
import seng302.utilities.Sounds;
|
||||||
|
import seng302.visualiser.controllers.ServerListController.ServerCreationDialogListener;
|
||||||
import seng302.visualiser.controllers.ViewManager;
|
import seng302.visualiser.controllers.ViewManager;
|
||||||
import seng302.visualiser.validators.FieldLengthValidator;
|
import seng302.visualiser.validators.FieldLengthValidator;
|
||||||
import seng302.visualiser.validators.ValidationTools;
|
import seng302.visualiser.validators.ValidationTools;
|
||||||
@@ -28,8 +29,12 @@ public class ServerCreationController implements Initializable {
|
|||||||
private Label maxPlayersLabel;
|
private Label maxPlayersLabel;
|
||||||
@FXML
|
@FXML
|
||||||
private JFXButton submitBtn;
|
private JFXButton submitBtn;
|
||||||
|
@FXML
|
||||||
|
private Label closeLabel;
|
||||||
//---------FXML END---------//
|
//---------FXML END---------//
|
||||||
|
|
||||||
|
private List<ServerCreationDialogListener> serverCreationDialogListeners;
|
||||||
|
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
updateMaxPlayerLabel();
|
updateMaxPlayerLabel();
|
||||||
maxPlayersSlider.valueProperty().addListener((observable, oldValue, newValue) -> {
|
maxPlayersSlider.valueProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
@@ -49,6 +54,7 @@ public class ServerCreationController implements Initializable {
|
|||||||
validateServerSettings();
|
validateServerSettings();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
closeLabel.setOnMouseClicked(event -> notifyListeners());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,4 +93,14 @@ public class ServerCreationController implements Initializable {
|
|||||||
Sounds.playHoverSound();
|
Sounds.playHoverSound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setListener(List<ServerCreationDialogListener> serverCreationDialogListeners) {
|
||||||
|
this.serverCreationDialogListeners = serverCreationDialogListeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyListeners() {
|
||||||
|
for (ServerCreationDialogListener serverCreationDialogListener : serverCreationDialogListeners) {
|
||||||
|
serverCreationDialogListener.notifyClosure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,21 +2,59 @@ package seng302.visualiser.fxObjects.assets_3D;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Enum for boat meshes. Enum values should be of the form :
|
* Enum for boat meshes. Enum values should be of the form :
|
||||||
* ENUM_VALUE (hull file, mast file, Y offset of mast CoR from origin, sail file, Y offset of sail CoR from origin)
|
* ENUM_VALUE (hull file, mast file, Y offset of mast CoR from origin, sail file, Y offset of sail CoR from origin, jib file, fixed sail)
|
||||||
* Files must be valid .stl files.
|
* Files must be valid .stl files.
|
||||||
*/
|
*/
|
||||||
public enum BoatMeshType {
|
public enum BoatMeshType {
|
||||||
|
|
||||||
DINGHY ("dinghy_hull.stl", "dinghy_mast.stl", -1.36653, "dinghy_sail.stl", -1.36653);
|
DINGHY("dinghy_hull.stl", "dinghy_mast.stl", 1.36653, "dinghy_sail.stl", 1.36653, null, false, 1.8, 1.0, 1.0),
|
||||||
|
CATAMARAN("catamaran_hull.stl", "catamaran_mast.stl", 0.997, "catamaran_sail.stl",
|
||||||
|
0.997, null, false, 1.0, 1.4, 2.0),
|
||||||
|
PIRATE_SHIP("pirateship_hull.stl", "pirateship_mast.stl", -0.5415, "pirateship_mainsail.stl",
|
||||||
|
-0.5415, "pirateship_frontsail.stl", true, 1.2, 1.6, 1.2);
|
||||||
|
|
||||||
final String hullFile, mastFile, sailFile;
|
final String hullFile, mastFile, sailFile, jibFile;
|
||||||
final double mastOffset, sailOffset;
|
final double mastOffset, sailOffset;
|
||||||
|
public final double maxSpeedMultiplier;
|
||||||
|
public final double accelerationMultiplier;
|
||||||
|
public final double turnStep;
|
||||||
|
final boolean fixedSail;
|
||||||
|
final static BoatMeshType[] boatTypes = new BoatMeshType[]{DINGHY, CATAMARAN, PIRATE_SHIP};
|
||||||
|
|
||||||
BoatMeshType(String hullFile, String mastFile, double mastOffset, String sailFile, double sailOffset) {
|
BoatMeshType(String hullFile, String mastFile, double mastOffset, String sailFile,
|
||||||
|
double sailOffset, String jibFile, boolean fixedSail, double maxSpeedMultiplier, double accelerationMultiplier, double turnStep) {
|
||||||
this.hullFile = hullFile;
|
this.hullFile = hullFile;
|
||||||
this.mastFile = mastFile;
|
this.mastFile = mastFile;
|
||||||
this.mastOffset = mastOffset;
|
this.mastOffset = mastOffset;
|
||||||
this.sailFile = sailFile;
|
this.sailFile = sailFile;
|
||||||
this.sailOffset = sailOffset;
|
this.sailOffset = sailOffset;
|
||||||
|
this.jibFile = jibFile;
|
||||||
|
this.fixedSail = fixedSail;
|
||||||
|
this.maxSpeedMultiplier = maxSpeedMultiplier;
|
||||||
|
this.accelerationMultiplier = accelerationMultiplier;
|
||||||
|
this.turnStep = turnStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static BoatMeshType getNextBoatType(BoatMeshType boatType) {
|
||||||
|
for (int i = 0; i < boatTypes.length; i++) {
|
||||||
|
if (i == boatTypes.length -1) {
|
||||||
|
return boatTypes[0];
|
||||||
|
} else if (boatType == boatTypes[i]) {
|
||||||
|
return boatTypes[i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return boatType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BoatMeshType getPrevBoatType(BoatMeshType boatType) {
|
||||||
|
for (int i = 0; i < boatTypes.length; i++) {
|
||||||
|
if (i == 0 && boatType == boatTypes[i]) {
|
||||||
|
return boatTypes[boatTypes.length -1];
|
||||||
|
} else if (boatType == boatTypes[i]) {
|
||||||
|
return boatTypes[i-1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return boatType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,14 +34,16 @@ public class BoatModel extends Model {
|
|||||||
* @param degrees The rotation of the sail in degrees
|
* @param degrees The rotation of the sail in degrees
|
||||||
*/
|
*/
|
||||||
public void rotateSail(double degrees) {
|
public void rotateSail(double degrees) {
|
||||||
MeshView mast = getMeshViewChild(MAST_INDEX);
|
if (!meshType.fixedSail) {
|
||||||
MeshView sail = getMeshViewChild(SAIL_INDEX);
|
MeshView mast = getMeshViewChild(MAST_INDEX);
|
||||||
mast.getTransforms().setAll(
|
MeshView sail = getMeshViewChild(SAIL_INDEX);
|
||||||
new Rotate(degrees, -meshType.mastOffset, 0,0, new Point3D(0, 0, 1))
|
mast.getTransforms().setAll(
|
||||||
);
|
new Rotate(degrees, 0, -meshType.mastOffset, 0, new Point3D(0, 0, 1))
|
||||||
sail.getTransforms().setAll(
|
);
|
||||||
new Rotate(degrees, -meshType.sailOffset, 0,0, new Point3D(0, 0, 1))
|
sail.getTransforms().setAll(
|
||||||
);
|
new Rotate(degrees, 0, -meshType.sailOffset,0, new Point3D(0, 0, 1))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void hideSail() {
|
public void hideSail() {
|
||||||
@@ -69,4 +71,8 @@ public class BoatModel extends Model {
|
|||||||
private MeshView getMeshViewChild(int index) {
|
private MeshView getMeshViewChild(int index) {
|
||||||
return (MeshView) assets.getChildren().get(index);
|
return (MeshView) assets.getChildren().get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BoatMeshType getMeshType() {
|
||||||
|
return meshType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ package seng302.visualiser.fxObjects.assets_3D;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
import javafx.beans.property.ReadOnlyDoubleWrapper;
|
||||||
import javafx.geometry.Point3D;
|
import javafx.geometry.Point3D;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
@@ -11,7 +12,7 @@ import javafx.scene.transform.Rotate;
|
|||||||
/**
|
/**
|
||||||
* BoatGroup is a javafx group that by default contains a graphical objects for representing a 2
|
* BoatGroup is a javafx group that by default contains a graphical objects for representing a 2
|
||||||
* dimensional boat. It contains a single polygon for the boat, a group of lines to show it's path,
|
* dimensional boat. It contains a single polygon for the boat, a group of lines to show it's path,
|
||||||
* a wake object and two text labels to annotate the boat teams name and the boats velocity. The
|
* a wake object and two text labels to annotate the boat teams name and the boatTypes velocity. The
|
||||||
* boat will update it's position onscreen everytime UpdatePosition is called unless the window is
|
* boat will update it's position onscreen everytime UpdatePosition is called unless the window is
|
||||||
* minimized in which case it attempts to store animations and apply them when the window is
|
* minimized in which case it attempts to store animations and apply them when the window is
|
||||||
* maximised.
|
* maximised.
|
||||||
@@ -28,15 +29,18 @@ public class BoatObject extends Group {
|
|||||||
private Group wake;
|
private Group wake;
|
||||||
private Color colour = Color.BLACK;
|
private Color colour = Color.BLACK;
|
||||||
private Boolean isSelected = false;
|
private Boolean isSelected = false;
|
||||||
private Rotate rotation = new Rotate(0,0,1);
|
private Rotate rotation = new Rotate(0, new Point3D(0,0,1));
|
||||||
|
|
||||||
|
private ReadOnlyDoubleWrapper rotationProperty;
|
||||||
|
|
||||||
private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>();
|
private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a BoatGroup with the default triangular boat polygon.
|
* Creates a BoatGroup with the default triangular boat polygon.
|
||||||
*/
|
*/
|
||||||
public BoatObject() {
|
public BoatObject(BoatMeshType boatMeshType) {
|
||||||
boatAssets = ModelFactory.boatGameView(BoatMeshType.DINGHY, colour);
|
rotationProperty = new ReadOnlyDoubleWrapper(0.0);
|
||||||
|
boatAssets = ModelFactory.boatGameView(boatMeshType, colour);
|
||||||
boatAssets.hideSail();
|
boatAssets.hideSail();
|
||||||
boatAssets.getAssets().getTransforms().addAll(
|
boatAssets.getAssets().getTransforms().addAll(
|
||||||
rotation
|
rotation
|
||||||
@@ -66,8 +70,6 @@ public class BoatObject extends Group {
|
|||||||
* @param windDir .
|
* @param windDir .
|
||||||
*/
|
*/
|
||||||
public void moveTo(double x, double y, double rotation, double velocity, Boolean sailIn, double windDir) {
|
public void moveTo(double x, double y, double rotation, double velocity, Boolean sailIn, double windDir) {
|
||||||
Double dx = Math.abs(boatAssets.getAssets().getLayoutX() - x);
|
|
||||||
Double dy = Math.abs(boatAssets.getAssets().getLayoutY() - y);
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
rotateTo(rotation, sailIn, windDir);
|
rotateTo(rotation, sailIn, windDir);
|
||||||
this.layoutXProperty().setValue(x);
|
this.layoutXProperty().setValue(x);
|
||||||
@@ -85,6 +87,7 @@ public class BoatObject extends Group {
|
|||||||
|
|
||||||
|
|
||||||
private void rotateTo(double heading, boolean sailsIn, double windDir) {
|
private void rotateTo(double heading, boolean sailsIn, double windDir) {
|
||||||
|
rotationProperty.set(heading);
|
||||||
rotation.setAngle(heading);
|
rotation.setAngle(heading);
|
||||||
wake.getTransforms().setAll(new Rotate(heading, new Point3D(0,0,1)));
|
wake.getTransforms().setAll(new Rotate(heading, new Point3D(0,0,1)));
|
||||||
if (sailsIn) {
|
if (sailsIn) {
|
||||||
@@ -132,4 +135,8 @@ public class BoatObject extends Group {
|
|||||||
public void addSelectedBoatListener(SelectedBoatListener sbl) {
|
public void addSelectedBoatListener(SelectedBoatListener sbl) {
|
||||||
selectedBoatListenerListeners.add(sbl);
|
selectedBoatListenerListeners.add(sbl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReadOnlyDoubleWrapper getRotationProperty() {
|
||||||
|
return rotationProperty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ import javafx.geometry.Point3D;
|
|||||||
import javafx.scene.AmbientLight;
|
import javafx.scene.AmbientLight;
|
||||||
import javafx.scene.CacheHint;
|
import javafx.scene.CacheHint;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
|
import javafx.scene.PointLight;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.scene.paint.PhongMaterial;
|
import javafx.scene.paint.PhongMaterial;
|
||||||
import javafx.scene.shape.Circle;
|
import javafx.scene.shape.Circle;
|
||||||
@@ -18,7 +19,7 @@ import javafx.scene.transform.Translate;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory class for creating 3D models of boats.
|
* Factory class for creating 3D models of boatTypes.
|
||||||
*/
|
*/
|
||||||
public class ModelFactory {
|
public class ModelFactory {
|
||||||
|
|
||||||
@@ -51,6 +52,35 @@ public class ModelFactory {
|
|||||||
return bo;
|
return bo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static BoatModel boatCustomiseView(BoatMeshType boatType, Color primaryColour) {
|
||||||
|
Group boatAssets = getUnmodifiedBoatModel(boatType, primaryColour);
|
||||||
|
final Rotate animationRotate = new Rotate(0, new Point3D(0,0,1));
|
||||||
|
boatAssets.getTransforms().addAll(
|
||||||
|
new Scale(8.0, 8.0, 8.0),
|
||||||
|
new Rotate(-70, new Point3D(1,0,0)),
|
||||||
|
new Translate(16,50, 1),
|
||||||
|
animationRotate
|
||||||
|
);
|
||||||
|
|
||||||
|
boatAssets.getTransforms().add(animationRotate);
|
||||||
|
BoatModel bo = new BoatModel(boatAssets, null, boatType);
|
||||||
|
bo.rotateSail(45);
|
||||||
|
|
||||||
|
bo.setAnimation(new AnimationTimer() {
|
||||||
|
double boatAngle = 0;
|
||||||
|
Rotate rotate = animationRotate;
|
||||||
|
@Override
|
||||||
|
public void handle(long now) {
|
||||||
|
boatAngle += 0.5;
|
||||||
|
rotate.setAngle(boatAngle);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
boatAssets.getChildren().addAll(
|
||||||
|
new AmbientLight()
|
||||||
|
);
|
||||||
|
return bo;
|
||||||
|
}
|
||||||
|
|
||||||
public static BoatModel boatRotatingView(BoatMeshType boatType, Color primaryColour) {
|
public static BoatModel boatRotatingView(BoatMeshType boatType, Color primaryColour) {
|
||||||
Group boatAssets = getUnmodifiedBoatModel(boatType, primaryColour);
|
Group boatAssets = getUnmodifiedBoatModel(boatType, primaryColour);
|
||||||
boatAssets.getTransforms().addAll(
|
boatAssets.getTransforms().addAll(
|
||||||
@@ -84,20 +114,29 @@ public class ModelFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Group getUnmodifiedBoatModel(BoatMeshType boatType, Color primaryColour) {
|
private static Group getUnmodifiedBoatModel(BoatMeshType boatType, Color primaryColour) {
|
||||||
|
|
||||||
Group boatAssets = new Group();
|
Group boatAssets = new Group();
|
||||||
MeshView hull = importFile(boatType.hullFile);
|
MeshView hull = importSTL(boatType.hullFile);
|
||||||
hull.setMaterial(new PhongMaterial(primaryColour));
|
hull.setMaterial(new PhongMaterial(primaryColour));
|
||||||
MeshView mast = importFile(boatType.mastFile);
|
MeshView mast = importSTL(boatType.mastFile);
|
||||||
mast.setMaterial(new PhongMaterial(primaryColour));
|
mast.setMaterial(new PhongMaterial(primaryColour));
|
||||||
MeshView sail = importFile(boatType.sailFile);
|
MeshView sail = importSTL(boatType.sailFile);
|
||||||
sail.setMaterial(new PhongMaterial(Color.WHITE));
|
sail.setMaterial(new PhongMaterial(Color.WHITE));
|
||||||
boatAssets.getChildren().addAll(hull, mast, sail);
|
|
||||||
|
if (boatType.jibFile != null) {
|
||||||
|
MeshView jib = importSTL(boatType.jibFile);
|
||||||
|
sail.setMaterial(new PhongMaterial(Color.WHITE));
|
||||||
|
boatAssets.getChildren().addAll(hull, mast, sail, jib);
|
||||||
|
} else {
|
||||||
|
boatAssets.getChildren().addAll(hull, mast, sail);
|
||||||
|
}
|
||||||
|
|
||||||
return boatAssets;
|
return boatAssets;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MeshView importFile(String fileName) {
|
private static MeshView importSTL(String fileName) {
|
||||||
StlMeshImporter importer = new StlMeshImporter();
|
StlMeshImporter importer = new StlMeshImporter();
|
||||||
importer.read(ModelFactory.class.getResource("/meshes/" + fileName));
|
importer.read(ModelFactory.class.getResource("/meshes/boatSTLs/" + fileName));
|
||||||
MeshView importedFile = new MeshView(importer.getImport());
|
MeshView importedFile = new MeshView(importer.getImport());
|
||||||
importedFile.setCache(true);
|
importedFile.setCache(true);
|
||||||
importedFile.setCacheHint(CacheHint.SCALE_AND_ROTATE);
|
importedFile.setCacheHint(CacheHint.SCALE_AND_ROTATE);
|
||||||
|
|||||||
@@ -1,108 +0,0 @@
|
|||||||
package seng302.visualiser;
|
|
||||||
|
|
||||||
import com.interactivemesh.jfx.importer.stl.StlMeshImporter;
|
|
||||||
import javafx.animation.AnimationTimer;
|
|
||||||
import javafx.application.Application;
|
|
||||||
import javafx.geometry.Point3D;
|
|
||||||
import javafx.scene.Camera;
|
|
||||||
import javafx.scene.Group;
|
|
||||||
import javafx.scene.PerspectiveCamera;
|
|
||||||
import javafx.scene.Scene;
|
|
||||||
import javafx.scene.SceneAntialiasing;
|
|
||||||
import javafx.scene.paint.Color;
|
|
||||||
import javafx.scene.paint.PhongMaterial;
|
|
||||||
import javafx.scene.shape.MeshView;
|
|
||||||
import javafx.scene.transform.Rotate;
|
|
||||||
import javafx.scene.transform.Scale;
|
|
||||||
import javafx.scene.transform.Translate;
|
|
||||||
import javafx.stage.Stage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by cir27 on 7/09/17.
|
|
||||||
*/
|
|
||||||
public class test3d extends Application {
|
|
||||||
|
|
||||||
Group root = new Group();
|
|
||||||
Scene scene;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void start(Stage primaryStage) throws Exception {
|
|
||||||
// camera = new PerspectiveCamera();
|
|
||||||
// gameObjects = new Group();
|
|
||||||
// root3D = new Group(camera, gameObjects);
|
|
||||||
scene = new Scene(
|
|
||||||
root, 1000, 1000, true, SceneAntialiasing.BALANCED
|
|
||||||
);
|
|
||||||
gameView3DTest();
|
|
||||||
primaryStage.setScene(scene);
|
|
||||||
primaryStage.show();
|
|
||||||
// scene.setCamera(camera);
|
|
||||||
// primaryStage.setScene(scene);
|
|
||||||
// primaryStage.show();
|
|
||||||
//
|
|
||||||
// StlMeshImporter importer = new StlMeshImporter();
|
|
||||||
// importer.read(test3d.class.getResource("/meshes/dinghy_hull.stl").toString());
|
|
||||||
// MeshView boat = new MeshView(importer.getImport());
|
|
||||||
// boat.setMaterial(new PhongMaterial(Color.GREENYELLOW));
|
|
||||||
//
|
|
||||||
// importer = new StlMeshImporter();
|
|
||||||
// importer.read(getClass().getResource("/meshes/dinghy_mast.stl").toString());
|
|
||||||
// MeshView mast = new MeshView(importer.getImport());
|
|
||||||
// mast.setMaterial(new PhongMaterial(Color.GREENYELLOW));
|
|
||||||
//
|
|
||||||
// importer = new StlMeshImporter();
|
|
||||||
// importer.read(getClass().getResource("/meshes/dinghy_sail.stl").toString());
|
|
||||||
// MeshView sail = new MeshView(importer.getImport());
|
|
||||||
// sail.setMaterial(new PhongMaterial(Color.LIGHTGREY));
|
|
||||||
//
|
|
||||||
// gameObjects.getChildren().addAll(boat, mast, sail);
|
|
||||||
//
|
|
||||||
// gameObjects.getTransforms().add(new Scale(25, 25,25));
|
|
||||||
// gameObjects.getTransforms().add(new Translate(15, 20,0));
|
|
||||||
// gameObjects.getTransforms().addAll(
|
|
||||||
// new Rotate(90, new Point3D(0,0,1)),
|
|
||||||
// new Rotate(90, new Point3D(0, 1, 0))
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
//// PointLight light = new PointLight();
|
|
||||||
//// light.setLightOn(true);
|
|
||||||
//// light.getTransforms().add(new Translate(15, 20, 0));
|
|
||||||
////
|
|
||||||
//// PointLight light2 = new PointLight();
|
|
||||||
//// light2.setLightOn(true);
|
|
||||||
//// light2.getTransforms().add(new Translate(30, 40, 0));
|
|
||||||
//
|
|
||||||
//// root3D.getChildren().addAll(light);
|
|
||||||
//
|
|
||||||
// scene.setOnKeyPressed(event -> {
|
|
||||||
// switch (event.getCode()) {
|
|
||||||
// case UP:
|
|
||||||
// gameObjects.getTransforms().add(new Rotate(5, new Point3D(0,0,1)));
|
|
||||||
// break;
|
|
||||||
// case DOWN:
|
|
||||||
// gameObjects.getTransforms().add(new Rotate(-5, new Point3D(0,0,1)));
|
|
||||||
// break;
|
|
||||||
// case LEFT:
|
|
||||||
// gameObjects.getTransforms().add(new Rotate(-5, new Point3D(0,1,0)));
|
|
||||||
// break;
|
|
||||||
// case RIGHT:
|
|
||||||
// gameObjects.getTransforms().add(new Rotate(5, new Point3D(0,1,0)));
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// AnimationTimer animationTimer = new AnimationTimer() {
|
|
||||||
// @Override
|
|
||||||
// public void handle(long now) {
|
|
||||||
// sail.getTransforms().add(new Rotate(0.5, 0, -1.36653, 0, new Point3D(0, 0, 1)));
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
//// animationTimer.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void gameView3DTest() {
|
|
||||||
GameView3D gameView3D = new GameView3D();
|
|
||||||
root.getChildren().add(gameView3D.getAssets());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -44,8 +44,18 @@
|
|||||||
-fx-border-color: -fx-decorator-color;
|
-fx-border-color: -fx-decorator-color;
|
||||||
-fx-border-width: 0 4 4 4;
|
-fx-border-width: 0 4 4 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.jfx-decorator-button {
|
||||||
|
-fx-focus-traversable: false; /* so decorator button will not be focused */
|
||||||
|
}
|
||||||
|
|
||||||
/********* customised scroll bar for scroll pane ***********/
|
/********* customised scroll bar for scroll pane ***********/
|
||||||
|
|
||||||
|
.scroll-pane {
|
||||||
|
-fx-focus-traversable: false;
|
||||||
|
-fx-border-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* The main scrollbar **track** CSS class */
|
/* The main scrollbar **track** CSS class */
|
||||||
.scroll-bar:horizontal .track,
|
.scroll-bar:horizontal .track,
|
||||||
.scroll-bar:vertical .track {
|
.scroll-bar:vertical .track {
|
||||||
@@ -100,3 +110,15 @@
|
|||||||
.slider .track {
|
.slider .track {
|
||||||
-fx-background-color: -fx-pp-dark-text-color;
|
-fx-background-color: -fx-pp-dark-text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.jfx-snackbar-content {
|
||||||
|
-fx-background-color: -fx-pp-front-color;
|
||||||
|
-fx-padding: 0 5 0 5;
|
||||||
|
-fx-spacing: 0 5 0 5;
|
||||||
|
-fx-font-size: 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfx-snackbar-toast {
|
||||||
|
-fx-text-fill: -fx-pp-theme-color;
|
||||||
|
-fx-font-size: 15;
|
||||||
|
}
|
||||||
@@ -48,6 +48,7 @@ GridPane .timer * {
|
|||||||
-fx-text-fill: -fx-pp-theme-color;
|
-fx-text-fill: -fx-pp-theme-color;
|
||||||
-fx-font-size: 13px;
|
-fx-font-size: 13px;
|
||||||
-fx-pref-height: 35px;
|
-fx-pref-height: 35px;
|
||||||
|
-fx-focus-traversable: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#chatSend:hover {
|
#chatSend:hover {
|
||||||
|
|||||||
@@ -38,30 +38,30 @@
|
|||||||
-fx-font-size: 23px;
|
-fx-font-size: 23px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#connectButton, #roomConnectButton {
|
#connectButton {
|
||||||
-fx-background-color: -fx-pp-light-text-color; /* inverted */
|
-fx-background-color: -fx-pp-light-text-color; /* inverted */
|
||||||
-fx-text-fill: -fx-pp-theme-color; /* inverted */
|
-fx-text-fill: -fx-pp-theme-color; /* inverted */
|
||||||
-fx-font-size: 20px;
|
-fx-font-size: 20px;
|
||||||
-fx-pref-height: 45px;
|
-fx-pref-height: 65px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#connectButton:hover, #roomConnectButton:hover {
|
#connectButton:hover {
|
||||||
-fx-font-size: 23px;
|
-fx-font-size: 23px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#connectLabel, #connectLabel1, #serverPortNumber, #roomNumber, #serverHostName {
|
#connectLabel, #serverPortNumber, #serverHostName {
|
||||||
-fx-text-fill: -fx-pp-light-text-color;
|
-fx-text-fill: -fx-pp-light-text-color;
|
||||||
-fx-font-size: 18px;
|
-fx-font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#serverHostName, #serverPortNumber, #roomNumber {
|
#serverHostName, #serverPortNumber {
|
||||||
-jfx-focus-color: -fx-pp-light-text-color;
|
-jfx-focus-color: -fx-pp-light-text-color;
|
||||||
-jfx-unfocus-color: -fx-pp-light-text-color;
|
-jfx-unfocus-color: -fx-pp-light-text-color;
|
||||||
-fx-prompt-text-fill: -fx-pp-light-text-color;
|
-fx-prompt-text-fill: -fx-pp-light-text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#serverHostName .error-label, #serverPortNumber .error-label, #roomNumber .error-label {
|
#serverHostName .error-label, #serverPortNumber .error-label {
|
||||||
-fx-font-size: 12px;
|
-fx-font-size: 12px;
|
||||||
-fx-text-fill: lightblue;
|
-fx-text-fill: lightblue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
-fx-font-size: 20px;
|
-fx-font-size: 20px;
|
||||||
-fx-text-fill: -fx-pp-light-text-color;
|
-fx-text-fill: -fx-pp-light-text-color;
|
||||||
-fx-background-color: -fx-pp-theme-color;
|
-fx-background-color: -fx-pp-theme-color;
|
||||||
|
-fx-focus-traversable: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jfx-rippler {
|
.jfx-rippler {
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#keyBindingDialogHeader {
|
||||||
|
-fx-font-size: 27px;
|
||||||
|
-fx-text-fill: -fx-pp-dark-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
#closeLabel {
|
||||||
|
-fx-font-size: 30;
|
||||||
|
-fx-text-fill: -fx-pp-dark-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
#closeLabel:hover {
|
||||||
|
-fx-text-fill: red;
|
||||||
|
-fx-font-size: 33px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sectionLabel {
|
||||||
|
-fx-text-fill: -fx-pp-dark-text-color;
|
||||||
|
-fx-font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
JFXButton {
|
||||||
|
-fx-background-color: -fx-pp-light-text-color;
|
||||||
|
-fx-text-fill: -fx-pp-theme-color;
|
||||||
|
-fx-font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
-fx-font-size: 15px;
|
||||||
|
-fx-text-fill: -fx-pp-theme-color;
|
||||||
|
-fx-effect: -fx-pp-dropshadow-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
JFXToggleButton {
|
||||||
|
-jfx-toggle-color: -fx-pp-theme-color;
|
||||||
|
-fx-text-fill: -fx-pp-theme-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
#resetBtn {
|
||||||
|
-fx-background-color: -fx-pp-theme-color;
|
||||||
|
-fx-text-fill: -fx-pp-front-color;
|
||||||
|
-fx-effect: -fx-pp-dropshadow-light;
|
||||||
|
-fx-font-size: 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
#resetBtn:hover {
|
||||||
|
-fx-font-size: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfx-snackbar-content {
|
||||||
|
-fx-background-color: #323232;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfx-snackbar-toast {
|
||||||
|
-fx-text-fill: WHITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfx-snackbar-action {
|
||||||
|
-fx-text-fill: #ff4081;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#headerLabel {
|
||||||
|
-fx-font-size: 20px;
|
||||||
|
-fx-text-fill: -fx-pp-dark-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
#closeLabel {
|
||||||
|
-fx-font-size: 22px;
|
||||||
|
-fx-text-fill: -fx-pp-dark-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
#closeLabel:hover {
|
||||||
|
-fx-font-size: 24px;
|
||||||
|
-fx-text-fill: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#contentLabel {
|
||||||
|
-fx-font-size: 22px;
|
||||||
|
-fx-text-fill: -fx-pp-dark-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
#optionButton {
|
||||||
|
-fx-background-color: -fx-pp-theme-color;
|
||||||
|
-fx-text-fill: -fx-pp-light-text-color;
|
||||||
|
-fx-font-size: 18px;
|
||||||
|
-fx-effect: -fx-pp-dropshadow-light;
|
||||||
|
-fx-max-height: 55;
|
||||||
|
-fx-focus-traversable: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#optionButton:hover {
|
||||||
|
-fx-font-size: 20px !important;
|
||||||
|
-fx-background-color: -fx-pp-light-theme-color;
|
||||||
|
}
|
||||||
@@ -45,3 +45,13 @@
|
|||||||
.maxPlayers {
|
.maxPlayers {
|
||||||
-fx-font-size: 13px;
|
-fx-font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#closeLabel {
|
||||||
|
-fx-font-size: 30;
|
||||||
|
-fx-text-fill: -fx-pp-dark-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
#closeLabel:hover {
|
||||||
|
-fx-text-fill: red;
|
||||||
|
-fx-font-size: 33px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/* a separate file to dynamically change snackbar's color */
|
||||||
|
.jfx-snackbar-toast {
|
||||||
|
-fx-text-fill: red !important;
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -5,8 +5,8 @@
|
|||||||
<author>Blender User</author>
|
<author>Blender User</author>
|
||||||
<authoring_tool>Blender 2.78.0 commit date:2016-09-26, commit time:12:42, hash:4bb1e22</authoring_tool>
|
<authoring_tool>Blender 2.78.0 commit date:2016-09-26, commit time:12:42, hash:4bb1e22</authoring_tool>
|
||||||
</contributor>
|
</contributor>
|
||||||
<created>2017-09-19T15:45:46</created>
|
<created>2017-09-26T19:13:35</created>
|
||||||
<modified>2017-09-19T15:45:46</modified>
|
<modified>2017-09-26T19:13:35</modified>
|
||||||
<unit name="meter" meter="1"/>
|
<unit name="meter" meter="1"/>
|
||||||
<up_axis>Z_UP</up_axis>
|
<up_axis>Z_UP</up_axis>
|
||||||
</asset>
|
</asset>
|
||||||
@@ -23,10 +23,10 @@
|
|||||||
<color sid="ambient">0 0 0 1</color>
|
<color sid="ambient">0 0 0 1</color>
|
||||||
</ambient>
|
</ambient>
|
||||||
<diffuse>
|
<diffuse>
|
||||||
<color sid="diffuse">0.004555753 0.0885511 0.003947978 1</color>
|
<color sid="diffuse">0.01630632 0.52949 0.0134405 1</color>
|
||||||
</diffuse>
|
</diffuse>
|
||||||
<specular>
|
<specular>
|
||||||
<color sid="specular">0.25 0.25 0.25 1</color>
|
<color sid="specular">0.125 0.125 0.125 1</color>
|
||||||
</specular>
|
</specular>
|
||||||
<shininess>
|
<shininess>
|
||||||
<float sid="shininess">50</float>
|
<float sid="shininess">50</float>
|
||||||
@@ -49,10 +49,10 @@
|
|||||||
<color sid="ambient">0 0 0 1</color>
|
<color sid="ambient">0 0 0 1</color>
|
||||||
</ambient>
|
</ambient>
|
||||||
<diffuse>
|
<diffuse>
|
||||||
<color sid="diffuse">0.64 0.1458963 0.001825521 1</color>
|
<color sid="diffuse">0.64 0.5334254 0 1</color>
|
||||||
</diffuse>
|
</diffuse>
|
||||||
<specular>
|
<specular>
|
||||||
<color sid="specular">0.25 0.25 0.25 1</color>
|
<color sid="specular">0.125 0.125 0.125 1</color>
|
||||||
</specular>
|
</specular>
|
||||||
<shininess>
|
<shininess>
|
||||||
<float sid="shininess">50</float>
|
<float sid="shininess">50</float>
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
</technique_common>
|
</technique_common>
|
||||||
</source>
|
</source>
|
||||||
<source id="Icosphere_001-mesh-normals">
|
<source id="Icosphere_001-mesh-normals">
|
||||||
<float_array id="Icosphere_001-mesh-normals-array" count="240">0.7002241 -0.2680317 -0.6616988 0.9049891 -0.2680316 -0.3303847 0.02474653 -0.9435215 -0.330386 -0.8896973 -0.3150947 -0.3303849 -0.5746018 0.7487837 -0.3303875 0.5345759 0.7778646 -0.3303867 0.4089462 -0.6284253 0.6616985 -0.4712997 -0.5831224 0.6616985 -0.7002241 0.2680317 0.6616988 0.03853034 0.7487788 0.6616991 0.7240421 0.1947362 0.6616954 0.4911195 0.356821 0.7946575 0.4089463 0.6284252 0.6616985 -0.1875942 0.5773453 0.7946577 -0.4712997 0.5831224 0.6616985 -0.6070605 0 0.7946557 -0.7002241 -0.2680318 0.6616988 -0.1875942 -0.5773453 0.7946577 0.03853034 -0.7487788 0.6616991 0.4911194 -0.356821 0.7946576 0.7240421 -0.1947363 0.6616954 0.8896973 0.3150946 0.3303849 0.7946556 0.5773479 0.1875951 0.5746018 0.7487836 0.3303875 -0.02474653 0.9435214 0.3303861 -0.3035309 0.9341714 0.1875976 -0.5345759 0.7778646 0.3303867 -0.9049891 0.2680316 0.3303846 -0.9822458 0 0.1875985 -0.9049891 -0.2680316 0.3303846 -0.5345759 -0.7778646 0.3303867 -0.3035309 -0.9341714 0.1875975 -0.02474653 -0.9435214 0.3303861 0.5746018 -0.7487836 0.3303875 0.7946556 -0.5773479 0.1875951 0.8896973 -0.3150946 0.3303849 0.3035309 0.9341714 -0.1875975 0.02474653 0.9435215 -0.330386 -0.7946556 0.5773479 -0.1875951 -0.8896973 0.3150945 -0.3303849 -0.7946556 -0.5773479 -0.1875951 -0.5746018 -0.7487836 -0.3303875 0.3035309 -0.9341714 -0.1875976 0.5345759 -0.7778645 -0.3303867 0.9822458 0 -0.1875985 0.9049891 0.2680316 -0.3303847 0.4712997 0.5831224 -0.6616986 0.1875942 0.5773453 -0.7946577 -0.0385304 0.7487788 -0.6616991 -0.4089462 0.6284252 -0.6616984 -0.4911194 0.356821 -0.7946576 -0.7240421 0.1947362 -0.6616954 -0.7240421 -0.1947362 -0.6616954 -0.4911195 -0.356821 -0.7946575 -0.4089462 -0.6284252 -0.6616984 0.7002241 0.2680318 -0.6616988 0.6070605 0 -0.7946556 -0.0385304 -0.7487788 -0.6616991 0.1875942 -0.5773453 -0.7946577 0.4712997 -0.5831224 -0.6616986 0.1023808 -0.3150898 -0.9435235 -0.2680341 -0.1947365 -0.9435229 -0.2680341 0.1947365 -0.9435229 0.1023808 0.3150898 -0.9435235 0.802609 -0.5831265 -0.1256273 -0.306569 -0.9435216 -0.1256289 -0.9920774 0 -0.1256284 -0.306569 0.9435216 -0.1256289 0.802609 0.5831265 -0.1256273 0.2680341 0.1947365 0.9435229 -0.1023808 0.3150899 0.9435235 -0.3313045 0 0.943524 -0.1023808 -0.3150898 0.9435235 0.2680341 -0.1947365 0.9435229 0.306569 0.9435216 0.1256289 -0.802609 0.5831265 0.1256274 -0.802609 -0.5831265 0.1256274 0.306569 -0.9435216 0.1256289 0.9920774 0 0.1256284 0.3313045 0 -0.943524</float_array>
|
<float_array id="Icosphere_001-mesh-normals-array" count="240">0.7002241 -0.2680317 -0.6616988 0.9049891 -0.2680316 -0.3303847 0.02474653 -0.9435215 -0.330386 -0.8896973 -0.3150947 -0.3303849 -0.5746018 0.7487837 -0.3303875 0.5345759 0.7778646 -0.3303867 0.4089462 -0.6284252 0.6616985 -0.4712997 -0.5831224 0.6616985 -0.7002241 0.2680317 0.6616988 0.03853034 0.7487788 0.6616992 0.7240421 0.1947362 0.6616954 0.4911194 0.356821 0.7946576 0.4089462 0.6284253 0.6616984 -0.1875943 0.5773454 0.7946577 -0.4712997 0.5831224 0.6616985 -0.6070605 0 0.7946557 -0.7002241 -0.2680318 0.6616988 -0.1875943 -0.5773454 0.7946577 0.03853034 -0.7487788 0.6616992 0.4911193 -0.356821 0.7946577 0.7240421 -0.1947363 0.6616954 0.8896973 0.3150946 0.3303849 0.7946556 0.5773479 0.1875951 0.5746018 0.7487836 0.3303875 -0.02474653 0.9435214 0.3303861 -0.3035309 0.9341714 0.1875976 -0.5345759 0.7778646 0.3303867 -0.9049891 0.2680316 0.3303846 -0.9822458 0 0.1875985 -0.9049891 -0.2680316 0.3303846 -0.5345759 -0.7778646 0.3303867 -0.3035309 -0.9341714 0.1875975 -0.02474653 -0.9435214 0.3303861 0.5746018 -0.7487836 0.3303875 0.7946556 -0.5773479 0.1875951 0.8896973 -0.3150946 0.3303849 0.3035309 0.9341714 -0.1875975 0.02474653 0.9435215 -0.330386 -0.7946556 0.5773479 -0.1875951 -0.8896973 0.3150945 -0.3303849 -0.7946556 -0.5773479 -0.1875951 -0.5746018 -0.7487836 -0.3303875 0.3035309 -0.9341714 -0.1875976 0.5345759 -0.7778645 -0.3303867 0.9822458 0 -0.1875985 0.9049891 0.2680316 -0.3303847 0.4712997 0.5831224 -0.6616986 0.1875943 0.5773454 -0.7946577 -0.0385304 0.7487789 -0.6616991 -0.4089462 0.6284252 -0.6616984 -0.4911193 0.356821 -0.7946577 -0.7240421 0.1947362 -0.6616954 -0.7240421 -0.1947362 -0.6616954 -0.4911194 -0.356821 -0.7946576 -0.4089462 -0.6284252 -0.6616984 0.7002241 0.2680318 -0.6616988 0.6070605 0 -0.7946556 -0.0385304 -0.7487789 -0.6616991 0.1875943 -0.5773454 -0.7946577 0.4712997 -0.5831224 -0.6616986 0.1023808 -0.3150898 -0.9435235 -0.2680341 -0.1947365 -0.9435229 -0.2680341 0.1947365 -0.9435229 0.1023808 0.3150898 -0.9435235 0.802609 -0.5831265 -0.1256273 -0.306569 -0.9435216 -0.1256289 -0.9920774 0 -0.1256284 -0.306569 0.9435216 -0.1256289 0.802609 0.5831265 -0.1256273 0.2680341 0.1947365 0.9435229 -0.1023808 0.3150898 0.9435235 -0.3313045 0 0.943524 -0.1023808 -0.3150899 0.9435235 0.2680341 -0.1947365 0.9435229 0.306569 0.9435216 0.1256289 -0.802609 0.5831265 0.1256274 -0.802609 -0.5831265 0.1256274 0.306569 -0.9435216 0.1256289 0.9920774 0 0.1256284 0.3313045 0 -0.943524</float_array>
|
||||||
<technique_common>
|
<technique_common>
|
||||||
<accessor source="#Icosphere_001-mesh-normals-array" count="80" stride="3">
|
<accessor source="#Icosphere_001-mesh-normals-array" count="80" stride="3">
|
||||||
<param name="X" type="float"/>
|
<param name="X" type="float"/>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
</BoatShapes>
|
</BoatShapes>
|
||||||
<Boats>
|
<Boats>
|
||||||
<#list boats as boat>
|
<#list boats as boat>
|
||||||
<Boat Type="Yacht" SourceID="${boat.sourceId}" ShapeID="4" HullNum="${boat.hullID}" StoweName="${boat.shortName}" ShortName="${boat.shortName}"
|
<Boat Type="${boat.boatType}" SourceID="${boat.sourceId}" ShapeID="4" HullNum="${boat.hullID}" StoweName="${boat.shortName}" ShortName="${boat.shortName}"
|
||||||
BoatName="${boat.boatName}" Country="${boat.country}" Color="${boat.boatColor}">
|
BoatName="${boat.boatName}" Country="${boat.country}" Color="${boat.boatColor}">
|
||||||
<GPSposition Z="0" Y="3.7" X="0" />
|
<GPSposition Z="0" Y="3.7" X="0" />
|
||||||
<MastTop Z="0" Y="6.2" X="0" />
|
<MastTop Z="0" Y="6.2" X="0" />
|
||||||
|
|||||||
@@ -52,19 +52,10 @@
|
|||||||
<Insets left="35.0" top="-15.0" />
|
<Insets left="35.0" top="-15.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</Label>
|
</Label>
|
||||||
<Label fx:id="roomLabel" text="Room: 2145" GridPane.columnIndex="2" GridPane.halignment="RIGHT" GridPane.valignment="CENTER">
|
|
||||||
<font>
|
|
||||||
<Font size="31.0" />
|
|
||||||
</font>
|
|
||||||
<GridPane.margin>
|
|
||||||
<Insets right="20.0" top="10.0" />
|
|
||||||
</GridPane.margin>
|
|
||||||
</Label>
|
|
||||||
</children>
|
</children>
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="732.0" minWidth="10.0" prefWidth="507.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="10000.0" minWidth="10.0" prefWidth="155.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
<ColumnConstraints halignment="RIGHT" hgrow="NEVER" maxWidth="445.0" minWidth="10.0" prefWidth="238.0" />
|
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="50.0" prefHeight="74.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="50.0" prefHeight="74.0" vgrow="SOMETIMES" />
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
<?import javafx.scene.image.Image?>
|
<?import javafx.scene.image.Image?>
|
||||||
<?import javafx.scene.image.ImageView?>
|
<?import javafx.scene.image.ImageView?>
|
||||||
<?import javafx.scene.layout.AnchorPane?>
|
|
||||||
<?import javafx.scene.layout.ColumnConstraints?>
|
<?import javafx.scene.layout.ColumnConstraints?>
|
||||||
<?import javafx.scene.layout.GridPane?>
|
<?import javafx.scene.layout.GridPane?>
|
||||||
<?import javafx.scene.layout.Pane?>
|
<?import javafx.scene.layout.Pane?>
|
||||||
@@ -24,285 +23,277 @@
|
|||||||
<?import javafx.scene.layout.StackPane?>
|
<?import javafx.scene.layout.StackPane?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
<AnchorPane fx:id="rvAnchorPane" maxHeight="1.7976931348623157E308"
|
<StackPane fx:id="contentStackPane" maxHeight="1.7976931348623157E308"
|
||||||
maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0"
|
maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0"
|
||||||
prefWidth="1200.0" style="-fx-background-color: lightblue;" xmlns="http://javafx.com/javafx/8"
|
prefWidth="1200.0" style="-fx-background-color: skyblue;" xmlns="http://javafx.com/javafx/8.0.111"
|
||||||
xmlns:fx="http://javafx.com/fxml/1"
|
xmlns:fx="http://javafx.com/fxml/1"
|
||||||
fx:controller="seng302.visualiser.controllers.RaceViewController">
|
fx:controller="seng302.visualiser.controllers.RaceViewController">
|
||||||
<children>
|
<children>
|
||||||
<StackPane fx:id="contentAnchorPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="800.0" prefWidth="1200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
|
||||||
<children>
|
prefHeight="800.0" prefWidth="1200.0">
|
||||||
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
|
<columnConstraints>
|
||||||
prefHeight="800.0" prefWidth="1200.0">
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="250.0" minWidth="250.0"
|
||||||
<columnConstraints>
|
prefWidth="250.0"/>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="250.0" minWidth="250.0"
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308"/>
|
||||||
prefWidth="250.0"/>
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="400.0"
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308"/>
|
prefWidth="400.0"/>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="400.0"
|
</columnConstraints>
|
||||||
prefWidth="400.0"/>
|
<rowConstraints>
|
||||||
</columnConstraints>
|
<RowConstraints maxHeight="70.0" minHeight="70.0" prefHeight="70.0"
|
||||||
<rowConstraints>
|
vgrow="SOMETIMES"/>
|
||||||
<RowConstraints maxHeight="70.0" minHeight="70.0" prefHeight="70.0"
|
<RowConstraints maxHeight="1.7976931348623157E308" vgrow="SOMETIMES"/>
|
||||||
vgrow="SOMETIMES"/>
|
<RowConstraints maxHeight="250.0" minHeight="250.0" prefHeight="250.0"
|
||||||
<RowConstraints maxHeight="1.7976931348623157E308" vgrow="SOMETIMES"/>
|
valignment="BOTTOM" vgrow="SOMETIMES"/>
|
||||||
<RowConstraints maxHeight="250.0" minHeight="250.0" prefHeight="250.0"
|
</rowConstraints>
|
||||||
valignment="BOTTOM" vgrow="SOMETIMES"/>
|
<children>
|
||||||
</rowConstraints>
|
<GridPane id="timerGrid" fx:id="timerGrid" prefWidth="192.0" styleClass="timer">
|
||||||
<children>
|
<columnConstraints>
|
||||||
<GridPane id="timerGrid" fx:id="timerGrid" prefWidth="192.0"
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="50.0" minWidth="50.0"
|
||||||
styleClass="timer">
|
prefWidth="50.0"/>
|
||||||
<columnConstraints>
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="135.0" minWidth="135.0"
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="50.0" minWidth="50.0"
|
prefWidth="135.0"/>
|
||||||
prefWidth="50.0"/>
|
</columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="135.0"
|
<rowConstraints>
|
||||||
minWidth="135.0" prefWidth="135.0"/>
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||||
</columnConstraints>
|
</rowConstraints>
|
||||||
<rowConstraints>
|
<opaqueInsets>
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0"
|
<Insets/>
|
||||||
vgrow="SOMETIMES"/>
|
</opaqueInsets>
|
||||||
</rowConstraints>
|
<GridPane.margin>
|
||||||
<opaqueInsets>
|
<Insets left="10.0" right="200.0" top="10.0"/>
|
||||||
<Insets/>
|
</GridPane.margin>
|
||||||
</opaqueInsets>
|
<children>
|
||||||
<GridPane.margin>
|
<ImageView fitHeight="40.0" fitWidth="40.0" pickOnBounds="true"
|
||||||
<Insets left="10.0" right="200.0" top="10.0"/>
|
preserveRatio="true" GridPane.halignment="CENTER"
|
||||||
</GridPane.margin>
|
GridPane.valignment="CENTER">
|
||||||
<children>
|
<image>
|
||||||
<ImageView fitHeight="40.0" fitWidth="40.0" pickOnBounds="true"
|
<Image url="@../images/timer.png"/>
|
||||||
preserveRatio="true" GridPane.halignment="CENTER"
|
</image>
|
||||||
GridPane.valignment="CENTER">
|
<GridPane.margin>
|
||||||
<image>
|
<Insets/>
|
||||||
<Image url="@../images/timer.png"/>
|
</GridPane.margin>
|
||||||
</image>
|
</ImageView>
|
||||||
<GridPane.margin>
|
<Label fx:id="timerLabel" text="00:03:34" GridPane.columnIndex="1"
|
||||||
<Insets/>
|
GridPane.halignment="CENTER" GridPane.valignment="CENTER">
|
||||||
</GridPane.margin>
|
<font>
|
||||||
</ImageView>
|
<Font size="21.0"/>
|
||||||
<Label fx:id="timerLabel" text="00:03:34" GridPane.columnIndex="1"
|
</font>
|
||||||
GridPane.halignment="CENTER" GridPane.valignment="CENTER">
|
<GridPane.margin>
|
||||||
<font>
|
<Insets/>
|
||||||
<Font size="21.0"/>
|
</GridPane.margin>
|
||||||
</font>
|
</Label>
|
||||||
<GridPane.margin>
|
</children>
|
||||||
<Insets/>
|
</GridPane>
|
||||||
</GridPane.margin>
|
<GridPane GridPane.columnIndex="2">
|
||||||
</Label>
|
<columnConstraints>
|
||||||
</children>
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
|
||||||
</GridPane>
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
|
||||||
<GridPane GridPane.columnIndex="2">
|
</columnConstraints>
|
||||||
<columnConstraints>
|
<rowConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||||
prefWidth="100.0"/>
|
</rowConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
|
</GridPane>
|
||||||
prefWidth="100.0"/>
|
<GridPane fx:id="chatGridPane" GridPane.columnIndex="2" GridPane.rowIndex="2">
|
||||||
</columnConstraints>
|
<columnConstraints>
|
||||||
<rowConstraints>
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="390.0" minWidth="390.0"
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0"
|
prefWidth="390.0"/>
|
||||||
vgrow="SOMETIMES"/>
|
</columnConstraints>
|
||||||
</rowConstraints>
|
<rowConstraints>
|
||||||
</GridPane>
|
<RowConstraints maxHeight="1.7976931348623157E308" vgrow="SOMETIMES"/>
|
||||||
<GridPane fx:id="chatGridPane" GridPane.columnIndex="2"
|
<RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="60.0"
|
||||||
GridPane.rowIndex="2">
|
vgrow="SOMETIMES"/>
|
||||||
<columnConstraints>
|
</rowConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="390.0"
|
<children>
|
||||||
minWidth="390.0" prefWidth="390.0"/>
|
<Pane fx:id="chatHistoryHolder" prefHeight="200.0" prefWidth="200.0"
|
||||||
</columnConstraints>
|
GridPane.hgrow="ALWAYS" GridPane.valignment="BOTTOM"
|
||||||
<rowConstraints>
|
GridPane.vgrow="ALWAYS">
|
||||||
<RowConstraints maxHeight="1.7976931348623157E308"
|
<GridPane.margin>
|
||||||
vgrow="SOMETIMES"/>
|
<Insets/>
|
||||||
<RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="60.0"
|
</GridPane.margin>
|
||||||
vgrow="SOMETIMES"/>
|
<padding>
|
||||||
</rowConstraints>
|
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
|
||||||
<children>
|
</padding>
|
||||||
<Pane fx:id="chatHistoryHolder" prefHeight="200.0" prefWidth="200.0"
|
</Pane>
|
||||||
GridPane.hgrow="ALWAYS" GridPane.valignment="BOTTOM"
|
<GridPane fx:id="chatInputHolder" GridPane.rowIndex="1">
|
||||||
GridPane.vgrow="ALWAYS">
|
<columnConstraints>
|
||||||
<GridPane.margin>
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
|
||||||
<Insets/>
|
prefWidth="100.0"/>
|
||||||
</GridPane.margin>
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity"
|
||||||
<padding>
|
minWidth="90.0" prefWidth="90.0"/>
|
||||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
|
</columnConstraints>
|
||||||
</padding>
|
<rowConstraints>
|
||||||
</Pane>
|
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0"
|
||||||
<GridPane fx:id="chatInputHolder" GridPane.rowIndex="1">
|
valignment="CENTER" vgrow="SOMETIMES"/>
|
||||||
<columnConstraints>
|
</rowConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
|
<children>
|
||||||
prefWidth="100.0"/>
|
<JFXButton fx:id="chatSend" alignment="CENTER" buttonType="RAISED"
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity"
|
focusTraversable="false" maxHeight="-Infinity"
|
||||||
minWidth="90.0" prefWidth="90.0"/>
|
maxWidth="1.7976931348623157E308" minHeight="-Infinity"
|
||||||
</columnConstraints>
|
minWidth="-Infinity" prefHeight="35.0" text="SEND"
|
||||||
<rowConstraints>
|
GridPane.columnIndex="1">
|
||||||
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
<GridPane.margin>
|
||||||
prefHeight="50.0" valignment="CENTER" vgrow="SOMETIMES"/>
|
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
|
||||||
</rowConstraints>
|
</GridPane.margin>
|
||||||
<children>
|
</JFXButton>
|
||||||
<JFXButton fx:id="chatSend" alignment="CENTER"
|
<JFXTextField fx:id="chatInput" focusTraversable="false"
|
||||||
buttonType="RAISED" maxHeight="-Infinity"
|
maxHeight="35.0" minHeight="-Infinity" prefHeight="35.0">
|
||||||
maxWidth="1.7976931348623157E308" minHeight="-Infinity"
|
<GridPane.margin>
|
||||||
minWidth="-Infinity" prefHeight="35.0" text="SEND"
|
<Insets bottom="10.0" left="20.0" right="10.0"/>
|
||||||
GridPane.columnIndex="1">
|
</GridPane.margin>
|
||||||
<GridPane.margin>
|
<padding>
|
||||||
<Insets bottom="10.0" left="10.0" right="10.0"
|
<Insets right="15.0"/>
|
||||||
top="10.0"/>
|
</padding>
|
||||||
</GridPane.margin>
|
</JFXTextField>
|
||||||
</JFXButton>
|
</children>
|
||||||
<JFXTextField fx:id="chatInput" maxHeight="35.0"
|
<GridPane.margin>
|
||||||
minHeight="-Infinity" prefHeight="35.0">
|
<Insets top="10.0"/>
|
||||||
<GridPane.margin>
|
</GridPane.margin>
|
||||||
<Insets bottom="10.0" left="20.0" right="10.0"/>
|
</GridPane>
|
||||||
</GridPane.margin>
|
</children>
|
||||||
<padding>
|
<GridPane.margin>
|
||||||
<Insets right="15.0"/>
|
<Insets bottom="10.0" right="10.0"/>
|
||||||
</padding>
|
</GridPane.margin>
|
||||||
</JFXTextField>
|
</GridPane>
|
||||||
</children>
|
<GridPane fx:id="windGridPane" maxHeight="-Infinity" maxWidth="-Infinity"
|
||||||
<GridPane.margin>
|
prefHeight="150.0" prefWidth="240.0" GridPane.halignment="CENTER"
|
||||||
<Insets top="10.0"/>
|
GridPane.rowIndex="2" GridPane.valignment="BOTTOM">
|
||||||
</GridPane.margin>
|
<columnConstraints>
|
||||||
</GridPane>
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="110.0" minWidth="110.0"
|
||||||
</children>
|
prefWidth="110.0"/>
|
||||||
<GridPane.margin>
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="132.0" minWidth="10.0"
|
||||||
<Insets bottom="10.0" right="10.0"/>
|
prefWidth="132.0"/>
|
||||||
</GridPane.margin>
|
</columnConstraints>
|
||||||
</GridPane>
|
<rowConstraints>
|
||||||
<GridPane fx:id="windGridPane" maxHeight="-Infinity" maxWidth="-Infinity"
|
<RowConstraints maxHeight="120.0" minHeight="120.0" prefHeight="120.0"
|
||||||
prefHeight="150.0" prefWidth="240.0" GridPane.halignment="CENTER"
|
vgrow="SOMETIMES"/>
|
||||||
GridPane.rowIndex="2" GridPane.valignment="BOTTOM">
|
<RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0"
|
||||||
<columnConstraints>
|
vgrow="SOMETIMES"/>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="110.0"
|
</rowConstraints>
|
||||||
minWidth="110.0" prefWidth="110.0"/>
|
<children>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="132.0" minWidth="10.0"
|
<Label fx:id="positionLabel" text="Position:" GridPane.columnIndex="1"
|
||||||
prefWidth="132.0"/>
|
GridPane.halignment="LEFT" GridPane.rowSpan="2" GridPane.valignment="TOP">
|
||||||
</columnConstraints>
|
<padding>
|
||||||
<rowConstraints>
|
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/>
|
||||||
<RowConstraints maxHeight="120.0" minHeight="120.0"
|
</padding>
|
||||||
prefHeight="120.0" vgrow="SOMETIMES"/>
|
</Label>
|
||||||
<RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0"
|
<Label fx:id="boatSpeedLabel" text="Boat Speed:" GridPane.columnIndex="1"
|
||||||
vgrow="SOMETIMES"/>
|
GridPane.halignment="LEFT" GridPane.rowSpan="2"
|
||||||
</rowConstraints>
|
GridPane.valignment="CENTER">
|
||||||
<children>
|
<opaqueInsets>
|
||||||
<Label fx:id="positionLabel" text="Position:"
|
<Insets/>
|
||||||
GridPane.columnIndex="1" GridPane.halignment="LEFT"
|
</opaqueInsets>
|
||||||
GridPane.rowSpan="2" GridPane.valignment="TOP">
|
<padding>
|
||||||
<padding>
|
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/>
|
||||||
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/>
|
</padding>
|
||||||
</padding>
|
</Label>
|
||||||
</Label>
|
<Label fx:id="boatHeadingLabel" text="Boat Heading:"
|
||||||
<Label fx:id="boatSpeedLabel" text="Boat Speed:"
|
GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowSpan="2"
|
||||||
GridPane.columnIndex="1" GridPane.halignment="LEFT"
|
GridPane.valignment="BOTTOM">
|
||||||
GridPane.rowSpan="2" GridPane.valignment="CENTER">
|
<padding>
|
||||||
<opaqueInsets>
|
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/>
|
||||||
<Insets/>
|
</padding>
|
||||||
</opaqueInsets>
|
</Label>
|
||||||
<padding>
|
<GridPane fx:id="windHolder" GridPane.rowSpan="2">
|
||||||
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/>
|
<columnConstraints>
|
||||||
</padding>
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
|
||||||
</Label>
|
prefWidth="100.0"/>
|
||||||
<Label fx:id="boatHeadingLabel" text="Boat Heading:"
|
</columnConstraints>
|
||||||
GridPane.columnIndex="1" GridPane.halignment="LEFT"
|
<rowConstraints>
|
||||||
GridPane.rowSpan="2" GridPane.valignment="BOTTOM">
|
<RowConstraints maxHeight="120.0" minHeight="120.0"
|
||||||
<padding>
|
prefHeight="120.0" vgrow="SOMETIMES"/>
|
||||||
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/>
|
<RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0"
|
||||||
</padding>
|
vgrow="SOMETIMES"/>
|
||||||
</Label>
|
</rowConstraints>
|
||||||
<GridPane fx:id="windHolder" GridPane.rowSpan="2">
|
<children>
|
||||||
<columnConstraints>
|
<ImageView fx:id="windImageView" fitHeight="92.0" fitWidth="109.0"
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
|
pickOnBounds="true" preserveRatio="true"
|
||||||
prefWidth="100.0"/>
|
GridPane.halignment="CENTER" GridPane.rowSpan="2"
|
||||||
</columnConstraints>
|
GridPane.valignment="CENTER"/>
|
||||||
<rowConstraints>
|
<Label fx:id="windSpeedLabel" text="0.0 Knots"
|
||||||
<RowConstraints maxHeight="120.0" minHeight="120.0"
|
GridPane.halignment="RIGHT" GridPane.rowIndex="1"
|
||||||
prefHeight="120.0" vgrow="SOMETIMES"/>
|
GridPane.valignment="CENTER">
|
||||||
<RowConstraints maxHeight="30.0" minHeight="30.0"
|
<GridPane.margin>
|
||||||
prefHeight="30.0" vgrow="SOMETIMES"/>
|
<Insets right="5.0"/>
|
||||||
</rowConstraints>
|
</GridPane.margin>
|
||||||
<children>
|
</Label>
|
||||||
<ImageView fx:id="windImageView" fitHeight="92.0"
|
<Label fx:id="windDirectionLabel" text="180.0°"
|
||||||
fitWidth="109.0" pickOnBounds="true" preserveRatio="true"
|
GridPane.halignment="LEFT" GridPane.rowIndex="1"
|
||||||
GridPane.halignment="CENTER" GridPane.rowSpan="2"
|
GridPane.valignment="CENTER">
|
||||||
GridPane.valignment="CENTER"/>
|
<GridPane.margin>
|
||||||
<Label fx:id="windSpeedLabel" text="0.0 Knots"
|
<Insets left="5.0"/>
|
||||||
GridPane.halignment="RIGHT" GridPane.rowIndex="1"
|
</GridPane.margin>
|
||||||
GridPane.valignment="CENTER">
|
</Label>
|
||||||
<GridPane.margin>
|
</children>
|
||||||
<Insets right="5.0"/>
|
</GridPane>
|
||||||
</GridPane.margin>
|
</children>
|
||||||
</Label>
|
<opaqueInsets>
|
||||||
<Label fx:id="windDirectionLabel" text="180.0°"
|
<Insets/>
|
||||||
GridPane.halignment="LEFT" GridPane.rowIndex="1"
|
</opaqueInsets>
|
||||||
GridPane.valignment="CENTER">
|
<GridPane.margin>
|
||||||
<GridPane.margin>
|
<Insets bottom="10.0" left="10.0" top="40.0"/>
|
||||||
<Insets left="5.0"/>
|
</GridPane.margin>
|
||||||
</GridPane.margin>
|
</GridPane>
|
||||||
</Label>
|
<GridPane GridPane.columnIndex="1" GridPane.rowIndex="2">
|
||||||
</children>
|
<columnConstraints>
|
||||||
</GridPane>
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
|
||||||
</children>
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
|
||||||
<opaqueInsets>
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
|
||||||
<Insets/>
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
|
||||||
</opaqueInsets>
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
|
||||||
<GridPane.margin>
|
</columnConstraints>
|
||||||
<Insets bottom="10.0" left="10.0" top="40.0"/>
|
<rowConstraints>
|
||||||
</GridPane.margin>
|
<RowConstraints maxHeight="152.0" minHeight="10.0" prefHeight="152.0"
|
||||||
</GridPane>
|
vgrow="SOMETIMES"/>
|
||||||
<GridPane GridPane.columnIndex="1" GridPane.rowIndex="2">
|
<RowConstraints maxHeight="118.0" minHeight="10.0" prefHeight="98.0"
|
||||||
<columnConstraints>
|
vgrow="SOMETIMES"/>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
|
</rowConstraints>
|
||||||
prefWidth="100.0"/>
|
<children>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
|
<ImageView fx:id="velocityIcon" fitHeight="88.0" fitWidth="106.0"
|
||||||
prefWidth="100.0"/>
|
pickOnBounds="true" preserveRatio="true" visible="false"
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
|
GridPane.halignment="CENTER" GridPane.rowIndex="1">
|
||||||
prefWidth="100.0"/>
|
<image>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
|
<Image url="@../icons/velocity.png"/>
|
||||||
prefWidth="100.0"/>
|
</image>
|
||||||
</columnConstraints>
|
</ImageView>
|
||||||
<rowConstraints>
|
<ImageView fx:id="handlingIcon" fitHeight="87.0" fitWidth="98.0"
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0"
|
pickOnBounds="true" preserveRatio="true" visible="false"
|
||||||
vgrow="SOMETIMES"/>
|
GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0"
|
GridPane.rowIndex="1">
|
||||||
vgrow="SOMETIMES"/>
|
<image>
|
||||||
</rowConstraints>
|
<Image url="@../icons/handlingIcon.png"/>
|
||||||
<children>
|
</image>
|
||||||
<ImageView fx:id="velocityIcon" fitHeight="123.0" fitWidth="139.0"
|
</ImageView>
|
||||||
pickOnBounds="true" preserveRatio="true" visible="false"
|
<ImageView fx:id="windWalkerIcon" fitHeight="83.0" fitWidth="100.0"
|
||||||
GridPane.halignment="CENTER" GridPane.rowIndex="1">
|
pickOnBounds="true" preserveRatio="true" visible="false"
|
||||||
<image>
|
GridPane.columnIndex="2" GridPane.halignment="CENTER"
|
||||||
<Image url="@../icons/velocity.png"/>
|
GridPane.rowIndex="1">
|
||||||
</image>
|
<image>
|
||||||
</ImageView>
|
<Image url="@../icons/windWalkerIcon.png"/>
|
||||||
<ImageView fx:id="handlingIcon" fitHeight="123.0" fitWidth="139.0"
|
</image>
|
||||||
pickOnBounds="true" preserveRatio="true" visible="false"
|
</ImageView>
|
||||||
GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
<ImageView fx:id="bumperIcon" fitHeight="83.0" fitWidth="88.0"
|
||||||
GridPane.rowIndex="1">
|
pickOnBounds="true" preserveRatio="true" visible="false"
|
||||||
<image>
|
GridPane.columnIndex="3" GridPane.halignment="CENTER"
|
||||||
<Image url="@../icons/handlingIcon.png"/>
|
GridPane.rowIndex="1">
|
||||||
</image>
|
<image>
|
||||||
</ImageView>
|
<Image url="@../icons/bumperIcon.png"/>
|
||||||
<ImageView fx:id="windWalkerIcon" fitHeight="123.0" fitWidth="139.0"
|
</image>
|
||||||
pickOnBounds="true" preserveRatio="true" visible="false"
|
</ImageView>
|
||||||
GridPane.columnIndex="2" GridPane.halignment="CENTER"
|
<ImageView fx:id="badRandomIcon" fitHeight="69.0" fitWidth="103.0"
|
||||||
GridPane.rowIndex="1">
|
pickOnBounds="true" preserveRatio="true" visible="false"
|
||||||
<image>
|
GridPane.columnIndex="4" GridPane.halignment="CENTER"
|
||||||
<Image url="@../icons/windWalkerIcon.png"/>
|
GridPane.rowIndex="1" GridPane.valignment="CENTER">
|
||||||
</image>
|
<image>
|
||||||
</ImageView>
|
<Image url="@../icons/ayy_lmao.gif"/>
|
||||||
<ImageView fx:id="bumperIcon" fitHeight="123.0" fitWidth="139.0"
|
</image>
|
||||||
pickOnBounds="true" preserveRatio="true" visible="false"
|
</ImageView>
|
||||||
GridPane.columnIndex="3" GridPane.halignment="CENTER"
|
</children>
|
||||||
GridPane.rowIndex="1">
|
</GridPane>
|
||||||
<image>
|
</children>
|
||||||
<Image url="@../icons/bumperIcon.png"/>
|
</GridPane>
|
||||||
</image>
|
</children>
|
||||||
</ImageView>
|
|
||||||
</children>
|
|
||||||
</GridPane>
|
|
||||||
</children>
|
|
||||||
</GridPane>
|
|
||||||
</children>
|
|
||||||
</StackPane>
|
|
||||||
</children>
|
|
||||||
<stylesheets>
|
<stylesheets>
|
||||||
<String fx:value="/css/Master.css" />
|
<String fx:value="/css/Master.css"/>
|
||||||
<String fx:value="/css/RaceView.css" />
|
<String fx:value="/css/RaceView.css"/>
|
||||||
</stylesheets>
|
</stylesheets>
|
||||||
</AnchorPane>
|
</StackPane>
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import com.jfoenix.controls.*?>
|
|
||||||
<?import java.lang.*?>
|
|
||||||
<?import javafx.geometry.*?>
|
|
||||||
<?import javafx.scene.control.*?>
|
|
||||||
<?import javafx.scene.layout.*?>
|
|
||||||
<?import javafx.scene.text.*?>
|
|
||||||
<?import com.jfoenix.controls.JFXButton?>
|
<?import com.jfoenix.controls.JFXButton?>
|
||||||
<?import com.jfoenix.controls.JFXTextField?>
|
<?import com.jfoenix.controls.JFXTextField?>
|
||||||
<?import java.lang.String?>
|
<?import java.lang.String?>
|
||||||
@@ -18,48 +12,35 @@
|
|||||||
<?import javafx.scene.layout.StackPane?>
|
<?import javafx.scene.layout.StackPane?>
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?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>
|
||||||
<GridPane fx:id="serverListMainGridPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308">
|
<GridPane fx:id="serverListMainGridPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308">
|
||||||
<children>
|
<children>
|
||||||
<GridPane fx:id="connectGridPane" GridPane.rowIndex="2">
|
<GridPane fx:id="connectGridPane" GridPane.rowIndex="2">
|
||||||
<children>
|
<children>
|
||||||
<JFXButton fx:id="connectButton" buttonType="RAISED" prefHeight="45.0" prefWidth="220.0" ripplerFill="#3493e3" text="CONNECT" textFill="WHITE" GridPane.columnIndex="5" GridPane.halignment="RIGHT" GridPane.rowIndex="1" GridPane.valignment="CENTER">
|
<JFXButton fx:id="connectButton" buttonType="RAISED" prefHeight="45.0"
|
||||||
|
prefWidth="220.0" ripplerFill="#3493e3" text="CONNECT" textFill="WHITE"
|
||||||
|
GridPane.columnIndex="5" GridPane.halignment="RIGHT"
|
||||||
|
GridPane.valignment="CENTER">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets right="50.0" />
|
<Insets right="50.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</JFXButton>
|
</JFXButton>
|
||||||
<JFXTextField fx:id="serverHostName" maxHeight="30.0" minHeight="30.0" prefHeight="30.0" promptText="Host Name" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER">
|
<JFXTextField fx:id="serverHostName" maxHeight="30.0" minHeight="30.0" prefHeight="30.0" promptText="Host Name" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets left="20.0" right="20.0" />
|
<Insets left="20.0" right="20.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</JFXTextField>
|
</JFXTextField>
|
||||||
<JFXTextField fx:id="serverPortNumber" maxHeight="30.0" minHeight="30.0" prefHeight="30.0" promptText="Port Number" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER">
|
<JFXTextField fx:id="serverPortNumber" maxHeight="30.0" minHeight="30.0" prefHeight="30.0" promptText="Port Number" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets left="20.0" right="20.0" />
|
<Insets left="20.0" right="20.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</JFXTextField>
|
</JFXTextField>
|
||||||
<Label fx:id="connectLabel" text="Direct Connect:" GridPane.columnIndex="1" GridPane.halignment="RIGHT" GridPane.rowIndex="1" GridPane.valignment="CENTER">
|
<Label fx:id="connectLabel" text="Direct Connect:" GridPane.columnIndex="1" GridPane.halignment="RIGHT" GridPane.valignment="CENTER">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets right="45.0" />
|
<Insets right="45.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</Label>
|
</Label>
|
||||||
<Label fx:id="connectLabel1" text="Connect to Room:" GridPane.columnIndex="2" GridPane.halignment="RIGHT" GridPane.valignment="CENTER">
|
|
||||||
<GridPane.margin>
|
|
||||||
<Insets right="45.0" top="5.0" />
|
|
||||||
</GridPane.margin>
|
|
||||||
</Label>
|
|
||||||
<JFXButton fx:id="roomConnectButton" buttonType="RAISED" prefHeight="45.0" prefWidth="220.0" text="CONNECT" GridPane.columnIndex="5" GridPane.halignment="RIGHT" GridPane.valignment="CENTER">
|
|
||||||
<GridPane.margin>
|
|
||||||
<Insets right="50.0" top="5.0" />
|
|
||||||
</GridPane.margin>
|
|
||||||
</JFXButton>
|
|
||||||
<JFXTextField fx:id="roomNumber" maxHeight="30.0" minHeight="30.0" prefHeight="30.0" promptText="Room Number" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
|
|
||||||
<GridPane.margin>
|
|
||||||
<Insets left="20.0" right="20.0" top="5.0" />
|
|
||||||
</GridPane.margin>
|
|
||||||
</JFXTextField>
|
|
||||||
</children>
|
</children>
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" />
|
<ColumnConstraints hgrow="SOMETIMES" />
|
||||||
@@ -70,7 +51,6 @@
|
|||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="273.0" minWidth="250.0" prefWidth="273.0" />
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="273.0" minWidth="250.0" prefWidth="273.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
@@ -96,9 +76,12 @@
|
|||||||
<Insets left="35.0" top="5.0" />
|
<Insets left="35.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</Label>
|
</Label>
|
||||||
<JFXButton id="hostButton" fx:id="serverListHostButton" buttonType="RAISED" prefHeight="45.0" prefWidth="220.0" text="HOST" GridPane.columnIndex="1" GridPane.halignment="RIGHT" GridPane.valignment="CENTER">
|
<JFXButton id="hostButton" fx:id="serverListHostButton" buttonType="RAISED"
|
||||||
|
prefHeight="45.0" prefWidth="220.0"
|
||||||
|
text="HOST" GridPane.columnIndex="1" GridPane.halignment="RIGHT"
|
||||||
|
GridPane.valignment="CENTER">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets right="50.0" />
|
<Insets right="50.0"/>
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</JFXButton>
|
</JFXButton>
|
||||||
</children>
|
</children>
|
||||||
@@ -116,11 +99,11 @@
|
|||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints maxHeight="80.0" minHeight="80.0" prefHeight="80.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="80.0" minHeight="80.0" prefHeight="80.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="400.0" prefHeight="465.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="400.0" prefHeight="400.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="70.0" minHeight="70.0" prefHeight="70.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="80.0" minHeight="80.0" prefHeight="80.0" vgrow="SOMETIMES" />
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<stylesheets>
|
<stylesheets>
|
||||||
<String fx:value="/css/Master.css" />
|
<String fx:value="/css/Master.css"/>
|
||||||
<String fx:value="/css/ServerListView.css" />
|
<String fx:value="/css/ServerListView.css" />
|
||||||
</stylesheets>
|
</stylesheets>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.text.*?>
|
||||||
|
<?import com.jfoenix.controls.*?>
|
||||||
|
<?import java.lang.*?>
|
||||||
|
<?import javafx.geometry.*?>
|
||||||
|
<?import javafx.scene.control.*?>
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
<?import com.jfoenix.controls.JFXButton?>
|
<?import com.jfoenix.controls.JFXButton?>
|
||||||
<?import com.jfoenix.controls.JFXColorPicker?>
|
<?import com.jfoenix.controls.JFXColorPicker?>
|
||||||
<?import com.jfoenix.controls.JFXDialogLayout?>
|
<?import com.jfoenix.controls.JFXDialogLayout?>
|
||||||
@@ -10,54 +16,45 @@
|
|||||||
<?import javafx.scene.layout.ColumnConstraints?>
|
<?import javafx.scene.layout.ColumnConstraints?>
|
||||||
<?import javafx.scene.layout.GridPane?>
|
<?import javafx.scene.layout.GridPane?>
|
||||||
<?import javafx.scene.layout.RowConstraints?>
|
<?import javafx.scene.layout.RowConstraints?>
|
||||||
<JFXDialogLayout maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
|
|
||||||
minWidth="-Infinity" prefWidth="400.0" xmlns="http://javafx.com/javafx/8"
|
<JFXDialogLayout maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="400.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.dialogs.BoatCustomizeController">
|
||||||
xmlns:fx="http://javafx.com/fxml/1"
|
|
||||||
fx:controller="seng302.visualiser.controllers.dialogs.BoatCustomizeController">
|
|
||||||
<children>
|
<children>
|
||||||
<GridPane>
|
<GridPane>
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints maxHeight="90.0" minHeight="90.0" prefHeight="90.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="90.0" minHeight="48.0" prefHeight="48.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="100.0" minHeight="100.0" prefHeight="100.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="207.0" minHeight="93.0" prefHeight="181.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="125.0" minHeight="61.0" prefHeight="99.0"
|
<RowConstraints maxHeight="207.0" minHeight="93.0" prefHeight="181.0" vgrow="SOMETIMES" />
|
||||||
vgrow="SOMETIMES"/>
|
<RowConstraints maxHeight="145.0" minHeight="66.0" prefHeight="109.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="164.0" minHeight="100.0" prefHeight="126.0"
|
<RowConstraints maxHeight="125.0" minHeight="24.0" prefHeight="72.0" vgrow="SOMETIMES" />
|
||||||
vgrow="SOMETIMES"/>
|
<RowConstraints maxHeight="164.0" minHeight="100.0" prefHeight="105.0" vgrow="SOMETIMES" />
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<children>
|
<children>
|
||||||
<Label fx:id="hostDialogHeader" text="Customize Boat" GridPane.halignment="CENTER"
|
<Label fx:id="hostDialogHeader" text="Customize Boat" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
|
||||||
GridPane.valignment="CENTER"/>
|
<JFXButton fx:id="submitBtn" prefHeight="45.0" prefWidth="220.0" text="Customize Boat" GridPane.halignment="CENTER" GridPane.rowIndex="5" GridPane.valignment="CENTER" />
|
||||||
<JFXButton fx:id="submitBtn" prefHeight="45.0" prefWidth="220.0" text="Customize Boat" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="CENTER" />
|
<JFXTextField fx:id="boatName" focusColor="#6c6c6c" promptText="Boat Name" unFocusColor="#6b6b6b" GridPane.rowIndex="3">
|
||||||
<JFXTextField fx:id="boatName" focusColor="#6c6c6c" promptText="Boat Name"
|
|
||||||
unFocusColor="#6b6b6b" GridPane.rowIndex="1">
|
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets left="30.0" right="30.0" />
|
<Insets left="30.0" right="30.0" />
|
||||||
</GridPane.margin></JFXTextField>
|
</GridPane.margin></JFXTextField>
|
||||||
<GridPane GridPane.halignment="CENTER" GridPane.rowIndex="2"
|
<GridPane GridPane.halignment="CENTER" GridPane.rowIndex="4" GridPane.valignment="CENTER">
|
||||||
GridPane.valignment="CENTER">
|
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="139.0" minWidth="10.0"
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="139.0" minWidth="10.0" prefWidth="94.0" />
|
||||||
prefWidth="94.0"/>
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="203.0" minWidth="10.0" prefWidth="198.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="203.0" minWidth="10.0"
|
|
||||||
prefWidth="198.0"/>
|
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints percentHeight="100.0" valignment="CENTER" vgrow="SOMETIMES"/>
|
<RowConstraints percentHeight="100.0" valignment="CENTER" vgrow="SOMETIMES" />
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<children>
|
<children>
|
||||||
<Label fx:id="boatColorLabel" prefHeight="25.0" prefWidth="96.0"
|
<Label fx:id="boatColorLabel" prefHeight="25.0" prefWidth="96.0" text="Boat Color" GridPane.valignment="CENTER">
|
||||||
text="Boat Color" GridPane.valignment="CENTER">
|
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets top="-10.0" />
|
<Insets top="-10.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</Label>
|
</Label>
|
||||||
<JFXColorPicker fx:id="colorPicker" onAction="#colorChanged"
|
<JFXColorPicker fx:id="colorPicker" onAction="#colorChanged" GridPane.columnIndex="1" GridPane.valignment="CENTER">
|
||||||
GridPane.columnIndex="1" GridPane.valignment="CENTER">
|
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets left="30.0" top="-10.0"/>
|
<Insets left="30.0" top="-10.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</JFXColorPicker>
|
</JFXColorPicker>
|
||||||
</children>
|
</children>
|
||||||
@@ -65,11 +62,45 @@
|
|||||||
<Insets left="30.0" right="30.0" />
|
<Insets left="30.0" right="30.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
|
<GridPane GridPane.rowIndex="1">
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="50.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="256.0" minWidth="10.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="50.0" />
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||||
|
</rowConstraints>
|
||||||
|
<children>
|
||||||
|
<Pane fx:id="boatPane" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" />
|
||||||
|
<JFXButton buttonType="RAISED" onAction="#prevBoat" prefHeight="200.0" prefWidth="50.0" text="<" />
|
||||||
|
<JFXButton buttonType="RAISED" onAction="#nextBoat" prefHeight="200.0" prefWidth="50.0" text=">" GridPane.columnIndex="2" />
|
||||||
|
</children>
|
||||||
|
</GridPane>
|
||||||
|
<GridPane GridPane.rowIndex="2">
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||||
|
</rowConstraints>
|
||||||
|
<children>
|
||||||
|
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Max Speed:" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
|
||||||
|
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Acceleration:" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER" />
|
||||||
|
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Handling:" GridPane.halignment="CENTER" GridPane.rowIndex="2" GridPane.valignment="CENTER" />
|
||||||
|
<ProgressBar fx:id="speedBar" focusTraversable="false" prefWidth="200.0" progress="0.0" GridPane.columnIndex="1" />
|
||||||
|
<ProgressBar fx:id="accelBar" prefWidth="200.0" progress="0.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
||||||
|
<ProgressBar fx:id="handleBar" prefWidth="200.0" progress="0.0" GridPane.columnIndex="1" GridPane.rowIndex="2" />
|
||||||
|
</children>
|
||||||
|
</GridPane>
|
||||||
</children>
|
</children>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
</children>
|
</children>
|
||||||
<stylesheets>
|
<stylesheets>
|
||||||
<String fx:value="/css/dialogs/BoatCustomize.css"/>
|
<String fx:value="/css/dialogs/BoatCustomize.css" />
|
||||||
<String fx:value="/css/Master.css"/>
|
<String fx:value="/css/Master.css" />
|
||||||
</stylesheets>
|
</stylesheets>
|
||||||
</JFXDialogLayout>
|
</JFXDialogLayout>
|
||||||
|
|||||||
@@ -0,0 +1,231 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import com.jfoenix.controls.JFXButton?>
|
||||||
|
<?import com.jfoenix.controls.JFXDialogLayout?>
|
||||||
|
<?import com.jfoenix.controls.JFXToggleButton?>
|
||||||
|
<?import java.net.URL?>
|
||||||
|
<?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?>
|
||||||
|
<JFXDialogLayout fx:id="keyBindDialog" maxHeight="-Infinity" maxWidth="-Infinity"
|
||||||
|
minHeight="-Infinity" minWidth="-Infinity" prefHeight="580.0" prefWidth="500.0"
|
||||||
|
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
|
||||||
|
fx:controller="seng302.visualiser.controllers.dialogs.KeyBindingDialogController">
|
||||||
|
<stylesheets>
|
||||||
|
<URL value="@../../css/dialogs/KeyBindingDialog.css"/>
|
||||||
|
<URL value="@../../css/Master.css"/>
|
||||||
|
</stylesheets>
|
||||||
|
<children>
|
||||||
|
<GridPane>
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="60.0"
|
||||||
|
vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="60.0"
|
||||||
|
vgrow="SOMETIMES"/>
|
||||||
|
</rowConstraints>
|
||||||
|
<children>
|
||||||
|
<ScrollPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1">
|
||||||
|
<content>
|
||||||
|
<StackPane prefHeight="150.0" prefWidth="200.0">
|
||||||
|
<children>
|
||||||
|
<GridPane>
|
||||||
|
<children>
|
||||||
|
<JFXButton fx:id="viewButton" buttonType="RAISED"
|
||||||
|
minHeight="35.0" prefWidth="120.0" text="F1"
|
||||||
|
GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="14" GridPane.valignment="CENTER"/>
|
||||||
|
<Label text="VIEW ASPECT" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="14" GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton fx:id="rightButton" buttonType="RAISED"
|
||||||
|
minHeight="35.0" prefWidth="120.0" text="D"
|
||||||
|
GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="13" GridPane.valignment="CENTER"/>
|
||||||
|
<Label text="RIGHT" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="13" GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton fx:id="leftButton" buttonType="RAISED"
|
||||||
|
minHeight="35.0" prefWidth="120.0" text="A"
|
||||||
|
GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="12" GridPane.valignment="CENTER"/>
|
||||||
|
<Label text="LEFT" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="12" GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton fx:id="forwardButton" buttonType="RAISED"
|
||||||
|
minHeight="35.0" prefWidth="120.0" text="W"
|
||||||
|
GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="10" GridPane.valignment="CENTER"/>
|
||||||
|
<Label text="FORWARD" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="10" GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton fx:id="backwardButton" buttonType="RAISED"
|
||||||
|
minHeight="35.0" prefWidth="120.0" text="S"
|
||||||
|
GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="11" GridPane.valignment="CENTER"/>
|
||||||
|
<Label text="BACKWARD" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="11" GridPane.valignment="CENTER"/>
|
||||||
|
<Label text="ZOOM IN" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="1" GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</Label>
|
||||||
|
<Label text="ZOOM OUT" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="2" GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</Label>
|
||||||
|
<Label text="VMG" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="3" GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</Label>
|
||||||
|
<Label text="SAILS IN/OUT" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="4" GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</Label>
|
||||||
|
<Label text="TACK/GYBE" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="5" GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</Label>
|
||||||
|
<Label fx:id="upwindLabel" text="UPWIND"
|
||||||
|
GridPane.halignment="CENTER" GridPane.rowIndex="6"
|
||||||
|
GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</Label>
|
||||||
|
<Label fx:id="downwindLabel" text="DOWNWIND"
|
||||||
|
GridPane.halignment="CENTER" GridPane.rowIndex="7"
|
||||||
|
GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</Label>
|
||||||
|
<JFXButton id="ZOOM IN" fx:id="zoomInbtn" buttonType="RAISED"
|
||||||
|
maxHeight="-Infinity" maxWidth="-Infinity" minHeight="35.0"
|
||||||
|
minWidth="-Infinity" prefWidth="120.0" text="Z"
|
||||||
|
GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="1" GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton id="ZOOM OUT" fx:id="zoomOutBtn" buttonType="RAISED"
|
||||||
|
maxHeight="-Infinity" maxWidth="-Infinity" minHeight="35.0"
|
||||||
|
minWidth="-Infinity" prefWidth="120.0" text="X"
|
||||||
|
GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="2" GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton id="VMG" fx:id="vmgBtn" buttonType="RAISED"
|
||||||
|
maxHeight="-Infinity" maxWidth="-Infinity" minHeight="35.0"
|
||||||
|
minWidth="-Infinity" prefWidth="120.0" text="SPACE"
|
||||||
|
GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="3" GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton id="SAILS IN/OUT" fx:id="sailInOutBtn"
|
||||||
|
buttonType="RAISED" maxHeight="-Infinity"
|
||||||
|
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity"
|
||||||
|
prefWidth="120.0" text="SHIFT" GridPane.columnIndex="1"
|
||||||
|
GridPane.halignment="CENTER" GridPane.rowIndex="4"
|
||||||
|
GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton id="TACK/GYBE" fx:id="tackGybeBtn"
|
||||||
|
buttonType="RAISED" maxHeight="-Infinity"
|
||||||
|
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity"
|
||||||
|
prefWidth="120.0" text="ENTER" GridPane.columnIndex="1"
|
||||||
|
GridPane.halignment="CENTER" GridPane.rowIndex="5"
|
||||||
|
GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton id="UPWIND" fx:id="upwindBtn" buttonType="RAISED"
|
||||||
|
maxHeight="-Infinity" maxWidth="-Infinity" minHeight="35.0"
|
||||||
|
minWidth="-Infinity" prefWidth="120.0" text="PAGE_UP"
|
||||||
|
GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="6" GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton id="DOWNWIND" fx:id="downwindBtn"
|
||||||
|
buttonType="RAISED" maxHeight="-Infinity"
|
||||||
|
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity"
|
||||||
|
prefWidth="120.0" text="PAGE_DOWN" GridPane.columnIndex="1"
|
||||||
|
GridPane.halignment="CENTER" GridPane.rowIndex="7"
|
||||||
|
GridPane.valignment="CENTER"/>
|
||||||
|
<JFXToggleButton fx:id="turningToggle" minHeight="-Infinity"
|
||||||
|
prefHeight="35.0" text="OFF / ON" GridPane.columnIndex="1"
|
||||||
|
GridPane.halignment="CENTER" GridPane.rowIndex="8"/>
|
||||||
|
<Label text="CONTINUOUSLY TURNING" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="8" GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</Label>
|
||||||
|
<Label styleClass="sectionLabel" text="BOAT ACTIONS"
|
||||||
|
GridPane.columnSpan="2" GridPane.halignment="CENTER"
|
||||||
|
GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets left="50.0"/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</Label>
|
||||||
|
<Label styleClass="sectionLabel" text="CAMERA SETTINGS"
|
||||||
|
GridPane.columnSpan="2" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="9" GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets left="50.0"/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</Label>
|
||||||
|
</children>
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity"
|
||||||
|
minWidth="-Infinity" prefWidth="250.0"/>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity"
|
||||||
|
minWidth="-Infinity" prefWidth="150.0"/>
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0"
|
||||||
|
prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
</rowConstraints>
|
||||||
|
</GridPane>
|
||||||
|
</children>
|
||||||
|
</StackPane>
|
||||||
|
</content>
|
||||||
|
</ScrollPane>
|
||||||
|
<Label fx:id="keyBindingDialogHeader" text="CUSTOM KEYBINDING" GridPane.columnSpan="2"
|
||||||
|
GridPane.halignment="CENTER" GridPane.valignment="CENTER"/>
|
||||||
|
<Label fx:id="closeLabel" text="✖" GridPane.halignment="RIGHT"
|
||||||
|
GridPane.valignment="TOP"/>
|
||||||
|
<JFXButton fx:id="resetBtn" buttonType="RAISED" maxHeight="-Infinity"
|
||||||
|
maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="45.0"
|
||||||
|
prefWidth="150.0" text="RESET" GridPane.columnSpan="2" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="2" GridPane.valignment="CENTER"/>
|
||||||
|
</children>
|
||||||
|
</GridPane>
|
||||||
|
</children>
|
||||||
|
</JFXDialogLayout>
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
|
||||||
|
<?import com.jfoenix.controls.JFXButton?>
|
||||||
|
<?import com.jfoenix.controls.JFXDialogLayout?>
|
||||||
|
<?import java.net.URL?>
|
||||||
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.layout.ColumnConstraints?>
|
||||||
|
<?import javafx.scene.layout.GridPane?>
|
||||||
|
<?import javafx.scene.layout.RowConstraints?>
|
||||||
|
<JFXDialogLayout maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
|
||||||
|
minWidth="-Infinity" prefWidth="550.0" xmlns="http://javafx.com/javafx/8"
|
||||||
|
xmlns:fx="http://javafx.com/fxml/1"
|
||||||
|
fx:controller="seng302.visualiser.controllers.dialogs.PopupDialogController">
|
||||||
|
<children>
|
||||||
|
<GridPane>
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308"/>
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints maxHeight="-Infinity" minHeight="30.0" prefHeight="30.0"
|
||||||
|
vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="80.0"
|
||||||
|
prefHeight="80.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
</rowConstraints>
|
||||||
|
<children>
|
||||||
|
<JFXButton fx:id="optionButton" buttonType="RAISED" prefHeight="55.0"
|
||||||
|
prefWidth="150.0" GridPane.halignment="RIGHT" GridPane.rowIndex="2"
|
||||||
|
GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</JFXButton>
|
||||||
|
<Label fx:id="contentLabel" text="Popup content goes here ..."
|
||||||
|
GridPane.rowIndex="1"/>
|
||||||
|
<Label fx:id="headerLabel" text="Popup header"/>
|
||||||
|
<Label fx:id="closeLabel" text="✖" translateY="-10.0" GridPane.halignment="RIGHT"/>
|
||||||
|
</children>
|
||||||
|
</GridPane>
|
||||||
|
</children>
|
||||||
|
<stylesheets>
|
||||||
|
<URL value="@../../css/dialogs/Popup.css"/>
|
||||||
|
<URL value="@../../css/Master.css"/>
|
||||||
|
</stylesheets>
|
||||||
|
</JFXDialogLayout>
|
||||||
@@ -4,14 +4,18 @@
|
|||||||
<?import com.jfoenix.controls.JFXDialogLayout?>
|
<?import com.jfoenix.controls.JFXDialogLayout?>
|
||||||
<?import com.jfoenix.controls.JFXSlider?>
|
<?import com.jfoenix.controls.JFXSlider?>
|
||||||
<?import com.jfoenix.controls.JFXTextField?>
|
<?import com.jfoenix.controls.JFXTextField?>
|
||||||
<?import java.lang.String?>
|
<?import java.net.URL?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
<?import javafx.scene.layout.ColumnConstraints?>
|
<?import javafx.scene.layout.ColumnConstraints?>
|
||||||
<?import javafx.scene.layout.GridPane?>
|
<?import javafx.scene.layout.GridPane?>
|
||||||
<?import javafx.scene.layout.RowConstraints?>
|
<?import javafx.scene.layout.RowConstraints?>
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<JFXDialogLayout maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="550.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.dialogs.ServerCreationController">
|
|
||||||
|
<JFXDialogLayout maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
|
||||||
|
minWidth="-Infinity" prefWidth="550.0" xmlns="http://javafx.com/javafx/8.0.111"
|
||||||
|
xmlns:fx="http://javafx.com/fxml/1"
|
||||||
|
fx:controller="seng302.visualiser.controllers.dialogs.ServerCreationController">
|
||||||
<children>
|
<children>
|
||||||
<GridPane>
|
<GridPane>
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
@@ -59,11 +63,13 @@
|
|||||||
</VBox>
|
</VBox>
|
||||||
</children>
|
</children>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
|
<Label fx:id="closeLabel" text="✖" GridPane.halignment="RIGHT"
|
||||||
|
GridPane.valignment="TOP"/>
|
||||||
</children>
|
</children>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
</children>
|
</children>
|
||||||
<stylesheets>
|
<stylesheets>
|
||||||
<String fx:value="/css/dialogs/ServerCreation.css" />
|
<URL value="@../../css/dialogs/ServerCreation.css"/>
|
||||||
<String fx:value="/css/Master.css"/>
|
<URL value="@../../css/Master.css"/>
|
||||||
</stylesheets>
|
</stylesheets>
|
||||||
</JFXDialogLayout>
|
</JFXDialogLayout>
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public class ChatCommandsTest {
|
|||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
ie.printStackTrace();
|
ie.printStackTrace();
|
||||||
}
|
}
|
||||||
Assert.assertEquals(5.0, GameState.getSpeedMultiplier(), 0.00001);
|
Assert.assertEquals(5.0, GameState.getServerSpeedMultiplier(), 0.00001);
|
||||||
mst.terminate();
|
mst.terminate();
|
||||||
try {
|
try {
|
||||||
Thread.sleep(200);
|
Thread.sleep(200);
|
||||||
@@ -150,7 +150,7 @@ public class ChatCommandsTest {
|
|||||||
ie.printStackTrace();
|
ie.printStackTrace();
|
||||||
}
|
}
|
||||||
mst.terminate();
|
mst.terminate();
|
||||||
Assert.assertEquals(1.0, GameState.getSpeedMultiplier(), 0.00001);
|
Assert.assertEquals(1.0, GameState.getServerSpeedMultiplier(), 0.00001);
|
||||||
try {
|
try {
|
||||||
Thread.sleep(2000);
|
Thread.sleep(2000);
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
@@ -194,7 +194,7 @@ public class ChatCommandsTest {
|
|||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
ie.printStackTrace();
|
ie.printStackTrace();
|
||||||
}
|
}
|
||||||
Assert.assertEquals(1.0, GameState.getSpeedMultiplier(), 0.00001);
|
Assert.assertEquals(1.0, GameState.getServerSpeedMultiplier(), 0.00001);
|
||||||
mst.terminate();
|
mst.terminate();
|
||||||
host.setSocketToClose();
|
host.setSocketToClose();
|
||||||
client.setSocketToClose();
|
client.setSocketToClose();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import seng302.gameServer.GameState;
|
import seng302.gameServer.GameState;
|
||||||
import seng302.utilities.GeoUtility;
|
import seng302.utilities.GeoUtility;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
|
|
||||||
import static seng302.gameServer.GameState.checkCollision;
|
import static seng302.gameServer.GameState.checkCollision;
|
||||||
|
|
||||||
@@ -14,8 +15,10 @@ import static seng302.gameServer.GameState.checkCollision;
|
|||||||
*/
|
*/
|
||||||
public class UpdateYachtTest {
|
public class UpdateYachtTest {
|
||||||
|
|
||||||
private ServerYacht yacht1 = new ServerYacht("Yacht", 1, "1", "Yacht" + 1, "Yacht" + 1, "Test1");
|
private ServerYacht yacht1 = new ServerYacht(BoatMeshType.DINGHY, 1, "1", "Yacht" + 1,
|
||||||
private ServerYacht yacht2 = new ServerYacht("Yacht", 2, "2", "Yacht" + 2, "Yacht" + 2, "Test2");
|
"Yacht" + 1, "Test1");
|
||||||
|
private ServerYacht yacht2 = new ServerYacht(BoatMeshType.DINGHY, 2, "2", "Yacht" + 2,
|
||||||
|
"Yacht" + 2, "Test2");
|
||||||
private GeoPoint geoPoint1 = new GeoPoint(50.0, 50.0);
|
private GeoPoint geoPoint1 = new GeoPoint(50.0, 50.0);
|
||||||
private GeoPoint geoPoint2 = GeoUtility.getGeoCoordinate(geoPoint1, 90.0, 50.0);
|
private GeoPoint geoPoint2 = GeoUtility.getGeoCoordinate(geoPoint1, 90.0, 50.0);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import org.junit.AfterClass;
|
|||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import seng302.gameServer.GameState;
|
import seng302.gameServer.GameState;
|
||||||
import seng302.model.ServerYacht;
|
import seng302.model.ServerYacht;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
|
|
||||||
|
|
||||||
public class YachtTest {
|
public class YachtTest {
|
||||||
@@ -17,7 +18,7 @@ public class YachtTest {
|
|||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setUp() {
|
public static void setUp() {
|
||||||
new GameState("localhost");
|
new GameState("localhost");
|
||||||
y1 = new ServerYacht("Yacht", 1, "Y1", "Y1", "Yacht 1", "C1");
|
y1 = new ServerYacht(BoatMeshType.DINGHY, 1, "Y1", "Y1", "Yacht 1", "C1");
|
||||||
gs = new GameState("localhost");
|
gs = new GameState("localhost");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
package seng302.serverDiscovery;
|
|
||||||
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
import seng302.discoveryServer.util.ServerListing;
|
|
||||||
import seng302.discoveryServer.util.ServerTable;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
public class ServerTableTest {
|
|
||||||
private static ServerTable serverTable;
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void setup(){
|
|
||||||
serverTable = new ServerTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAddServer(){
|
|
||||||
ServerListing listing = new ServerListing("", "", "", 12, 12);
|
|
||||||
serverTable.addServer(listing);
|
|
||||||
|
|
||||||
assertTrue(serverTable.getAllServers().contains(listing));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetNextRoomCodeIsUnique(){
|
|
||||||
assertTrue(!Objects.equals(serverTable.getNextRoomCode(), serverTable.getNextRoomCode()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetServerRoomCode(){
|
|
||||||
ServerListing listing = new ServerListing("123", "", "", 12, 12);
|
|
||||||
listing.setRoomCode(serverTable.getNextRoomCode().toString());
|
|
||||||
serverTable.addServer(listing);
|
|
||||||
|
|
||||||
ServerListing result = serverTable.getServerByRoomCode(listing.getRoomCode());
|
|
||||||
|
|
||||||
assertTrue(result.equals(listing));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testServersRemovedOnExpiry() throws InterruptedException {
|
|
||||||
ServerListing listing = new ServerListing("432", "221", "", 12, 12);
|
|
||||||
listing.setTtl(1);
|
|
||||||
|
|
||||||
serverTable.addServer(listing);
|
|
||||||
|
|
||||||
listing.decrementTtl();
|
|
||||||
|
|
||||||
Thread.sleep(1000);
|
|
||||||
|
|
||||||
assertTrue(!serverTable.getAllServers().contains(listing));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package seng302.serverDiscovery;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import seng302.gameServer.messages.Message;
|
|
||||||
import seng302.gameServer.messages.RoomCodeRequest;
|
|
||||||
import seng302.model.stream.packets.PacketType;
|
|
||||||
import seng302.discoveryServer.util.ServerRepoStreamParser;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
public class testStreamParser {
|
|
||||||
private static ServerRepoStreamParser parser;
|
|
||||||
private static InputStream inputStream;
|
|
||||||
|
|
||||||
private static void setupWithByteArray(byte[] bytes){
|
|
||||||
inputStream = new ByteArrayInputStream(bytes);
|
|
||||||
parser = new ServerRepoStreamParser(inputStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParseRoomCodeRequest() throws Exception {
|
|
||||||
Message roomCodeMsg = new RoomCodeRequest("1234");
|
|
||||||
setupWithByteArray(roomCodeMsg.getBuffer());
|
|
||||||
|
|
||||||
assertTrue(parser.parse() == PacketType.ROOM_CODE_REQUEST);
|
|
||||||
assertTrue(parser.getRoomCode().equals("1234"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package seng302.utilities;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic tests for the next and previous methods
|
||||||
|
* Created by kre39 on 20/09/17.
|
||||||
|
*/
|
||||||
|
public class BoatMeshTypeTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNextBoatMeshType() {
|
||||||
|
BoatMeshType currentBoat = BoatMeshType.DINGHY;
|
||||||
|
BoatMeshType nextBoat = BoatMeshType.getNextBoatType(currentBoat);
|
||||||
|
Assert.assertEquals(BoatMeshType.CATAMARAN, nextBoat);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPreviousBoatMeshType() {
|
||||||
|
BoatMeshType currentBoat = BoatMeshType.CATAMARAN;
|
||||||
|
BoatMeshType prevBoat = BoatMeshType.getPrevBoatType(currentBoat);
|
||||||
|
Assert.assertEquals(BoatMeshType.DINGHY, prevBoat);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package seng302.utilities;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import seng302.model.GeoPoint;
|
||||||
|
import seng302.model.mark.CompoundMark;
|
||||||
|
import seng302.model.mark.Mark;
|
||||||
|
import seng302.model.token.Token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by wmu16 on 27/09/17.
|
||||||
|
*/
|
||||||
|
public class RandomSpawnTest {
|
||||||
|
|
||||||
|
private RandomSpawn randomSpawn;
|
||||||
|
|
||||||
|
Mark mark1 = new Mark("mark1", 0, 57.670333, 11.827833, 0);
|
||||||
|
Mark mark2 = new Mark("mark2", 1, 57.671829, 11.842049, 1);
|
||||||
|
CompoundMark compoundMark1 = new CompoundMark(0, "mark1",
|
||||||
|
new ArrayList<>(Arrays.asList(mark1)));
|
||||||
|
CompoundMark compoundMark2 = new CompoundMark(0, "mark1",
|
||||||
|
new ArrayList<>(Arrays.asList(mark2)));
|
||||||
|
|
||||||
|
List<CompoundMark> markOrder = new ArrayList<>(Arrays.asList(compoundMark1, compoundMark2));
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
randomSpawn = new RandomSpawn(markOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetRandomTokenLocation() {
|
||||||
|
GeoPoint testMidPoint = GeoUtility
|
||||||
|
.getDirtyMidPoint(compoundMark1.getMidPoint(), compoundMark2.getMidPoint());
|
||||||
|
Double maxDistance = GeoUtility.getDistance(testMidPoint, compoundMark2.getMidPoint());
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
Token token = randomSpawn.getRandomTokenLocation();
|
||||||
|
Double distanceFromCentreRadius = GeoUtility.getDistance(testMidPoint, token);
|
||||||
|
assertTrue("Out of bounds token", distanceFromCentreRadius <= maxDistance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import static org.junit.Assert.assertTrue;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import seng302.model.ClientYacht;
|
import seng302.model.ClientYacht;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by kre39 on 6/08/17.
|
* Created by kre39 on 6/08/17.
|
||||||
@@ -16,7 +17,7 @@ public class BoatSailAnimationToggleTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() throws Exception{
|
public void setup() throws Exception{
|
||||||
yacht = new ClientYacht("Yacht", 1, "YACHT", "YAC", "Test Yacht", "NZ");
|
yacht = new ClientYacht(BoatMeshType.DINGHY, 1, "YACHT", "YAC", "Test Yacht", "NZ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import seng302.model.ServerYacht;
|
|||||||
import seng302.visualiser.ClientToServerThread;
|
import seng302.visualiser.ClientToServerThread;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* Created by kre39 on 7/08/17.
|
* Created by kre39 on 7/08/17.
|
||||||
*/
|
*/
|
||||||
public class ToggleSailSteps {
|
public class ToggleSailSteps {
|
||||||
|
|||||||
Reference in New Issue
Block a user