Added server list updates, and added lobby

- Server list updates when a server is added/removed
- Player can host a server
- Lobby view shows players connected

Tags: #pair[mra106, hyi25] #story[1245]
This commit is contained in:
Michael Rausch
2017-09-07 19:20:36 +12:00
parent 8cc725616c
commit b35126ff4e
13 changed files with 280 additions and 170 deletions
-5
View File
@@ -86,9 +86,6 @@ public class App extends Application {
primaryStage.show();
primaryStage.setOnCloseRequest(e -> {
// ClientPacketParser.appClose();
// ClientPacketParser.appClose();
try {
ServerAdvertiser.getInstance().unregister();
@@ -108,8 +105,6 @@ public class App extends Application {
parseArgs(args);
} catch (ParseException e) {
logger.error("Could not parse command line arguments");
} catch (IOException e) {
e.printStackTrace();
}
launch(args);
@@ -16,6 +16,7 @@ import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Pane;
import seng302.gameServer.GameState;
import seng302.gameServer.MainServerThread;
import seng302.gameServer.ServerDescription;
import seng302.gameServer.messages.BoatAction;
import seng302.gameServer.messages.BoatStatus;
import seng302.model.ClientYacht;
@@ -34,6 +35,7 @@ import seng302.visualiser.controllers.FinishScreenViewController;
import seng302.visualiser.controllers.LobbyController_old;
import seng302.visualiser.controllers.LobbyController_old.CloseStatus;
import seng302.visualiser.controllers.RaceViewController;
import seng302.visualiser.controllers.ViewManager;
/**
* This class is a client side instance of a yacht racing game in JavaFX. The game is instantiated
@@ -72,30 +74,43 @@ public class GameClient {
public void runAsClient(String ipAddress, Integer portNumber) {
try {
startClientToServerThread(ipAddress, portNumber);
socketThread.addDisconnectionListener((cause) -> {
showConnectionError(cause);
Platform.runLater(this::loadStartScreen);
});
// socketThread.addDisconnectionListener((cause) -> {
// showConnectionError(cause);
// Platform.runLater(this::loadStartScreen);
// });
socketThread.addStreamObserver(this::parsePackets);
LobbyController_old lobbyController = loadLobby();
lobbyController.setSocketThread(socketThread);
lobbyController.setPlayerID(socketThread.getClientId());
lobbyController.setPlayerListSource(clientLobbyList);
lobbyController.disableReadyButton();
ViewManager.getInstance().setPlayerList(clientLobbyList);
if (regattaData != null){
lobbyController.setTitle(regattaData.getRegattaName());
lobbyController.setCourseName(regattaData.getCourseName());
ViewManager.getInstance().setProperty("serverName", regattaData.getRegattaName());
ViewManager.getInstance().setProperty("mapName", regattaData.getCourseName());
}
else{
lobbyController.setTitle(ipAddress);
lobbyController.setCourseName("");
ViewManager.getInstance().setProperty("serverName", ipAddress);
ViewManager.getInstance().setProperty("mapName", "");
}
lobbyController.addCloseListener((exitCause) -> this.loadStartScreen());
this.lobbyController = lobbyController;
// TODO disable ready button;
//LobbyController_old lobbyController = loadLobby();
//lobbyController.setSocketThread(socketThread);
//lobbyController.setPlayerID(socketThread.getClientId());
//lobbyController.setPlayerListSource(clientLobbyList);
//lobbyController.disableReadyButton();
// lobbyController.addCloseListener((exitCause) -> this.loadStartScreen());
// this.lobbyController = lobbyController;
} catch (IOException ioe) {
showConnectionError("Unable to find server");
Platform.runLater(this::loadStartScreen);
//Platform.runLater(this::loadStartScreen);
}
}
@@ -104,41 +119,32 @@ public class GameClient {
* @param ipAddress IP to connect to.
* @param portNumber Port to connect to.
*/
public void runAsHost(String ipAddress, Integer portNumber) {
public ServerDescription runAsHost(String ipAddress, Integer portNumber) {
server = new MainServerThread();
try {
startClientToServerThread(ipAddress, portNumber);
socketThread.addDisconnectionListener((cause) -> {
Platform.runLater(this::loadStartScreen);
});
LobbyController_old lobbyController = loadLobby();
lobbyController.setSocketThread(socketThread);
lobbyController.setPlayerID(socketThread.getClientId());
lobbyController.setPlayerListSource(clientLobbyList);
if (regattaData != null) {
lobbyController.setTitle("Hosting: " + regattaData.getRegattaName());
lobbyController.setCourseName(regattaData.getCourseName());
} else {
lobbyController.setTitle("Hosting: " + ipAddress);
lobbyController.setCourseName("");
}
lobbyController.addCloseListener(exitCause -> {
if (exitCause == CloseStatus.READY) {
GameState.resetStartTime();
lobbyController.disableReadyButton();
server.startGame();
} else if (exitCause == CloseStatus.LEAVE) {
server.terminate();
server = null;
loadStartScreen();
}
});
this.lobbyController = lobbyController;
} catch (IOException ioe) {
try {
startClientToServerThread(ipAddress, 4942);
} catch (IOException e) {
showConnectionError("Cannot connect to server as host");
Platform.runLater(this::loadStartScreen);
}
String serverName = "";
String courseName = "";
while (regattaData == null){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ViewManager.getInstance().setPlayerList(clientLobbyList);
serverName = regattaData.getRegattaName();
courseName = regattaData.getCourseName();
return new ServerDescription(serverName, courseName, 0, ipAddress, 4942);
}
private void loadStartScreen() {
@@ -3,16 +3,24 @@ package seng302.visualiser.controllers;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXDialog.DialogTransition;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.application.Platform;
import javafx.collections.ListChangeListener;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import seng302.gameServer.GameStages;
import seng302.gameServer.GameState;
public class LobbyController implements Initializable {
@@ -23,41 +31,43 @@ public class LobbyController implements Initializable {
private ScrollPane playerListScrollpane;
@FXML
private JFXButton customizeButton;
private JFXButton customizeButton, leaveLobbyButton;
@FXML
private StackPane serverListMainStackPane;
@FXML
private Label serverName;
@FXML
private Label mapName;
private List<LobbyController_old.LobbyCloseListener> lobbyListeners = new ArrayList<>();
@Override
public void initialize(URL location, ResourceBundle resources) {
leaveLobbyButton.setOnMouseReleased(event -> leaveLobby());
Platform.runLater(() -> {
Integer max = 6;
for (int i = 0; i < max; i++) {
VBox pane = null;
FXMLLoader loader = new FXMLLoader(
getClass().getResource("/views/cells/PlayerCell.fxml"));
serverName.setText(ViewManager.getInstance().getProperty("serverName"));
mapName.setText(ViewManager.getInstance().getProperty("mapName"));
loader.setController(new PlayerCell("Player " + i));
ViewManager.getInstance().getPlayerList().addListener((ListChangeListener<String>) c -> {
Platform.runLater(this::refreshPlayerList);
});
try {
pane = loader.load();
} catch (IOException e) {
e.printStackTrace();
}
playerListVBox.getChildren().add(pane);
}
ViewManager.getInstance().getPlayerList().setAll(ViewManager.getInstance().getPlayerList().sorted());
});
Platform.runLater(() -> {
FXMLLoader dialogContent = new FXMLLoader(getClass().getResource(
"/views/dialogs/BoatCustomizeDialog.fxml"));
"/views/dialogs/BoatCustomizeDialog.fxml"));
try {
JFXDialog dialog = new JFXDialog(serverListMainStackPane, dialogContent.load(),
DialogTransition.CENTER);
DialogTransition.CENTER);
customizeButton.setOnAction(action -> dialog.show());
} catch (IOException e) {
e.printStackTrace();
@@ -65,4 +75,35 @@ public class LobbyController implements Initializable {
});
}
private void refreshPlayerList() {
playerListVBox.getChildren().clear();
for (String player : ViewManager.getInstance().getPlayerList()) {
VBox pane = null;
FXMLLoader loader = new FXMLLoader(
getClass().getResource("/views/cells/PlayerCell.fxml"));
loader.setController(new PlayerCell(player));
try {
pane = loader.load();
} catch (IOException e) {
e.printStackTrace();
}
playerListVBox.getChildren().add(pane);
}
}
public void leaveLobby() {
// TODO: 10/07/17 wmu16 - Finish function!
GameState.setCurrentStage(GameStages.CANCELLED);
// for (LobbyController_old.LobbyCloseListener readyListener : lobbyListeners)
// readyListener.notify(LobbyController_old.CloseStatus.LEAVE);
//TODO close threads and figure out what the above lines do;
ViewManager.getInstance().goToStartView();
}
}
@@ -5,6 +5,8 @@ import com.jfoenix.controls.JFXDecorator;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import com.jfoenix.controls.JFXTextField;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
@@ -13,58 +15,59 @@ import javafx.scene.control.Label;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import seng302.gameServer.ServerDescription;
public class ServerCell implements Initializable {
@FXML
private Label serverName;
//--------FXML BEGIN--------//
//Layout
@FXML
private GridPane serverListCell;
//Server Information
@FXML
private Label serverName;
@FXML
private Label mapName;
@FXML
private Label serverPlayerCount;
//Server Connection
@FXML
private JFXButton serverConnButton;
//---------FXML END---------//
private String name;
private String mapNameString;
private Integer currPlayerCount;
private String hostName;
private Integer portNumber;
public ServerCell(String name) {
this.name = name;
public ServerCell(ServerDescription server) {
this.name = server.getName();
this.currPlayerCount = server.spacesLeft();
this.mapNameString = server.getMapName();
this.hostName = server.getAddress();
this.portNumber = server.portNumber();
}
public void initialize(URL location, ResourceBundle resources) {
serverName.setText(name);
serverPlayerCount.setText(Integer.toString(currPlayerCount));
DropShadow dropShadow = new DropShadow();
dropShadow.setRadius(10.0);
dropShadow.setOffsetX(3.0);
dropShadow.setOffsetY(4.0);
dropShadow.setColor(Color.color(0, 0, 0, 0.1));
serverListCell.setEffect(dropShadow);
DropShadow dropShadow2 = new DropShadow();
dropShadow2.setRadius(10.0);
dropShadow2.setOffsetX(5.0);
dropShadow2.setOffsetY(6.0);
dropShadow2.setColor(Color.color(0, 0, 0, 0.3));
serverListCell.setOnMouseEntered(event -> {
serverListCell.setEffect(dropShadow2);
});
serverListCell.setOnMouseExited(event -> {
serverListCell.setEffect(dropShadow);
});
serverConnButton.setOnMouseReleased(event -> joinServer());
}
public void createServer() {
JFXDecorator decorator = (JFXDecorator) serverConnButton.getScene().getRoot();
public void joinServer() {
// TODO: 7/09/17 ajm412: Connect to a server here with the values stored in the hostName/portNumber variables.
System.out.println("Connecting to " + serverName.getText());
FXMLLoader fxmlLoader = new FXMLLoader();
try {
Parent root = FXMLLoader.load(StartScreenController.class.getResource("/views/LobbyView.fxml"));
decorator.setContent(root);
ViewManager.getInstance().setScene(root);
} catch (IOException e) {
e.printStackTrace();
}
@@ -6,48 +6,48 @@ import com.jfoenix.controls.JFXSlider;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import com.jfoenix.controls.JFXTextField;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import seng302.gameServer.ServerDescription;
public class ServerCreationController implements Initializable {
//--------FXML BEGIN--------//
@FXML
private JFXButton submitBtn;
private JFXTextField serverName;
@FXML
private JFXSlider maxPlayers;
@FXML
private Label maxPlayersLabel;
public ServerCreationController() {
}
@FXML
private JFXButton submitBtn;
//---------FXML END---------//
public void initialize(URL location, ResourceBundle resources) {
updateMaxPlayerLabel();
maxPlayers.valueProperty().addListener((observable, oldValue, newValue) -> {
updateMaxPlayerLabel();
});
submitBtn.setOnMouseReleased(event -> createServer());
}
public void createServer() {
System.out.println(submitBtn.getScene().getRoot());
JFXDecorator decorator = (JFXDecorator) submitBtn.getScene().getRoot();
System.out.println(decorator.getChildren());
StackPane stackPane = (StackPane) decorator.getChildren().get(1);
FXMLLoader fxmlLoader = new FXMLLoader();
try {
Parent root = FXMLLoader.load(StartScreenController.class.getResource("/views/LobbyView.fxml"));
ServerDescription serverDescription = ViewManager.getInstance().getGameClient().runAsHost("localhost", 4941);
ViewManager.getInstance().getGameClient().runAsHost("localhost", 4941);
ViewManager.getInstance().setProperty("serverName", serverDescription.getName());
ViewManager.getInstance().setProperty("mapName", serverDescription.getMapName());
Parent root = FXMLLoader.load(StartScreenController.class.getResource("/views/LobbyView.fxml"));
ViewManager.getInstance().setScene(root);
} catch (IOException e) {
@@ -5,7 +5,9 @@ import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXDialog.DialogTransition;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
import com.jfoenix.controls.JFXTextField;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
@@ -13,42 +15,49 @@ import javafx.fxml.Initializable;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import seng302.gameServer.ServerDescription;
import seng302.visualiser.ServerListener;
import seng302.visualiser.ServerListenerDelegate;
public class ServerListController implements Initializable {
public class ServerListController implements Initializable, ServerListenerDelegate {
//--------FXML BEGIN--------//
// Layout Related
@FXML
private VBox serverListVBox;
@FXML
private ScrollPane serverListScrollPane;
@FXML
private StackPane serverListMainStackPane;
// Host Button
@FXML
private JFXButton serverListHostButton;
private void refreshServerList(){
//Direct Connect
@FXML
private JFXButton connectButton;
@FXML
private JFXTextField serverHostName;
@FXML
private JFXTextField serverPortNumber;
//---------FXML END---------//
}
private Logger logger = LoggerFactory.getLogger(ServerListController.class);
public void initialize(URL location, ResourceBundle resources) {
serverListVBox.minWidthProperty().bind(serverListScrollPane.widthProperty());
// for (int i = 0; i < 20; i++) {
// VBox pane = null;
//
// FXMLLoader loader = new FXMLLoader(
// getClass().getResource("/views/cells/ServerCell.fxml"));
//
// loader.setController(new ServerCell("Server " + i));
//
// try {
// pane = loader.load();
// } catch (IOException e) {
// e.printStackTrace();
// }
//
// serverListVBox.getChildren().add(pane);
// }
connectButton.setOnMouseReleased(event -> goToDirectConnectLobby());
try {
ServerListener.getInstance().setDelegate(this);
} catch (IOException e) {
logger.warn("Could not start Server Listener Delegate");
}
Platform.runLater(() -> {
FXMLLoader dialogContent = new FXMLLoader(getClass().getResource(
@@ -59,8 +68,49 @@ public class ServerListController implements Initializable {
DialogTransition.CENTER);
serverListHostButton.setOnAction(action -> dialog.show());
} catch (IOException e) {
e.printStackTrace();
logger.warn("Could not create Server Creation Dialog.");
}
});
}
private void goToDirectConnectLobby() {
// TODO: 7/09/17 ajm412: Implement ability to connect to a lobby.
serverHostName.setText("Invalid Host Name or Port Number");
serverPortNumber.setText("");
}
@Override
public void serverRemoved(List<ServerDescription> servers) {
Platform.runLater(() -> refreshServers(servers));
}
@Override
public void serverDetected(ServerDescription serverDescription, List<ServerDescription> servers) {
Platform.runLater(() -> refreshServers(servers));
}
private void refreshServers(List<ServerDescription> servers) {
// TODO: 7/09/17 ajm412: Add some way to force a refresh.
// TODO: 7/09/17 ajm412: Add something for No Servers Found.
serverListVBox.getChildren().clear();
// Populate the server list with a series of server cell objects.
for (ServerDescription server : servers){
VBox pane = null;
FXMLLoader loader = new FXMLLoader(
getClass().getResource("/views/cells/ServerCell.fxml"));
loader.setController(new ServerCell(server));
try {
pane = loader.load();
} catch (IOException e) {
e.printStackTrace();
}
serverListVBox.getChildren().add(pane);
}
}
}
@@ -36,7 +36,7 @@ import java.util.Enumeration;
import java.util.List;
import java.util.ResourceBundle;
public class StartScreenController implements Initializable {
public class StartScreenController implements Initializable{
@FXML
private Label headText;
@@ -47,38 +47,8 @@ public class StartScreenController implements Initializable {
private Node serverList;
private Logger logger = LoggerFactory.getLogger(StartScreenController.class);
public void initialize(URL url, ResourceBundle resourceBundle) {
// gameClient = new GameClient(holder);
try {
ServerListener.getInstance().setDelegate(this);
} catch (IOException e) {
e.printStackTrace();
}
joinLobbyButton.setOnAction(event -> joinLobbyClicked());
}
//
// /**
// * Loads the fxml content into the parent pane
// * @param jfxUrl
// * @return the controller of the fxml
// */
// private Object setContentPane(String jfxUrl) {
// try {
// AnchorPane contentPane = (AnchorPane) startScreen2.getParent();
// contentPane.getChildren().removeAll();
// contentPane.getChildren().clear();
// contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString());
// FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(jfxUrl));
// contentPane.getChildren().addAll((Pane) fxmlLoader.load());
//
// return fxmlLoader.getController();
// } catch (IOException e) {
// e.printStackTrace();
// }
// return null;
// }
private List<ServerDescription> servers;
private void setInitialDropShadow(){
DropShadow dropShadow = new DropShadow();
@@ -114,5 +84,8 @@ public class StartScreenController implements Initializable {
setInitialDropShadow();
preloadServerListView();
}
}
@@ -1,16 +1,25 @@
package seng302.visualiser.controllers;
import com.jfoenix.controls.JFXDecorator;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import seng302.visualiser.GameClient;
import java.io.IOException;
import java.util.HashMap;
public class ViewManager {
private static ViewManager instance;
private GameClient gameClient;
private JFXDecorator decorator;
private HashMap<String, String> props; //TODO is this the best way to do this??
private ObservableList<String> playerList;
private ViewManager(){
props = new HashMap<>();
gameClient = new GameClient(decorator);
}
@@ -34,8 +43,33 @@ public class ViewManager {
decorator.setContent(scene);
}
public void goToStartView() {
try {
Parent root = FXMLLoader.load(getClass().getResource("/views/StartScreenView.fxml"));
this.setScene(root);
} catch (IOException e) {
e.printStackTrace();
}
}
public GameClient getGameClient(){
return gameClient;
}
public String getProperty(String key){
return props.get(key);
}
public void setProperty(String key, String val){
props.put(key, val);
}
public void setPlayerList(ObservableList<String> playerList) {
this.playerList = playerList;
}
public ObservableList<String> getPlayerList(){
return playerList;
}
}