Cleaned up, deleted unused files, reformatted all code
This commit is contained in:
parent
d2c2ca1732
commit
6071ea4b2f
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,8 +10,8 @@ public class GameFunctions {
|
||||
**/
|
||||
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
|
||||
int nrOfUsers; // saves how many clients are active in this Game
|
||||
Train train; // saves who sits where
|
||||
Passenger[] passengerTrain;
|
||||
|
||||
/**
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.jonasStuff;
|
||||
|
||||
public enum ClientProtocol {
|
||||
MSGRS, //"Message received": Parameters: 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 //No command found.
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.jonasStuff;
|
||||
|
||||
public class ClientProtocolParser {
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.jonasStuff;
|
||||
|
||||
public enum ServerProtocol {
|
||||
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.
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.client;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.ClientPinger;
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NoLegalProtocolCommandStringFoundException;
|
||||
|
||||
import java.net.Socket;
|
||||
import java.io.*;
|
||||
@ -50,23 +49,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
|
||||
@ -92,6 +78,10 @@ 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);
|
||||
@ -103,6 +93,10 @@ public class Client {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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,22 +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": Parameters: 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.
|
||||
* CHATM: Incoming Chat message.
|
||||
*/
|
||||
@ -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,7 +1,6 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.server;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.ServerPinger;
|
||||
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NTtBFormatMsg;
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.util.HashSet;
|
||||
@ -18,7 +17,6 @@ public class ClientHandler implements Runnable {
|
||||
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();
|
||||
|
||||
/**
|
||||
* Implements the login logic in client-server architecture.
|
||||
@ -67,10 +65,6 @@ public class ClientHandler implements Runnable {
|
||||
return ghostClients;
|
||||
}
|
||||
|
||||
public ClientMsgDecoder getClientMsgDecoder() {
|
||||
return clientMsgDecoder;
|
||||
}
|
||||
|
||||
//Setters
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,13 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.server;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.jonasStuff.ServerProtocol;
|
||||
|
||||
|
||||
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)
|
||||
* @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
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
package ch.unibas.dmi.dbis.cs108.multiplayer.server;
|
||||
|
||||
public class NoCommandTokenException extends Exception {
|
||||
|
||||
}
|
||||
@ -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