Merge branch 'Jonas_Stuff' into 'master'
Added a Class and Method that can reformat the terminal commands into commands... See merge request cs108-fs22/Gruppe-8!1
This commit is contained in:
commit
44893525fd
Binary file not shown.
@ -1,30 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.BudaClientServerStuff;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
|
||||
public class BudaClient {
|
||||
public static void main(String[] args) {
|
||||
Socket sock = null;
|
||||
try {
|
||||
sock = new Socket("localhost", 8090);
|
||||
OutputStream out= sock.getOutputStream();
|
||||
BufferedReader conin = new BufferedReader(new InputStreamReader(System.in));
|
||||
String line = ""; //this String is the line that will be sent to the server
|
||||
while (true) {
|
||||
line = conin.readLine();
|
||||
out.write(line.getBytes());
|
||||
if (line.equalsIgnoreCase("Quitx")) {
|
||||
break;
|
||||
}
|
||||
//line.startsWith() //todo: automatically handle name lengths
|
||||
//TODO: Implement inputStream in.
|
||||
}
|
||||
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,66 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.BudaClientServerStuff;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
public class BudaClientThread implements Runnable {
|
||||
int number;
|
||||
Socket socket;
|
||||
String name;
|
||||
|
||||
|
||||
public BudaClientThread(int number, Socket socket) {
|
||||
this.number = number;
|
||||
this.socket = socket;
|
||||
name = "";
|
||||
}
|
||||
|
||||
public void run() {
|
||||
System.out.println("Connection " + number + " established.");
|
||||
try {
|
||||
InputStream in = socket.getInputStream();
|
||||
OutputStream out = socket.getOutputStream();
|
||||
byte[] command;
|
||||
String comString;
|
||||
while (true) {
|
||||
command = new byte[5];
|
||||
in.read(command); //BudaClientThread waits to receive a line from the inputstream.
|
||||
comString = new String(command);
|
||||
if (comString.equalsIgnoreCase("Quitx")) { //todo: do as switch.
|
||||
BudaServer.quit = true;
|
||||
System.out.println("I just set quit to true!");
|
||||
break;
|
||||
} else if (comString.equalsIgnoreCase("NAME:")) {
|
||||
setName(in);
|
||||
} else if (comString.equalsIgnoreCase("NAMES")) {
|
||||
printnames();
|
||||
} else {
|
||||
System.out.println("Client number " + number + " sent this message: \"" + comString + "\" and I'm not sure what it means.");
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void printnames() {
|
||||
for (BudaClientThread t: BudaServer.Clients) {
|
||||
System.out.println("user named "+ t.name + " is connected (#" + t.number + ")");
|
||||
}
|
||||
}
|
||||
|
||||
public void setName(InputStream in) throws IOException {
|
||||
String nameString = "";
|
||||
int i;
|
||||
while (true) {
|
||||
i = in.read();
|
||||
if (i == 46) break; //the name ends with a "."
|
||||
nameString = nameString + (char) i;
|
||||
}
|
||||
this.name = nameString;
|
||||
System.out.println("Client number " + number + " changed their name to: " + nameString);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.BudaClientServerStuff;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class BudaServer {
|
||||
public static boolean quit = false; //todo: meaningfully implement this
|
||||
public static HashSet<BudaClientThread> Clients = new HashSet<BudaClientThread>();
|
||||
static int connections = 0;
|
||||
|
||||
public static void main(String[] args) {
|
||||
ServerConnector ServC = new ServerConnector();
|
||||
Thread ServCThread = new Thread(ServC);
|
||||
ServCThread.start(); //the ServCThread listens for new connections so the server can do other things
|
||||
while (!quit) {
|
||||
//Main server stuff goes here
|
||||
}
|
||||
//ServCThread.stop(); //todo: find some alternative for this.
|
||||
System.out.println("stopping the main BudaServer thread.");
|
||||
System.out.println("Quitting after the next connection is made.");
|
||||
}
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
|
||||
public class ClientListener implements Runnable{
|
||||
private final Socket sock;
|
||||
|
||||
public ClientListener(Socket sock) {
|
||||
this.sock = sock;
|
||||
}
|
||||
|
||||
public void run(){
|
||||
byte[] command = new byte[5];
|
||||
String comString;
|
||||
|
||||
try {
|
||||
InputStream in = sock.getInputStream();
|
||||
in.read(command);
|
||||
System.out.println("Got a line!");
|
||||
comString = new String(command);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
This is a demo of some (basic) client / server functionality.
|
||||
Run BudaClient.java for the Client and BudaServer.java for the Server. Everything connects locally via port 8090
|
||||
|
||||
The client reads from the console input and sends that to the server. The Server generally reads messages in five characters (so a text-based protocol could be based on commands of five characters).
|
||||
|
||||
The server can connect to an arbitrary number of clients.
|
||||
|
||||
Type "Name:Jonas B." to change the client's name to Jonas B (the "." is where the name stops).
|
||||
|
||||
Type "Names" for the Server to display everyone who is connected along with their name (if they have set a name).
|
||||
|
||||
Typing "Quitx" should quit everything but I havent quite managed to implement that yet so just repeatedly use ctrl+c to quit everything.
|
||||
|
||||
-Jonas
|
||||
@ -1,29 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.BudaClientServerStuff;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
public class ServerConnector implements Runnable{
|
||||
public void run() {
|
||||
try {
|
||||
System.out.println(
|
||||
"Warte auf Verbindungen auf Port 8090...");
|
||||
ServerSocket servSock = new ServerSocket(8090);
|
||||
while (true) {
|
||||
Socket socket = servSock.accept();
|
||||
System.out.println("got a connection: socket " + BudaServer.connections + socket.toString());
|
||||
BudaClientThread newClientThread = new BudaClientThread(++BudaServer.connections, socket);
|
||||
BudaServer.Clients.add(newClientThread);
|
||||
Thread bCT = new Thread(newClientThread);
|
||||
bCT.start();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.out.println("server got an error");
|
||||
System.err.println(e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,10 @@
|
||||
package ch.unibas.dmi.dbis.cs108.Klassenstruktur;
|
||||
|
||||
public class Ghost extends Passenger {
|
||||
protected boolean isOG; //true if the Ghost is the original ghost.
|
||||
|
||||
public boolean getIsOG() {
|
||||
return isOG;
|
||||
}
|
||||
protected boolean isOG; //true if the Ghost is the original ghost.
|
||||
|
||||
public boolean getIsOG() {
|
||||
return isOG;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,22 +1,25 @@
|
||||
package ch.unibas.dmi.dbis.cs108.Klassenstruktur;
|
||||
|
||||
public class GhostNPC extends Ghost{
|
||||
public class GhostNPC extends Ghost {
|
||||
|
||||
/**
|
||||
* Creates a new GhostNPC. Should be used at game start or if a HumanNPC is turned into a ghost.
|
||||
* @param position position on the train
|
||||
* @param name player name. if null, then a default name is used.
|
||||
* @param isOG true if the ghost is the original ghost.
|
||||
*/
|
||||
public GhostNPC(int position, String name, boolean isOG) {
|
||||
this.isOG = isOG;
|
||||
this.position = position;
|
||||
this.clientHandler = null;
|
||||
isGhost = true;
|
||||
isPlayer = false;
|
||||
kickedOff = false;
|
||||
if (name == null) {
|
||||
this.name = "Robot Nr. " + position;
|
||||
} else this.name = name;
|
||||
}
|
||||
/**
|
||||
* Creates a new GhostNPC. Should be used at game start or if a HumanNPC is turned into a ghost.
|
||||
*
|
||||
* @param position position on the train
|
||||
* @param name player name. if null, then a default name is used.
|
||||
* @param isOG true if the ghost is the original ghost.
|
||||
*/
|
||||
public GhostNPC(int position, String name, boolean isOG) {
|
||||
this.isOG = isOG;
|
||||
this.position = position;
|
||||
this.clientHandler = null;
|
||||
isGhost = true;
|
||||
isPlayer = false;
|
||||
kickedOff = false;
|
||||
if (name == null) {
|
||||
this.name = "Robot Nr. " + position;
|
||||
} else {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,28 +2,32 @@ package ch.unibas.dmi.dbis.cs108.Klassenstruktur;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.server.ClientHandler;
|
||||
|
||||
public class GhostPlayer extends Ghost{
|
||||
public class GhostPlayer extends Ghost {
|
||||
|
||||
/**
|
||||
* Creates a new GhostPlayer. Should be used at game start or if a HumanPlayer is turned into a ghost.
|
||||
* @param position position on the train
|
||||
* @param name name. if null, then a default name is used.
|
||||
* @param isOG true if the ghost is the original ghost.
|
||||
*/
|
||||
public GhostPlayer(int position, String name, ClientHandler clientHandler, boolean isOG) {
|
||||
this.position = position;
|
||||
this.clientHandler = clientHandler;
|
||||
this.isOG = isOG;
|
||||
isGhost = true;
|
||||
isPlayer = true;
|
||||
kickedOff = false;
|
||||
if (name == null) {
|
||||
this.name = "Player Nr. " + position;
|
||||
} else this.name = name;
|
||||
/**
|
||||
* Creates a new GhostPlayer. Should be used at game start or if a HumanPlayer is turned into a
|
||||
* ghost.
|
||||
*
|
||||
* @param position position on the train
|
||||
* @param name name. if null, then a default name is used.
|
||||
* @param isOG true if the ghost is the original ghost.
|
||||
*/
|
||||
public GhostPlayer(int position, String name, ClientHandler clientHandler, boolean isOG) {
|
||||
this.position = position;
|
||||
this.clientHandler = clientHandler;
|
||||
this.isOG = isOG;
|
||||
isGhost = true;
|
||||
isPlayer = true;
|
||||
kickedOff = false;
|
||||
if (name == null) {
|
||||
this.name = "Player Nr. " + position;
|
||||
} else {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void send(String msg) {
|
||||
//todo(Jonas): pass message along to client.
|
||||
}
|
||||
public void send(String msg) {
|
||||
//todo(Jonas): pass message along to client.
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
package ch.unibas.dmi.dbis.cs108.Klassenstruktur;
|
||||
|
||||
public class Human extends Passenger {
|
||||
|
||||
}
|
||||
|
||||
@ -1,20 +1,23 @@
|
||||
package ch.unibas.dmi.dbis.cs108.Klassenstruktur;
|
||||
|
||||
public class HumanNPC extends Human {
|
||||
/**
|
||||
* Creates a new HumanNPC.
|
||||
* @param position position on the train
|
||||
* @param name player name. if null, then a default name is used.
|
||||
*
|
||||
*/
|
||||
public HumanNPC(int position, String name) {
|
||||
this.position = position;
|
||||
this.clientHandler = null;
|
||||
isGhost = false;
|
||||
isPlayer = false;
|
||||
kickedOff = false;
|
||||
if (name == null) {
|
||||
this.name = "Robot Nr. " + position;
|
||||
} else this.name = name;
|
||||
|
||||
/**
|
||||
* Creates a new HumanNPC.
|
||||
*
|
||||
* @param position position on the train
|
||||
* @param name player name. if null, then a default name is used.
|
||||
*/
|
||||
public HumanNPC(int position, String name) {
|
||||
this.position = position;
|
||||
this.clientHandler = null;
|
||||
isGhost = false;
|
||||
isPlayer = false;
|
||||
kickedOff = false;
|
||||
if (name == null) {
|
||||
this.name = "Robot Nr. " + position;
|
||||
} else {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,22 +2,27 @@ package ch.unibas.dmi.dbis.cs108.Klassenstruktur;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.server.ClientHandler;
|
||||
|
||||
public class HumanPlayer extends Human{
|
||||
/**
|
||||
* Creates a new GhostPlayer. Should be used at game start or if a HumanPlayer is turned into a ghost.
|
||||
* @param position position on the train
|
||||
* @param name name. if null, then a default name is used.
|
||||
*/
|
||||
public HumanPlayer(int position, String name, ClientHandler clientHandler, boolean isOG) {
|
||||
this.position = position;
|
||||
this.clientHandler = clientHandler;
|
||||
isGhost = false;
|
||||
isPlayer = true;
|
||||
kickedOff = false;
|
||||
if (name == null) {
|
||||
this.name = "Player Nr. " + position;
|
||||
} else this.name = name;
|
||||
public class HumanPlayer extends Human {
|
||||
|
||||
/**
|
||||
* Creates a new GhostPlayer. Should be used at game start or if a HumanPlayer is turned into a
|
||||
* ghost.
|
||||
*
|
||||
* @param position position on the train
|
||||
* @param name name. if null, then a default name is used.
|
||||
*/
|
||||
public HumanPlayer(int position, String name, ClientHandler clientHandler, boolean isOG) {
|
||||
this.position = position;
|
||||
this.clientHandler = clientHandler;
|
||||
isGhost = false;
|
||||
isPlayer = true;
|
||||
kickedOff = false;
|
||||
if (name == null) {
|
||||
this.name = "Player Nr. " + position;
|
||||
} else {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -3,67 +3,72 @@ package ch.unibas.dmi.dbis.cs108.Klassenstruktur;
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.server.ClientHandler;
|
||||
|
||||
public class Passenger {
|
||||
protected int position; //the player's Cabin number (0 to 5)
|
||||
protected String name; //the player's Name
|
||||
protected Boolean isGhost; //boolean regarding if the player is a ghost. Could probably be removed since ghost is a subclass but I'm keeping it in.
|
||||
protected Boolean isPlayer; //same here
|
||||
protected Boolean kickedOff; //true if the player has been voted off.
|
||||
protected ClientHandler clientHandler; //the socket for the client associated with this Passenger, for NPCs, this can be null.
|
||||
|
||||
/**
|
||||
* Sends a protocol message to the respective player.
|
||||
* @param msg the message that is sent to this player.
|
||||
**/
|
||||
public void send(String msg) {
|
||||
//todo: send protocol message to the respective client OR process messages for NPCS
|
||||
}
|
||||
protected int position; //the player's Cabin number (0 to 5)
|
||||
protected String name; //the player's Name
|
||||
protected Boolean isGhost; //boolean regarding if the player is a ghost. Could probably be removed since ghost is a subclass but I'm keeping it in.
|
||||
protected Boolean isPlayer; //same here
|
||||
protected Boolean kickedOff; //true if the player has been voted off.
|
||||
protected ClientHandler clientHandler; //the socket for the client associated with this Passenger, for NPCs, this can be null.
|
||||
|
||||
/**
|
||||
* sets the Position of this passenger
|
||||
* @param position the position of this passenger
|
||||
*/
|
||||
public void setPosition(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
/**
|
||||
* Sends a protocol message to the respective player.
|
||||
*
|
||||
* @param msg the message that is sent to this player.
|
||||
**/
|
||||
public void send(String msg) {
|
||||
//todo: send protocol message to the respective client OR process messages for NPCS
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the name of this passenger.
|
||||
* @param name the new name for this passenger.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
/**
|
||||
* sets the Position of this passenger
|
||||
*
|
||||
* @param position the position of this passenger
|
||||
*/
|
||||
public void setPosition(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the kickedOff status of this Passenger
|
||||
* @param kickedOff should be set to true if the passenger has been kicked off.
|
||||
*/
|
||||
public void setKickedOff(boolean kickedOff) {
|
||||
this.kickedOff = kickedOff;
|
||||
}
|
||||
/**
|
||||
* sets the name of this passenger.
|
||||
*
|
||||
* @param name the new name for this passenger.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
/**
|
||||
* sets the kickedOff status of this Passenger
|
||||
*
|
||||
* @param kickedOff should be set to true if the passenger has been kicked off.
|
||||
*/
|
||||
public void setKickedOff(boolean kickedOff) {
|
||||
this.kickedOff = kickedOff;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Boolean getIsGhost() {
|
||||
return isGhost;
|
||||
}
|
||||
public Boolean getIsGhost() {
|
||||
return isGhost;
|
||||
}
|
||||
|
||||
public Boolean getKickedOff() {
|
||||
return kickedOff;
|
||||
}
|
||||
public Boolean getKickedOff() {
|
||||
return kickedOff;
|
||||
}
|
||||
|
||||
public Boolean getIsPlayer() {
|
||||
return isPlayer;
|
||||
}
|
||||
public Boolean getIsPlayer() {
|
||||
return isPlayer;
|
||||
}
|
||||
|
||||
public ClientHandler getClientHandler() {
|
||||
return clientHandler;
|
||||
}
|
||||
public ClientHandler getClientHandler() {
|
||||
return clientHandler;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.Spiellogikentwurf;
|
||||
|
||||
public class Game {
|
||||
|
||||
/**
|
||||
* Can be extended for optional Game-settings
|
||||
**/
|
||||
protected int nrOfPlayers; //sets the length of the train
|
||||
protected int nrOfGhosts; // sets how many Ghosts we start witch
|
||||
protected int nrOfUsers; // safes how many clients are active in this Game
|
||||
protected GameFunctions gameFunctions;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a Game instance where:
|
||||
*
|
||||
* @param nrOfPlayers is the length of the Train
|
||||
* @param nrOfGhosts is the number of OG Ghosts you want to start with and
|
||||
* @param nrOfUsers is the number of active users at the time (non NPCs)
|
||||
*/
|
||||
Game(int nrOfPlayers, int nrOfGhosts, int nrOfUsers)
|
||||
throws TrainOverflow { //ToDo: Who handles Exception how and where
|
||||
this.nrOfPlayers = nrOfPlayers;
|
||||
this.nrOfGhosts = nrOfGhosts;
|
||||
this.nrOfUsers = nrOfUsers;
|
||||
this.gameFunctions = new GameFunctions(nrOfPlayers, nrOfGhosts, nrOfUsers);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Game game1 = new Game(6, 1, 1);
|
||||
for (int j = 0; j < game1.nrOfPlayers; j++) {
|
||||
System.out.println(game1.gameFunctions.passengerTrain[j].getPosition());
|
||||
}
|
||||
|
||||
} catch (TrainOverflow e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.Spiellogikentwurf;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.Klassenstruktur.Human;
|
||||
import ch.unibas.dmi.dbis.cs108.Klassenstruktur.Passenger;
|
||||
|
||||
public class GameFunctions {
|
||||
|
||||
/**
|
||||
* Can be extended for optional Game-settings
|
||||
**/
|
||||
int nrOfPlayers; //sets the length of the train
|
||||
int nrOfGhosts; // sets how many Ghosts we start witch
|
||||
int nrOfUsers; // safes how many clients are active in this Game
|
||||
Train train; // safes who sits where
|
||||
Passenger[] passengerTrain;
|
||||
|
||||
/**
|
||||
* Constructs a GameFunctions instance where nrOfPlayers >= nrOfUsers. Fills passengerTrain with
|
||||
* only humans
|
||||
*
|
||||
* @param nrOfPlayers is the length of the Train
|
||||
* @param nrOfGhosts is the number of OG Ghosts you want to start with and
|
||||
* @param nrOfUsers is the number of active users at the time (non NPCs)
|
||||
* @throws TrainOverflow if nrOfPlayers < nrOfUsers
|
||||
*/
|
||||
GameFunctions(int nrOfPlayers, int nrOfGhosts, int nrOfUsers)
|
||||
throws TrainOverflow { //ToDo: where will Exception be handled?
|
||||
this.nrOfPlayers = nrOfPlayers;
|
||||
this.nrOfGhosts = nrOfGhosts;
|
||||
this.nrOfUsers = nrOfUsers;
|
||||
this.train = new Train(nrOfPlayers, nrOfUsers);
|
||||
Passenger[] passengerTrain = new Passenger[nrOfPlayers]; //Creates an array with Passengers with correlation positions (Train)
|
||||
for (int i = 0; i < nrOfPlayers; i++) {
|
||||
Human h = new Human();
|
||||
h.setPosition(train.orderOfTrain[i]);
|
||||
passengerTrain[i] = h;
|
||||
}
|
||||
}
|
||||
|
||||
public int getNrOfGhosts() {
|
||||
return nrOfGhosts;
|
||||
}
|
||||
|
||||
public int getNrOfPlayers() {
|
||||
return nrOfPlayers;
|
||||
}
|
||||
|
||||
public int getNrOfUsers() {
|
||||
return nrOfUsers;
|
||||
}
|
||||
|
||||
public void ghostyfy(int position) {
|
||||
|
||||
}
|
||||
|
||||
public Passenger voteEval() {
|
||||
return new Passenger();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,79 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.Spiellogikentwurf;
|
||||
|
||||
public class Train {
|
||||
|
||||
int[] orderOfTrain; //gives the random order in which the passengers enter the train
|
||||
int positionOfGhost;
|
||||
|
||||
/**
|
||||
* Constructs a Train with orderOfTrain of the size nrOfPlayers, filled with a Random order of the
|
||||
* numbers 0-5. Puts the ghost approx in the middle of this order.
|
||||
*
|
||||
* @param nrOfPlayers sets how many Players fit in the Train
|
||||
* @param nrOfUsers sets how many of the Players are Users (vs NPCs)
|
||||
* @throws TrainOverflow if you want to play with to many users (Train is to small)
|
||||
*/
|
||||
Train(int nrOfPlayers, int nrOfUsers) throws TrainOverflow {
|
||||
|
||||
if (nrOfPlayers < nrOfUsers) {
|
||||
throw new TrainOverflow(); //ToDo: What kind of Exception must be thrown here and who handles it how?
|
||||
}
|
||||
|
||||
int[] userTrain = new int[nrOfPlayers];
|
||||
int[] check = new int[nrOfPlayers];
|
||||
int i = 0;
|
||||
int zeroCounter = 0;
|
||||
while (i < nrOfPlayers) {
|
||||
int randomNr = (int) ((Math.random() * ((nrOfPlayers)) + 0));
|
||||
if (randomNr == 0) {
|
||||
if (zeroCounter == 0) {
|
||||
i++;
|
||||
zeroCounter++;
|
||||
}
|
||||
}
|
||||
if (!isInArray(check, randomNr)) {
|
||||
userTrain[i] = randomNr;
|
||||
check[randomNr] = randomNr;
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
this.orderOfTrain = userTrain;
|
||||
this.positionOfGhost = nrOfPlayers / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the key is to be found in an array
|
||||
*
|
||||
* @param array the array to be searched
|
||||
* @param key the value searched for
|
||||
* @return true if and only if key is found
|
||||
*/
|
||||
static public boolean isInArray(int[] array, int key) {
|
||||
int i = 0;
|
||||
while (i < array.length) {
|
||||
if (array[i] == key) {
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int[] a = {1, 2, 3, 4, 5};
|
||||
System.out.println(isInArray(a, 0));
|
||||
//Test
|
||||
try {
|
||||
Train t = new Train(6, 1);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
System.out.print("|" + t.orderOfTrain[i] + "|");
|
||||
}
|
||||
System.out.println(" Ghost:" + t.positionOfGhost);
|
||||
|
||||
} catch (TrainOverflow e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.Spiellogikentwurf;
|
||||
|
||||
public class TrainOverflow extends Exception {
|
||||
|
||||
private static final String message = "Too many users are logged on";
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.example;
|
||||
|
||||
/**
|
||||
* A simple HelloWorld class.
|
||||
*/
|
||||
public class HelloWorld {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello World");
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.example.gui.javafx;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
/**
|
||||
* This is an example JavaFX-Application.
|
||||
*/
|
||||
public class GUI extends Application {
|
||||
|
||||
/**
|
||||
* Launching this method will not work on some platforms.
|
||||
* What you should do is to create a separate main class and launch the GUI class from there as is done in {@link Main}
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
launch(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Stage stage) {
|
||||
String javaVersion = System.getProperty("java.version");
|
||||
String javafxVersion = System.getProperty("javafx.version");
|
||||
Label l = new Label("Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + ".");
|
||||
Scene scene = new Scene(new StackPane(l), 640, 480);
|
||||
stage.setScene(scene);
|
||||
stage.show();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.example.gui.javafx;
|
||||
|
||||
import javafx.application.Application;
|
||||
|
||||
public class Main {
|
||||
|
||||
/**
|
||||
* This is simply a wrapper to launch the {@link GUI} class.
|
||||
* The reason this class exists is documented in {@link GUI#main(String[])}
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
Application.launch(GUI.class, args);
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.example.gui.swing;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
/**
|
||||
* This is an example Swing Application
|
||||
*/
|
||||
public class SwingGUI {
|
||||
|
||||
private static void createAndShowGUI() {
|
||||
// Make sure we have nice window decorations
|
||||
JFrame.setDefaultLookAndFeelDecorated(true);
|
||||
// Create and set up the window.
|
||||
JFrame frame = new JFrame("HelloWorldSwing");
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Add the ubiquitous "Hello World" label
|
||||
JLabel label = new JLabel("Hello World");
|
||||
frame.getContentPane().add(label);
|
||||
// Display the window
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Schedule a job for the event-dispatching thread: // creating and showing this application's GUI
|
||||
javax.swing.SwingUtilities.invokeLater(() -> createAndShowGUI());
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,19 +1,20 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.client;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NoLegalProtocolCommandStringFoundException;
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.server.NameGenerator;
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.ClientPinger;
|
||||
|
||||
import java.net.Socket;
|
||||
import java.io.*;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Scanner;
|
||||
|
||||
|
||||
public class Client {
|
||||
|
||||
private Socket socket;
|
||||
private BufferedReader in;
|
||||
private BufferedWriter out;
|
||||
public String userName;
|
||||
public ClientPinger clientPinger;
|
||||
|
||||
public Client(Socket socket, String userName) {
|
||||
try {
|
||||
@ -21,37 +22,32 @@ public class Client {
|
||||
this.out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
|
||||
this.in = new BufferedReader((new InputStreamReader((socket.getInputStream()))));
|
||||
|
||||
//TODO add the system based generated username here.
|
||||
//TODO hide connecting logik(next 4 lines)
|
||||
this.userName = userName;
|
||||
this.out.write(getUsername());
|
||||
this.out.newLine();
|
||||
this.out.flush();
|
||||
clientPinger = new ClientPinger(this.out, this.socket);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
closeEverything(socket, in, out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
public void sendMessage() {
|
||||
try {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
while (socket.isConnected()) {
|
||||
String msg = sc.nextLine();
|
||||
String encodedMsg = "";
|
||||
try {
|
||||
encodedMsg = encodeMessage(msg);
|
||||
} catch (NoLegalProtocolCommandStringFoundException e) {
|
||||
System.out.println("ERROR: no legal command found");
|
||||
encodedMsg = "";
|
||||
} catch (EmptyClientInputException e) {
|
||||
//Maybe this exception shouldn't do anything.
|
||||
} finally {
|
||||
out.write(encodedMsg);
|
||||
out.newLine();
|
||||
out.flush();
|
||||
}
|
||||
|
||||
|
||||
String formattedMSG = MessageFormatter.formatMsg(msg);
|
||||
out.write(formattedMSG);
|
||||
out.newLine();
|
||||
out.flush();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
@ -59,23 +55,10 @@ public class Client {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses <code>NTtBProtocolParser</code> to turn Client input into the NTtB Protocol format. Must
|
||||
* be called before a client input is sent to the server.
|
||||
*
|
||||
* @param msg the msg to be encoded.
|
||||
* @return Message encoded adhering to the NTtB Protocoll.
|
||||
*/
|
||||
private String encodeMessage(String msg)
|
||||
throws NoLegalProtocolCommandStringFoundException, EmptyClientInputException {
|
||||
NTtBProtocolParser pp = new NTtBProtocolParser(this);
|
||||
return pp.parseMsg(msg);
|
||||
}
|
||||
//TODO implement decoding of server input
|
||||
private String decodeServerMsg(String msg){return null;}
|
||||
|
||||
|
||||
/**
|
||||
* Listens for incoming messages
|
||||
* Starts a thread which listens for incoming messages
|
||||
*/
|
||||
public void chatListener() {
|
||||
/*TODO: what type of decoding has to be done
|
||||
@ -84,12 +67,13 @@ public class Client {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
String chatMsg;
|
||||
|
||||
while (socket.isConnected()) {
|
||||
try {
|
||||
chatMsg = in.readLine();
|
||||
System.out.println(chatMsg);
|
||||
parse(chatMsg);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
closeEverything(socket, in, out);
|
||||
@ -100,6 +84,29 @@ public class Client {
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the server, as is.
|
||||
* @param msg the message sent. Should already be protocol-formatted.
|
||||
*/
|
||||
public void sendMsgToServer(String msg) {
|
||||
try {
|
||||
out.write(msg);
|
||||
out.newLine();
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* parses a received message according to the client protocol.
|
||||
* @param msg the message to be parsed.
|
||||
*/
|
||||
public void parse(String msg) {
|
||||
JClientProtocolParser.parse(msg, this);
|
||||
}
|
||||
|
||||
public void closeEverything(Socket socket, BufferedReader in, BufferedWriter out) {
|
||||
//TODO Correctly closing a clients connection
|
||||
|
||||
@ -129,14 +136,17 @@ public class Client {
|
||||
} else {
|
||||
hostname = args[0];
|
||||
}
|
||||
System.out.println("Choose a nickname: ");
|
||||
String systemName = System.getProperty("user.name");
|
||||
System.out.println("Choose a nickname (Suggestion: " + systemName + "): ");
|
||||
String username = sc.next();
|
||||
Socket socket;
|
||||
try {
|
||||
socket = new Socket(hostname, 42069);
|
||||
Client client = new Client(socket, username);
|
||||
client.chatListener();
|
||||
client.sendMessage();
|
||||
Thread cP = new Thread(client.clientPinger);
|
||||
cP.start();
|
||||
client.sendMessage(); //this one blocks.
|
||||
} catch (UnknownHostException e) {
|
||||
System.out.println("Invalid host IP");
|
||||
} catch (IOException e) {
|
||||
@ -148,6 +158,4 @@ public class Client {
|
||||
public String getUsername() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.client;
|
||||
|
||||
public class EmptyClientInputException extends Exception {
|
||||
String exceptionMsg;
|
||||
Client whoDunIt;
|
||||
public EmptyClientInputException(Client whoDunIt) {
|
||||
this.whoDunIt = whoDunIt;
|
||||
this.exceptionMsg = whoDunIt.getUsername() + " tried to send an empty message";
|
||||
}
|
||||
|
||||
public String getExceptionMsg(){
|
||||
return exceptionMsg;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.client;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NightTrainProtocol;
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NoLegalProtocolCommandStringFoundException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class InputToProtocolMap {
|
||||
|
||||
private static final HashMap<String, NightTrainProtocol.NTtBCommands> encoding;
|
||||
private static final HashSet<String> legalClientInput;
|
||||
|
||||
static {
|
||||
//First add all legal commands to a map
|
||||
HashMap<String, NightTrainProtocol.NTtBCommands> builder = new HashMap<>();
|
||||
builder.put("chat", NightTrainProtocol.NTtBCommands.CHATA);
|
||||
builder.put("cn", NightTrainProtocol.NTtBCommands.CUSRN);
|
||||
builder.put("list", NightTrainProtocol.NTtBCommands.LISTP);
|
||||
builder.put("exit", NightTrainProtocol.NTtBCommands.LEAVG);
|
||||
//TODO extend according to extended function
|
||||
//Initialize static final map and set
|
||||
legalClientInput = new HashSet<>(builder.keySet());
|
||||
encoding = new HashMap<>(builder);
|
||||
}
|
||||
|
||||
public static String encode(String toEncode) throws NoLegalProtocolCommandStringFoundException {
|
||||
if (legalClientInput.contains(toEncode)) {
|
||||
return encoding.get(toEncode).toString();
|
||||
} else {
|
||||
throw new NoLegalProtocolCommandStringFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.client;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.server.ClientHandler;
|
||||
|
||||
public class JClientProtocolParser {
|
||||
|
||||
/**
|
||||
* Used by the client to parse an incoming protocol message.
|
||||
* @param msg the encoded message that needs to be parsed
|
||||
* @param c this Client(required so this method can access the Client's methods)
|
||||
*/
|
||||
public static void parse(String msg, Client c) {
|
||||
String header = ""; //"header" is the first 5 characters, i.e. the protocol part
|
||||
try {
|
||||
header = msg.substring(0, 5);
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
System.out.println("Received unknown command");
|
||||
}
|
||||
//System.out.println(header); helpful for debugging
|
||||
switch (header) {
|
||||
case "SPING":
|
||||
c.sendMsgToServer("PINGB");
|
||||
break;
|
||||
case "PINGB":
|
||||
c.clientPinger.setGotPingBack(true);
|
||||
break;
|
||||
case "CHATM":
|
||||
System.out.println(msg.substring(6));
|
||||
break;
|
||||
default:
|
||||
System.out.println("Received unknown command");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.client;
|
||||
|
||||
public class MessageFormatter {
|
||||
|
||||
/**
|
||||
* Takes a given Message and reformats it to where the JServerProtocolParser.parse() method can
|
||||
* handle it. May need to be redesigned one the games uses a GUI
|
||||
*
|
||||
* @param msg the Messaged to be reformatted
|
||||
* @return the reformatted message in the form HEADR$msg
|
||||
*/
|
||||
|
||||
public static String formatMsg(String msg) {
|
||||
String header = ""; //header is first two characters
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
String s; // just a friendly helper to save message in
|
||||
try {
|
||||
header = msg.substring(0, 2);
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
switch (header) {
|
||||
case "/c":
|
||||
stringBuilder.append("CHATA$");
|
||||
s = msg.substring(3);
|
||||
break;
|
||||
case "/q":
|
||||
stringBuilder.append("QUITS$");
|
||||
s = msg.substring(3);
|
||||
break;
|
||||
case "/n":
|
||||
stringBuilder.append("NAMEC$");
|
||||
s = msg.substring(3);
|
||||
break;
|
||||
default:
|
||||
s = msg;
|
||||
}
|
||||
stringBuilder.append(s);
|
||||
return stringBuilder.toString();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.client;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NoLegalProtocolCommandStringFoundException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Implements a protocol parser for the NTtB protocoll, that transforms client input into a server
|
||||
* readable format.
|
||||
*/
|
||||
public class NTtBProtocolParser implements ProtocolParser {
|
||||
|
||||
//TODO Possibly bad name, rename to clientMsgParser?
|
||||
public final Client caller;
|
||||
public static InputToProtocolMap legalCommands = new InputToProtocolMap();
|
||||
|
||||
|
||||
public NTtBProtocolParser(Client caller) {
|
||||
this.caller = caller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parseMsg(String msg)
|
||||
throws NoLegalProtocolCommandStringFoundException, EmptyClientInputException {
|
||||
Scanner sc = new Scanner(msg);
|
||||
ArrayList<String> input = new ArrayList<>();
|
||||
String parsedMsg;
|
||||
|
||||
while (sc.hasNext()) {
|
||||
input.add(sc.next());
|
||||
}
|
||||
return buildProtocolMsg(input);
|
||||
}
|
||||
|
||||
|
||||
private String buildProtocolMsg(ArrayList<String> input)
|
||||
throws EmptyClientInputException, NoLegalProtocolCommandStringFoundException {
|
||||
//TODO
|
||||
if (emptyClientInput(input)) {
|
||||
throw new EmptyClientInputException(caller);
|
||||
}
|
||||
StringBuilder s = new StringBuilder(); //friendly little helper
|
||||
s.append(InputToProtocolMap.encode(input.get(0)));
|
||||
if (containsParameters(input)) {
|
||||
int size = input.size();
|
||||
for (int i = 1; i < size; i++) {
|
||||
s.append("$");
|
||||
s.append(input.get(i).toLowerCase()); //parameters are always lower case (is that good?)
|
||||
}
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if input has parameters
|
||||
* <p>
|
||||
* if the list size is smaller than 2, i.e. not larger than 1, the input only contains a command.
|
||||
*
|
||||
* @param input the tokenized input string.
|
||||
* @return true if input list is larger than 2.
|
||||
*/
|
||||
private boolean containsParameters(ArrayList<String> input) {
|
||||
return input.size() > 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if client input is empty
|
||||
*
|
||||
* @param clientInput the clients input.
|
||||
* @return true if client didn't send any input besides whitespace
|
||||
*/
|
||||
private boolean emptyClientInput(ArrayList<String> clientInput) {
|
||||
return clientInput.isEmpty();
|
||||
}
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.client;
|
||||
|
||||
public interface ProtocolParser {
|
||||
|
||||
/**
|
||||
* Takes a String from client input and parses into server readable message.
|
||||
*
|
||||
* @param msg the message to be parsed
|
||||
* @return a String message formatted for the specific protocol
|
||||
*/
|
||||
String parseMsg(String msg) throws Exception;
|
||||
}
|
||||
@ -31,27 +31,27 @@ public class ClientPinger implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
while (socket.isConnected()) {
|
||||
gotPingBack = false;
|
||||
out.write("CPING");
|
||||
out.newLine();
|
||||
out.flush();
|
||||
Thread.sleep(2000);
|
||||
Thread.sleep(4000);
|
||||
if (gotPingBack) {
|
||||
if (!isConnected) { //if !isConnected, then the connection had been lost before.
|
||||
isConnected = true;
|
||||
System.out.println("Connection regained!");
|
||||
}
|
||||
} else {
|
||||
isConnected = false;
|
||||
System.out.println("Lost connection. Waiting to reconnect...");
|
||||
if (isConnected) {
|
||||
isConnected = false;
|
||||
System.out.println("Lost connection. Waiting to reconnect...");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
isConnected = false; //in case the socket accidentally disconnects (can this happen?)
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
isConnected = false; //in case the socket accidentally disconnects (can this happen?)
|
||||
} catch (InterruptedException | IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
Client commands:
|
||||
|
||||
Implemented:
|
||||
* CHATA$message Send chat message to all
|
||||
* QUITS quit server/ leave server
|
||||
* CPING Ping from client to server.
|
||||
* PINGB Pingback from client to server.
|
||||
* NAMEC$name Change name to whatever is specified
|
||||
|
||||
Future / planned:
|
||||
* CRTGM Create a new game
|
||||
* CHATW whisper chat
|
||||
* CHATG ghost chat
|
||||
* LEAVG leave a game
|
||||
* JOING join a game
|
||||
* VOTEG ghost voting who to infect
|
||||
* VOTEH humans voting who is the ghost
|
||||
* LISTP list players/clients in session with the Server
|
||||
|
||||
Server Commands:
|
||||
|
||||
Implemented:
|
||||
* SPING Ping from server to client
|
||||
* PINGB Pingback from client to server.
|
||||
|
||||
Future / planned:
|
||||
* MSGRS "Message received": Paramaters: a string detailing to the client that and what the server received as command.
|
||||
* SEROR Server had an error. (used for debugging)
|
||||
* NOCMD No command found.
|
||||
|
||||
|
||||
@ -31,26 +31,27 @@ public class ServerPinger implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
while (socket.isConnected()) {
|
||||
gotPingBack = false;
|
||||
out.write("SPING");
|
||||
out.newLine();
|
||||
out.flush();
|
||||
Thread.sleep(2000);
|
||||
Thread.sleep(4000);
|
||||
if (gotPingBack) {
|
||||
if (!isConnected) { //if !isConnected, then the connection had been lost before.
|
||||
isConnected = true;
|
||||
System.out.println("Connection regained!");
|
||||
}
|
||||
} else {
|
||||
isConnected = false;
|
||||
System.out.println("Lost connection. Waiting to reconnect...");
|
||||
if (isConnected) {
|
||||
isConnected = false;
|
||||
System.out.println("Lost connection. Waiting to reconnect...");
|
||||
}
|
||||
}
|
||||
}
|
||||
isConnected = false; //in case the socket accidentally disconnects (can this happen?)
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
} catch (InterruptedException | IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,50 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.protocol;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
/**
|
||||
* This class defines what type the ClientMsgDecoder returns after decoding the message. This is
|
||||
* done so the output can be split into a response to the client and action in to the game logik.
|
||||
* commands should map to methods(maybe classes) parameters map to method parameters
|
||||
*/
|
||||
|
||||
public class NTtBFormatMsg {
|
||||
|
||||
private String msgToClient;
|
||||
private NightTrainProtocol.NTtBCommands command;
|
||||
private final String[] parameters; //TODO maybe use array?
|
||||
|
||||
public NTtBFormatMsg(String msgToClient, NightTrainProtocol.NTtBCommands command,
|
||||
String[] parameters) {
|
||||
this.msgToClient = msgToClient;
|
||||
this.command = command;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public NTtBFormatMsg() {
|
||||
this.msgToClient = "";
|
||||
this.command = null;
|
||||
this.parameters = new String[]{""};
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return msgToClient;
|
||||
}
|
||||
|
||||
public NightTrainProtocol.NTtBCommands getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public String[] getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
protected void setMsgToClient(String msgToClient) {
|
||||
this.msgToClient = msgToClient;
|
||||
}
|
||||
|
||||
protected void setCommand(NightTrainProtocol.NTtBCommands command) {
|
||||
this.command = command;
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.protocol;
|
||||
|
||||
public interface NTtBInputType {
|
||||
String msg = null;
|
||||
public String getValue();
|
||||
public void setValue();
|
||||
|
||||
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.protocol;
|
||||
|
||||
public class NTtBParameter implements NTtBInputType {
|
||||
String parameterValue;
|
||||
|
||||
public NTtBParameter(String parameterValue) {
|
||||
this.parameterValue = parameterValue;
|
||||
}
|
||||
@Override
|
||||
public String getValue() {
|
||||
return parameterValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue() {
|
||||
//Possibly do not need
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* Client commands:
|
||||
* CRTGM: Create a new game
|
||||
* CHATA: chat to all
|
||||
* CHATW: whisper chat
|
||||
* CHATG: ghost chat
|
||||
* LEAVG: leave a game
|
||||
* JOING: join a game
|
||||
* VOTEG: ghost voting who to infect
|
||||
* VOTEH: humans voting who is the ghost
|
||||
* QUITS: quit server/ leave server
|
||||
* LISTP: list players/clients in session with the Server
|
||||
* CPING: Ping from client to server.
|
||||
*/
|
||||
/**
|
||||
Server Commands:
|
||||
* MSGRS: "Message received": Paramaters: a string detailing to the client that and what the server received as command.
|
||||
* SEROR: Server had an error. (used for debugging)
|
||||
* SPING: Ping from server to client;
|
||||
* NOCMD: Co command found.
|
||||
*/
|
||||
@ -1,66 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.protocol;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
/*
|
||||
The NightTrainProtocol implements the Communication-Protocol of the
|
||||
"Night Train to Budapest"" game. It acts as an Interface between Client and server. All Client Messages are
|
||||
piped through this protocol, in order for the Server to execute the correct action. It is used by the ClientHandler
|
||||
for this purpose.
|
||||
*/
|
||||
|
||||
public class NightTrainProtocol {
|
||||
//TODO: initialite the fields
|
||||
|
||||
private static HashMap<String, NTtBCommands> stringNTtBCommandsHashMap = initializeMapping();
|
||||
private static ProtocolValidator protocolValidator;
|
||||
private static HashSet<String> legalStrings = new HashSet<>(stringNTtBCommandsHashMap.keySet());
|
||||
|
||||
public enum NTtBCommands {
|
||||
//Client Commands
|
||||
CRTGM, CHATA, CHATW, CHATG, LEAVG, JOING, VOTEG, QUITS, LISTP, CUSRN,CPING,
|
||||
//Server Responses
|
||||
MSGRS, SEROR, SPING, NOCMD
|
||||
}
|
||||
|
||||
private static HashMap<String, NTtBCommands> initializeMapping(){
|
||||
HashMap<String, NTtBCommands> map = new HashMap<>();
|
||||
for(NTtBCommands cmd: NTtBCommands.values()) {
|
||||
map.put(cmd.toString(), cmd);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
//getters & setters
|
||||
|
||||
public static HashMap<String, NTtBCommands> getStringNTtBCommandsHashMap() {
|
||||
return stringNTtBCommandsHashMap;
|
||||
}
|
||||
|
||||
public static HashSet<String> getLegalStrings() {
|
||||
return legalStrings;
|
||||
}
|
||||
|
||||
//Utility Methods:
|
||||
/**
|
||||
* Validates a given string is a valid representation
|
||||
* of a protocol command
|
||||
* @param cmd, the string command to be validated
|
||||
* @return true if <code>cmd</code> is a valid command
|
||||
*/
|
||||
public static boolean isLegalCmdString(String cmd) {
|
||||
return legalStrings.contains(cmd);
|
||||
}
|
||||
|
||||
public static NTtBCommands getCmdEnumObject(String cmd) throws NoLegalProtocolCommandStringFoundException {
|
||||
if(isLegalCmdString(cmd)){
|
||||
return stringNTtBCommandsHashMap.get(cmd);
|
||||
} else {
|
||||
throw new NoLegalProtocolCommandStringFoundException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//TODO analyize what methods are needed
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.protocol;
|
||||
|
||||
public class NoLegalProtocolCommandStringFoundException extends Exception {
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.protocol;
|
||||
|
||||
public interface ProtocolDecoder {
|
||||
|
||||
public NTtBFormatMsg decodeMsg(String msg);
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.protocol;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
//TODO Possibly redundant!!
|
||||
|
||||
public class ProtocolValidator {
|
||||
|
||||
//TODO String or NTtBCommands HashSet?
|
||||
public static HashSet<NightTrainProtocol.NTtBCommands> legalCommands = initializeLegalCommands();
|
||||
|
||||
//Initialize the legalCommands set with the protocol values.
|
||||
private static HashSet<NightTrainProtocol.NTtBCommands> initializeLegalCommands(){
|
||||
EnumSet<NightTrainProtocol.NTtBCommands> enumVals = EnumSet.allOf(NightTrainProtocol.NTtBCommands.class);
|
||||
return new HashSet<>(enumVals);
|
||||
}
|
||||
|
||||
public boolean validateCommand(String s) {
|
||||
//TODO implement if needed
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,13 +1,21 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.server;
|
||||
|
||||
/* This class is built to contain the usernames of all players in a single string.
|
||||
/**
|
||||
* This class is built to contain the usernames of all players in a single string.
|
||||
* This allows a duplicate check (--> ClientHandler) when a new player chooses
|
||||
* a name: does the string with all the previous names contain the new player's
|
||||
* desired username? If yes, he is being assigned a random name. If no, he can keep
|
||||
* his desired name. */
|
||||
* his desired name.
|
||||
* **/
|
||||
|
||||
public class AllClientNames {
|
||||
static StringBuilder names = new StringBuilder();
|
||||
|
||||
/**
|
||||
* Safes a new name to the List of all Names
|
||||
* @param currentName the new name to be added
|
||||
* @return All names adding the new currentName
|
||||
*/
|
||||
public static String allNames(String currentName) {
|
||||
return names.append(currentName).toString();
|
||||
}
|
||||
|
||||
@ -1,147 +1,167 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.server;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NTtBFormatMsg;
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.ServerPinger;
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.util.HashSet;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class ClientHandler implements Runnable {
|
||||
private String clientUserName;
|
||||
private BufferedWriter out;
|
||||
private BufferedReader in;
|
||||
private Socket socket;
|
||||
Scanner sc;
|
||||
public static HashSet<ClientHandler> connectedClients = new HashSet<>();
|
||||
public static HashSet<ClientHandler> lobby = new HashSet<>();
|
||||
public static HashSet<ClientHandler> ghostClients = new HashSet<>();
|
||||
private ClientMsgDecoder clientMsgDecoder = new ClientMsgDecoder();
|
||||
public class ClientHandler implements Runnable {
|
||||
|
||||
/**
|
||||
* Implements the login logik in client-server
|
||||
* architecture.
|
||||
* @param socket the socket on which to make the connection.
|
||||
*/
|
||||
public ClientHandler(Socket socket) {
|
||||
try {
|
||||
this.socket = socket;
|
||||
this.out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
|
||||
this.in = new BufferedReader((new InputStreamReader((socket.getInputStream()))));
|
||||
this.clientUserName = in.readLine();
|
||||
private String clientUserName;
|
||||
private BufferedWriter out;
|
||||
private BufferedReader in;
|
||||
private Socket socket;
|
||||
Scanner sc;
|
||||
public ServerPinger serverPinger;
|
||||
public static HashSet<ClientHandler> connectedClients = new HashSet<>();
|
||||
public static HashSet<ClientHandler> lobby = new HashSet<>();
|
||||
public static HashSet<ClientHandler> ghostClients = new HashSet<>();
|
||||
|
||||
// duplicate handling: if username already taken, assign random name to client
|
||||
if (AllClientNames.allNames("").contains(clientUserName)) {
|
||||
clientUserName = NameGenerator.randomName();
|
||||
}
|
||||
// add username to list of all client names for future duplicate checking
|
||||
AllClientNames.allNames(clientUserName);
|
||||
|
||||
connectedClients.add(this);
|
||||
broadcastMessage("SERVER: " + clientUserName + " has joined the Server");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
closeEverything(socket, in, out);
|
||||
}
|
||||
/**
|
||||
* Implements the login logic in client-server architecture.
|
||||
*
|
||||
* @param socket the socket on which to make the connection.
|
||||
*/
|
||||
public ClientHandler(Socket socket) {
|
||||
try {
|
||||
this.socket = socket;
|
||||
this.out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
|
||||
this.in = new BufferedReader((new InputStreamReader((socket.getInputStream()))));
|
||||
this.clientUserName = in.readLine();
|
||||
// duplicate handling: if username already taken, assign random name to client
|
||||
if (AllClientNames.allNames("").contains(clientUserName)) {
|
||||
clientUserName = NameGenerator.randomName(clientUserName);
|
||||
}
|
||||
// add username to list of all client names for future duplicate checking
|
||||
AllClientNames.allNames(clientUserName);
|
||||
connectedClients.add(this);
|
||||
serverPinger = new ServerPinger(out, socket);
|
||||
Thread sP = new Thread(serverPinger);
|
||||
sP.start();
|
||||
broadcastMessage("SERVER: " + clientUserName + " has joined the Server");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
closeEverything(socket, in, out);
|
||||
}
|
||||
}
|
||||
|
||||
//Getters:
|
||||
public BufferedWriter getOut() {
|
||||
return out;
|
||||
//Getters:
|
||||
public BufferedWriter getOut() {
|
||||
return out;
|
||||
}
|
||||
|
||||
public BufferedReader getIn() {
|
||||
return in;
|
||||
}
|
||||
|
||||
public Socket getSocket() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
public static HashSet<ClientHandler> getConnectedClients() {
|
||||
return connectedClients;
|
||||
}
|
||||
|
||||
public static HashSet<ClientHandler> getLobby() {
|
||||
return lobby;
|
||||
}
|
||||
|
||||
public static HashSet<ClientHandler> getGhostClients() {
|
||||
return ghostClients;
|
||||
}
|
||||
|
||||
//Setters
|
||||
|
||||
|
||||
@Override
|
||||
/**
|
||||
* The main logic of the client handler.
|
||||
* Since every client is put on a string this is where
|
||||
* most interactions between client and server are held
|
||||
**/
|
||||
public void run() {
|
||||
String msg;
|
||||
while (socket.isConnected()) {
|
||||
try {
|
||||
msg = in.readLine();
|
||||
JServerProtocolParser.parse(msg, this);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
closeEverything(socket, in, out);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedReader getIn() {
|
||||
return in;
|
||||
public String getClientUserName() {
|
||||
return clientUserName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets the client change their respective username, if the username is already taken, a similar option is chosen
|
||||
* @param newName The desired new name to replace the old one with.
|
||||
*/
|
||||
public void changeUsername(String newName) {
|
||||
if (AllClientNames.allNames("").contains(newName)) {
|
||||
newName = NameGenerator.randomName(newName);
|
||||
}
|
||||
String h = this.clientUserName; //just a friendly little helper
|
||||
this.clientUserName = newName;
|
||||
AllClientNames.allNames(newName);
|
||||
broadcastMessage(h +" have changed their nickname to " + clientUserName);
|
||||
}
|
||||
|
||||
public static HashSet<ClientHandler> getConnectedClients() {
|
||||
return connectedClients;
|
||||
/**
|
||||
* Broadcasts a Message to all active clients in the form "Username: msg"
|
||||
* @param msg the Message to be broadcasted
|
||||
*/
|
||||
|
||||
public void broadcastMessage(String msg) {
|
||||
for (ClientHandler client : connectedClients) {
|
||||
client.sendMsgToClient("CHATM:" + clientUserName + ": \"" + msg + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
public static HashSet<ClientHandler> getLobby() {
|
||||
return lobby;
|
||||
//TODO: Documentation
|
||||
/**
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
|
||||
public void sendMsgToClient(String msg) {
|
||||
try {
|
||||
out.write(msg);
|
||||
out.newLine();
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static HashSet<ClientHandler> getGhostClients() {
|
||||
return ghostClients;
|
||||
public void removeClientHandler() {
|
||||
connectedClients.remove(this);
|
||||
broadcastMessage("SERVER: " + clientUserName + " has left the server");
|
||||
}
|
||||
|
||||
public void closeEverything(Socket socket, BufferedReader in, BufferedWriter out) {
|
||||
removeClientHandler();
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
if (socket != null) {
|
||||
socket.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public ClientMsgDecoder getClientMsgDecoder() {
|
||||
return clientMsgDecoder;
|
||||
}
|
||||
public void decodeMsg(String msg) {
|
||||
|
||||
//Setters
|
||||
|
||||
|
||||
@Override
|
||||
/**
|
||||
* The main logik of the client handler.
|
||||
* Since every client is put on a string this is where
|
||||
* most interactions between client and server are held..
|
||||
*/
|
||||
public void run() {
|
||||
String msg;
|
||||
NTtBFormatMsg response;
|
||||
while(socket.isConnected()) {
|
||||
try {
|
||||
|
||||
msg = in.readLine();
|
||||
response = clientMsgDecoder.decodeMsg(msg); //The response of the server to the clients message
|
||||
out.write(response.getMessage());
|
||||
out.newLine();
|
||||
out.flush();
|
||||
//TODO if merely an acknowledgement is sent back to the client, how does the client recieve game updates?
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
closeEverything(socket, in, out);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getClientUserName() {
|
||||
return clientUserName;
|
||||
}
|
||||
|
||||
public void broadcastMessage(String msg) {
|
||||
for (ClientHandler client : connectedClients) {
|
||||
try {
|
||||
if(!client.clientUserName.equals((clientUserName))) {
|
||||
client.out.write(msg);
|
||||
} else {
|
||||
client.out.write("Message: **" + msg + "** sent!");
|
||||
}
|
||||
client.out.newLine();
|
||||
client.out.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
closeEverything(socket, in ,out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeClientHandler() {
|
||||
connectedClients.remove(this);
|
||||
broadcastMessage("SERVER: " + clientUserName + " has left the server");
|
||||
}
|
||||
|
||||
public void closeEverything(Socket socket, BufferedReader in, BufferedWriter out) {
|
||||
removeClientHandler();
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
if (socket != null) {
|
||||
socket.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void decodeMsg(String msg){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,96 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.server;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NTtBFormatMsg;
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NightTrainProtocol;
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NightTrainProtocol.NTtBCommands;
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NoLegalProtocolCommandStringFoundException;
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.ProtocolDecoder;
|
||||
|
||||
|
||||
/**
|
||||
* Decodes the correctly formatted String containing command and parameters. For reasons of
|
||||
* seperation of work this class only tokenizes the string and acknowledges to the client that smth
|
||||
* was recieved. Actual method calls, change of state, method calles etc. are delegated to{@link
|
||||
* ch.unibas.dmi.dbis.cs108.multiplayer.server.cmd.methods.CommandExecuter} from within {@link
|
||||
* ClientHandler}.
|
||||
*/
|
||||
|
||||
public class ClientMsgDecoder implements ProtocolDecoder {
|
||||
|
||||
/**
|
||||
* The point of contact for the ClientHandler who calls this method to convert a String in to
|
||||
* usable, tokanized format defined by {@link NTtBFormatMsg}.
|
||||
*
|
||||
* @param msg coming from the client handlers input reader.
|
||||
* @return {@link NTtBFormatMsg}
|
||||
*/
|
||||
@Override
|
||||
public NTtBFormatMsg decodeMsg(String msg) {
|
||||
//Declare needed variables
|
||||
String[] msgTokens; //List where we'll put the string tokens seperated by $.
|
||||
String ackMsg; //The command token
|
||||
String[] parameters;
|
||||
NightTrainProtocol.NTtBCommands cmdObject;
|
||||
//Initalize fields for return object
|
||||
msgTokens = tokenizeMsg(msg);
|
||||
ackMsg = serverResponseBuilder(msgTokens);
|
||||
parameters = new String[msgTokens.length - 1];
|
||||
cmdObject = getCommandConstant(msgTokens[0]);
|
||||
return new NTtBFormatMsg(ackMsg, cmdObject, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the server acknowledgement response witch is instantly sent back to the client. The
|
||||
* response is merely that a command was recieved and which one.
|
||||
* <p>
|
||||
* If garbage was recieved a SEROR will be appended. It is assumed that the msgTokens array is not
|
||||
* empty.
|
||||
*
|
||||
* @param msgTokens an array containing the command String
|
||||
* @return a String containing the immediate response of the server to the client.
|
||||
*/
|
||||
private String serverResponseBuilder(String[] msgTokens) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
//assumes non-empty array!
|
||||
sb.append("SERVER: ");
|
||||
NightTrainProtocol.NTtBCommands cmd = getCommandConstant(msgTokens[0]);
|
||||
|
||||
if (cmd.equals(NTtBCommands.SEROR)) {
|
||||
return cmd + "invalid input";
|
||||
}
|
||||
|
||||
sb.append("Command *").append(cmd).append("* recieved!");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Turns the string into a command object. If no matching protocol command was found, it returns
|
||||
* an SEROR type.
|
||||
*
|
||||
* @param stringToken String that should match the String representation of a NTtBCommands,java
|
||||
* field.
|
||||
* @return type {@link ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NightTrainProtocol.NTtBCommands}
|
||||
* object
|
||||
*/
|
||||
private NightTrainProtocol.NTtBCommands getCommandConstant(String stringToken) {
|
||||
try {
|
||||
return NightTrainProtocol.getCmdEnumObject(stringToken);
|
||||
} catch (NoLegalProtocolCommandStringFoundException e) {
|
||||
return NightTrainProtocol.NTtBCommands.SEROR;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO What happens if there is no delimeter?
|
||||
|
||||
/**
|
||||
* Splits the input string along the delimiter "$".
|
||||
*
|
||||
* @param msg Clients input
|
||||
* @return an array of String objects containing the command and parameters of the message.
|
||||
*/
|
||||
private String[] tokenizeMsg(String msg) {
|
||||
return msg.split("$");
|
||||
}
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.server;
|
||||
|
||||
public class InSessionLogik {
|
||||
Server server;
|
||||
public InSessionLogik(Server server) {
|
||||
this.server = server;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.server;
|
||||
|
||||
|
||||
public class JServerProtocolParser {
|
||||
|
||||
/**
|
||||
* Used by the server (i.e. ClientHandler) to parse an incoming protocol message.
|
||||
*
|
||||
* @param msg the encoded message that needs to be parsed
|
||||
* @param h this ClientHandler (required so this method can access the ClientHandler's methods)
|
||||
*/
|
||||
public static void parse(String msg, ClientHandler h) {
|
||||
String header = ""; //"header" is the first 5 characters, i.e. the protocol part
|
||||
try {
|
||||
header = msg.substring(0, 5);
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
System.out.println("Received unknown command");
|
||||
}
|
||||
//System.out.println(header); helpful for debugging
|
||||
switch (header) {
|
||||
case "CHATA":
|
||||
h.broadcastMessage(msg.substring(6));
|
||||
break;
|
||||
case "NAMEC":
|
||||
h.changeUsername(msg.substring(6));
|
||||
break;
|
||||
case "CPING":
|
||||
h.sendMsgToClient("PINGB");
|
||||
break;
|
||||
case "PINGB":
|
||||
h.serverPinger.setGotPingBack(true);
|
||||
break;
|
||||
case "QUITS":
|
||||
h.closeEverything(h.getSocket(), h.getIn(), h.getOut());
|
||||
break;
|
||||
default:
|
||||
System.out.println("Received unknown command");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,19 +2,29 @@ package ch.unibas.dmi.dbis.cs108.multiplayer.server;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
// Creates a String beginning with "player_" followed by 4 random letters
|
||||
|
||||
public class NameGenerator {
|
||||
static String randomName() {
|
||||
StringBuilder name = new StringBuilder();
|
||||
Random r = new Random();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
char c = (char)(r.nextInt(26) + 'a');
|
||||
name.append(c);
|
||||
|
||||
/**
|
||||
* Creates a random alteration of a Name by adding 4 numbers at the end of the Name that shall be alterd
|
||||
* @param username the to be altered username
|
||||
* @return username + four numbers
|
||||
*/
|
||||
static String randomName(String username) {
|
||||
StringBuilder name;
|
||||
while (true) {
|
||||
|
||||
name = new StringBuilder();
|
||||
Random r = new Random();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int c = r.nextInt(10);
|
||||
name.append(c);
|
||||
}
|
||||
if (!AllClientNames.allNames("").contains(username + name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "player_" + name;
|
||||
}
|
||||
public static void main (String[] args) {
|
||||
System.out.println(randomName());
|
||||
return username + name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.server;
|
||||
|
||||
public class NoCommandTokenException extends Exception {
|
||||
|
||||
}
|
||||
@ -26,6 +26,12 @@ public class Server {
|
||||
Thread th = new Thread(nextClient);
|
||||
connectedClients.add(nextClient);
|
||||
th.start();
|
||||
// close socket + remove client if client is disconnected
|
||||
if (socket.getInputStream().read() == -1) {
|
||||
System.out.println("client disconnected. closing socket");
|
||||
socket.close();
|
||||
connectedClients.remove(nextClient);
|
||||
}
|
||||
|
||||
// close socket + remove client if client is disconnected
|
||||
if (socket.getInputStream().read() == -1) {
|
||||
|
||||
@ -1,110 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.server.cmd.methods;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NTtBFormatMsg;
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NightTrainProtocol.NTtBCommands;
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.server.ClientHandler;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This Class implements actually acting on the clients messages.
|
||||
*/
|
||||
public class CommandExecuter {
|
||||
|
||||
private ClientHandler caller;
|
||||
private static String msgPrefix = "SERVER: ";
|
||||
|
||||
public void execute(NTtBFormatMsg msg) {
|
||||
switch (msg.getCommand()) {
|
||||
case CRTGM:
|
||||
break;
|
||||
case CHATA:
|
||||
broadcastClientMsg(msg.getParameters());
|
||||
break;
|
||||
case CHATG:
|
||||
//TODO
|
||||
break;
|
||||
case LEAVG:
|
||||
//TODO
|
||||
break;
|
||||
case JOING:
|
||||
//TODO
|
||||
break;
|
||||
case VOTEG:
|
||||
//TODO
|
||||
break;
|
||||
case QUITS:
|
||||
quitServer();
|
||||
break;
|
||||
case CHATW:
|
||||
wisper(msg.getParameters());
|
||||
break;
|
||||
case LISTP:
|
||||
//TODO
|
||||
break;
|
||||
case CUSRN:
|
||||
changeNickname(msg.getParameters());
|
||||
break;
|
||||
case CPING:
|
||||
pongS();
|
||||
break;
|
||||
case MSGRS:
|
||||
//TODO
|
||||
break;
|
||||
case SEROR:
|
||||
//TODO
|
||||
break;
|
||||
case SPING:
|
||||
pongC();
|
||||
break;
|
||||
default:
|
||||
this.noCommand();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void wisper(String[] parameters) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
private void changeNickname(String[] parameters) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
private void quitServer() {
|
||||
//TODO
|
||||
}
|
||||
|
||||
private void pongC() {
|
||||
//TODO
|
||||
}
|
||||
|
||||
private void pongS() {
|
||||
//TODO
|
||||
}
|
||||
|
||||
private void noCommand() {
|
||||
try {
|
||||
caller.getOut().write(msgPrefix + String.valueOf(NTtBCommands.NOCMD));
|
||||
} catch (IOException e) {
|
||||
System.out.println("IOException in noCommand() in CommandExecuter.java");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* boradcast chat message to everyone
|
||||
*
|
||||
* @param parameters should only have one entry i.e. parameters.length == 1 should be true;
|
||||
*/
|
||||
private static void broadcastClientMsg(String[] parameters) {
|
||||
try {
|
||||
for (ClientHandler clients : ClientHandler.connectedClients) {
|
||||
clients.getOut().write(parameters[0]);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.out.println("IOEXCEPTION in CommandExecuter.java at broadcastClientMsg");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.server.cmd.methods;
|
||||
|
||||
public interface msgToMethod {
|
||||
|
||||
void quit();
|
||||
|
||||
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.server;
|
||||
|
||||
/**
|
||||
* Implements the communication protocol in the connecting phase.
|
||||
* After this one can consider the server and client in session;
|
||||
*/
|
||||
public class connectingLogik {
|
||||
}
|
||||
Reference in New Issue
Block a user