Skip to content

Commit

Permalink
Implemented a GUI for the Server.
Browse files Browse the repository at this point in the history
Server Owner can now also decide which Port he wants to open for hosting the Service. Configuration File will also be saved for convenience. Also added the possibility to start the server via. command line, check the ReadMe for more information about it.
  • Loading branch information
DManstrator committed Sep 12, 2018
1 parent 3cce1cf commit b28f417
Show file tree
Hide file tree
Showing 10 changed files with 436 additions and 164 deletions.
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@
A networking Version of Hangman.

## How to use
1. Go to the [Releases-Tab](../../releases) and download at least the Client (**hangman_client.jar**). When you want **to host**, you should also get the **hangman_server.jar**. Put the file(s) into a folder wherever you want but **don't let them in the Downloads Folder** since the Client will create a configuration file in that folder.
2. For the Host: Double-click the hangman_server.jar. It won't open anything (as of now) and if you want to close it, just go to the Task Manager -> Processes and look for "javaw.exe". When you scroll to the right, you should see "hangman_server.jar" in the Command Line Column.<br />Make sure to tell you friend your IP address so that he can join your server. To get your IP: Just search for your IP address online ([this site](http://www.myipaddress.com/show-my-ip-address/) is one of the sites which will give you your IP address). You will also need to open a port in your router, else nobody can connect to your PC from outside (which is also good but one uncommon port shouldn't be dangerous). Just google for your Wi-Fi Router and how to open Ports.
1. Go to the [Releases-Tab](../../releases) and download at least the Client (**hangman_client.jar**). When you want **to host**, you should also get the **hangman_server.jar**. Put the file(s) into a folder wherever you want but **don't let them in the Downloads Folder** since both the Client and the Server will create a configuration file in that folder.

2. For the Host: Double-click the hangman_server.jar. Make sure to tell you friend your IP address and the Port you have chosen so that he can join your server. To get your IP: Just search for your IP address online ([this site](http://www.myipaddress.com/show-my-ip-address/) is one of the sites which will give you your IP address). You will also need to open a port in your router, else nobody can connect to your PC from outside (which is also good but one uncommon port shouldn't be dangerous). Just google for your Wi-Fi Router and how to open Ports.<br />If you are experienced, you can host the Server without a GUI by typing `java -jar hangman_server.jar <<port>>` into a Command Line.

3. For the Client: Just double click the hangman_client.jar, it will open a little fancy GUI for you. For the first use, you must set a few things like your nickname. Let me explain the values:<br />- "Name" is a Nickname you want to use, feel free to be as creative as you want but a few names are locked for obvious reasons.<br />- "Server IP" is the IP-Address of the Server, you can't choose that and you need to get it from your friend or a public host service.<br />- "Server Port" is a number which will be used that nobody can join a Server by accident.<br />If you want to know more about Ports, read the FAQ or google for it, it's really interesting!<br /><br />When you are done, click "Save & Return" and now you can join the Server.

## Pictures
Here some pictures that you know how the GUI looks like:<br />
![Main Menu on start](img/main-menu_start.png)<br />
Here some pictures that you know how the GUI looks like:

### Client
![Main Menu on Client Start](img/main-menu_start.png)<br />
![Setting your User Profile](img/user-profile.png)<br />
![Inputs will be checked](img/input-validator.png)<br />
![Game is ready to go](img/main-menu_startable.png)

### Server
![Main Menu on Server Start](img/server-menu.png)<br />
![Server is running](img/server-info.png)

## FAQ
- Q: How to play?<br />
A: Read the text above. ;)
Expand Down
Binary file added img/server-info.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/server-menu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 7 additions & 2 deletions src/tk/dmanstrator/hangman/client/ClientConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
*/
public class ClientConfiguration {

/**
* Name of Configuration File.
*/
private final static String CONFIGNAME = "config.json";

/**
* (Nick)name of the Client.
*/
Expand Down Expand Up @@ -44,7 +49,7 @@ public class ClientConfiguration {
public ClientConfiguration() {
String fileContent = "";
try {
fileContent = Files.readAllLines(Paths.get("config.json")).stream().collect(Collectors.joining(System.lineSeparator()));
fileContent = Files.readAllLines(Paths.get(CONFIGNAME)).stream().collect(Collectors.joining(System.lineSeparator()));
} catch (IOException e) {
}
if (!fileContent.isEmpty()) {
Expand Down Expand Up @@ -78,7 +83,7 @@ public ClientConfiguration(String name, String ipAddr, int port) {
config.put("server_ip", ipAddr);
config.put("server_port", port);

File file = new File("config.json");
File file = new File(CONFIGNAME);
try {
file.createNewFile();
FileWriter fileWriter = new FileWriter(file);
Expand Down
12 changes: 11 additions & 1 deletion src/tk/dmanstrator/hangman/client/ClientStart.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;

/**
Expand All @@ -16,6 +17,11 @@
*
*/
public class ClientStart implements Runnable {

/**
* Amount of milliseconds to wait before a Timeout occures.
*/
private final static int TIMEOUT = 2500;

/**
* Name of the player.
Expand Down Expand Up @@ -47,7 +53,7 @@ public ClientStart(HangmanClient hangmanClient, ClientConfiguration config) {
boolean worked = false; // lazy workaround
try {
socket = new Socket();
socket.connect(new InetSocketAddress(ipAddr, port), 2500);
socket.connect(new InetSocketAddress(ipAddr, port), TIMEOUT);
worked = true;
} catch (SocketTimeoutException ex) {
hangmanClient.cancelGui();
Expand Down Expand Up @@ -98,6 +104,10 @@ public void run() {
while (true) {
try {
receive();
} catch (SocketException ex) {
System.out.println("Server was shut down!");
// TODO inform client that Server shut down
System.exit(-1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Expand Down
139 changes: 9 additions & 130 deletions src/tk/dmanstrator/hangman/client/HangmanClient.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
package tk.dmanstrator.hangman.client;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.scene.Scene;
Expand All @@ -23,9 +18,8 @@
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.TextAlignment;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import tk.dmanstrator.hangman.utils.GuiUtils;

/**
* One of the two Main-Programs of the Hangman Game, starts a new Client.
Expand All @@ -35,11 +29,6 @@
*/
public class HangmanClient extends Application {

/**
* List of forbidden names.
*/
private static final List<String> FORBIDDEN_NAMES = Arrays.asList("Hitler");

/**
* Actual Client which has a Connection to the Server.
*/
Expand Down Expand Up @@ -102,6 +91,8 @@ public static void main(String[] args) {
@Override
public void start(Stage primaryStage) throws Exception {
// Main Layout
VBox mainLayout = new VBox(20);

Label mainWelcomeLabel = new Label("Welcome!");
mainWelcomeLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 15px;");

Expand All @@ -117,8 +108,6 @@ public void start(Stage primaryStage) throws Exception {
connectButton.setDisable(true);
}

VBox mainLayout = new VBox(20);

HBox mainButtons = new HBox(5);
mainButtons.getChildren().addAll(connectButton, profileButton);
mainButtons.setAlignment(Pos.CENTER);
Expand Down Expand Up @@ -186,17 +175,18 @@ public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Hangman-Multiplayer");
});
saveButton.setOnAction(e -> {
GuiUtils guiUtils = new GuiUtils();
String name = nameField.getText();
String ipAddr = ipField.getText();
String port = portField.getText();
String errorResponse = verify(name, ipAddr, port);
String errorResponse = guiUtils.verify(name, ipAddr, port);
if (errorResponse == null) {
config = new ClientConfiguration(name, ipAddr, Integer.parseInt(port));
connectButton.setDisable(false);
primaryStage.setScene(mainScene);
primaryStage.setTitle("Hangman-Multiplayer");
} else {
alert(errorResponse);
guiUtils.alert(errorResponse);
}
});

Expand Down Expand Up @@ -233,122 +223,11 @@ public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Hangman-Multiplayer");
primaryStage.show();

primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent t) {
Platform.exit();
System.exit(0);
}
primaryStage.setOnCloseRequest(t -> {
Platform.exit();
System.exit(0);
});
}

/**
* Verifies the User Input
* @param name Name to check
* @param ip IP to check
* @param port Port to check
* @return <code>null</code> if all the data is formally correct, else returns an Error Message
*/
private String verify(String name, String ip, String port) {
if (name.trim().isEmpty() || ip.trim().isEmpty() || port.trim().isEmpty()) {
return "You have to fill in every value!";
}

// check if name is not allowed
if (FORBIDDEN_NAMES.contains(name)) {
return "That name is not allowed!";
}

// check if IP is formally correct
if (!validIp(ip)) {
return "IP-Address is not valid!";
}

// check if port is legitimate
try {
int portAsInt = Integer.parseInt(port);
if (portAsInt > 65535) {
return "The Port Number is not in range!";
} else if (portAsInt > 49151) {
return "The Port Number is in a reserved area (from 49152 up to 65535) and cannot be used!";
} else if (portAsInt < 1024 || portAsInt == 1080) {
return "You shouldn't use this number as a port for a good reason!"
+ System.lineSeparator() + "Use something from 1024 up to 49151 instead.";
}
} catch (NumberFormatException ex) {
return "The port has to be a number!";
}

return null;
}

/**
* Validates an IPv4 address. Returns true if valid.
*
* @param ip The IPv4 address to validate
* @return true if the argument contains a valid IPv4 address
*/
private boolean validIp(String ip) {
Pattern pattern = Pattern.compile("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$");
Matcher matcher = pattern.matcher(ip);

if (matcher.matches()) {
for (int c = 1; c <= matcher.groupCount(); c++) {
String ipSegment = matcher.group(c);
if (ipSegment == null || ipSegment.length() == 0) {
return false;
}

int iIpSegment = 0;

try {
iIpSegment = Integer.parseInt(ipSegment);
} catch (NumberFormatException e) {
return false;
}

if (iIpSegment > 255) {
return false;
}

if (ipSegment.length() > 1 && ipSegment.startsWith("0")) {
return false;
}
}
} else {
return false;
}

return true;
}

/**
* Opens an AlertBox to show the User that his input was not correct.
* @param errorResponse Additional Error Response giving the User more information
*/
private void alert(String errorResponse) {
Stage window = new Stage();
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle("Incorrect Input!");
window.setMinWidth(250);

Label label = new Label("Please re-check your input, it was wrong!");
Label info = new Label(errorResponse);
info.setWrapText(true);
info.setStyle("-fx-font-weight: bold; -fx-font-size: 15px; -fx-text-align: center;");
info.setTextAlignment(TextAlignment.CENTER);

Button closeButton = new Button("Close");
closeButton.setOnAction(e -> window.close());

VBox layout = new VBox(10);
layout.getChildren().addAll(label, info, closeButton);
layout.setAlignment(Pos.CENTER);

Scene scene = new Scene(layout, 500, 150);
window.setScene(scene);
window.showAndWait();
}

void cancelGui() {
Scene scene = getScene("gameScene");
Expand Down
Loading

0 comments on commit b28f417

Please sign in to comment.