Finnished ClientMsgDecoder!

last thing todo is implement
the execution of the input.
This commit is contained in:
Sebastian Lenzlinger 2022-03-26 13:14:36 +01:00
parent 9b1faa6ce1
commit b2d725f4c3
12 changed files with 423 additions and 312 deletions

View File

@ -41,7 +41,7 @@
</td> </td>
<td> <td>
<div class="infoBox" id="duration"> <div class="infoBox" id="duration">
<div class="counter">0.009s</div> <div class="counter">0.013s</div>
<p>duration</p> <p>duration</p>
</div> </div>
</td> </td>
@ -76,7 +76,7 @@
</thead> </thead>
<tr> <tr>
<td class="success">testMain()</td> <td class="success">testMain()</td>
<td class="success">0.009s</td> <td class="success">0.013s</td>
<td class="success">passed</td> <td class="success">passed</td>
</tr> </tr>
</table> </table>
@ -89,7 +89,7 @@
<input id="line-wrapping-toggle" type="checkbox" autocomplete="off"/> <input id="line-wrapping-toggle" type="checkbox" autocomplete="off"/>
</label> </label>
</div>Generated by </div>Generated by
<a href="http://www.gradle.org">Gradle 6.9.2</a> at 06.03.2022, 13:30:14</p> <a href="http://www.gradle.org">Gradle 6.9.2</a> at 26.03.2022, 12:19:23</p>
</div> </div>
</div> </div>
</body> </body>

View File

@ -60,25 +60,27 @@ public class Client {
} }
/** /**
* Uses <code>NTtBProtocolParser</code> to turn Client * Uses <code>NTtBProtocolParser</code> to turn Client input into the NTtB Protocol format. Must
* input into the NTtB Protocol format. * be called before a client input is sent to the server.
* Must be called before a client input is sent to the server. *
* @param msg the msg to be encoded. * @param msg the msg to be encoded.
* @return Message encoded adhering to the NTtB Protocoll. * @return Message encoded adhering to the NTtB Protocoll.
*/ */
private String encodeMessage(String msg) throws NoLegalProtocolCommandStringFoundException, EmptyClientInputException { private String encodeMessage(String msg)
throws NoLegalProtocolCommandStringFoundException, EmptyClientInputException {
NTtBProtocolParser pp = new NTtBProtocolParser(this); NTtBProtocolParser pp = new NTtBProtocolParser(this);
return pp.parseMsg(msg); return pp.parseMsg(msg);
} }
//TODO implement decoding of server input
private String decodeServerMsg(String msg){return null;}
/** /**
* Listens for incoming messages * Listens for incoming messages
*/ */
public void chatListener() { public void chatListener() {
/*TODO: what type of decoding has to be done /*TODO: what type of decoding has to be done
think better about structure for incoming messages TODO how shall input be logged?
*/ */
//TODO how shall input be logged?
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {

View File

@ -6,11 +6,11 @@ import java.util.ArrayList;
import java.util.Scanner; import java.util.Scanner;
/** /**
* Implements a protocol parser for the NTtB protocoll, * Implements a protocol parser for the NTtB protocoll, that transforms client input into a server
* that transforms client input * readable format.
* into a server readable format.
*/ */
public class NTtBProtocolParser implements ProtocolParser { public class NTtBProtocolParser implements ProtocolParser {
//TODO Possibly bad name, rename to clientMsgParser? //TODO Possibly bad name, rename to clientMsgParser?
public final Client caller; public final Client caller;
public static InputToProtocolMap legalCommands = new InputToProtocolMap(); public static InputToProtocolMap legalCommands = new InputToProtocolMap();
@ -19,8 +19,10 @@ public class NTtBProtocolParser implements ProtocolParser {
public NTtBProtocolParser(Client caller) { public NTtBProtocolParser(Client caller) {
this.caller = caller; this.caller = caller;
} }
@Override @Override
public String parseMsg(String msg) throws NoLegalProtocolCommandStringFoundException, EmptyClientInputException{ public String parseMsg(String msg)
throws NoLegalProtocolCommandStringFoundException, EmptyClientInputException {
Scanner sc = new Scanner(msg); Scanner sc = new Scanner(msg);
ArrayList<String> input = new ArrayList<>(); ArrayList<String> input = new ArrayList<>();
String parsedMsg = buildProtocolMsg(input); String parsedMsg = buildProtocolMsg(input);
@ -33,7 +35,8 @@ public class NTtBProtocolParser implements ProtocolParser {
} }
private String buildProtocolMsg(ArrayList<String> input) throws EmptyClientInputException, NoLegalProtocolCommandStringFoundException { private String buildProtocolMsg(ArrayList<String> input)
throws EmptyClientInputException, NoLegalProtocolCommandStringFoundException {
//TODO //TODO
if (emptyClientInput(input)) { if (emptyClientInput(input)) {
throw new EmptyClientInputException(caller); throw new EmptyClientInputException(caller);
@ -52,10 +55,8 @@ public class NTtBProtocolParser implements ProtocolParser {
/** /**
* Checks if input has parameters * Checks if input has parameters
* * <p>
* if the list size is smaller than 2, i.e. * if the list size is smaller than 2, i.e. not larger than 1, the input only contains a command.
* not larger than 1, the input only contains
* a command.
* *
* @param input the tokenized input string. * @param input the tokenized input string.
* @return true if input list is larger than 2. * @return true if input list is larger than 2.
@ -66,6 +67,7 @@ public class NTtBProtocolParser implements ProtocolParser {
/** /**
* checks if client input is empty * checks if client input is empty
*
* @param clientInput the clients input. * @param clientInput the clients input.
* @return true if client didn't send any input besides whitespace * @return true if client didn't send any input besides whitespace
*/ */

View File

@ -1,9 +1,10 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client; package ch.unibas.dmi.dbis.cs108.multiplayer.client;
public interface ProtocolParser { public interface ProtocolParser {
/** /**
* Takes a String from client input and parses into * Takes a String from client input and parses into server readable message.
* server readable message. *
* @param msg the message to be parsed * @param msg the message to be parsed
* @return a String message formatted for the specific protocol * @return a String message formatted for the specific protocol
*/ */

View File

@ -4,21 +4,19 @@ import java.util.LinkedList;
import java.util.Queue; import java.util.Queue;
/** /**
* This class defines what type the ClientMsgDecoder returns after decoding the message. * This class defines what type the ClientMsgDecoder returns after decoding the message. This is
* This is done so the output can be split into a response to the client and action * done so the output can be split into a response to the client and action in to the game logik.
* in to the game logik. * commands should map to methods(maybe classes) parameters map to method parameters
* commands should map to methods(maybe classes)
* parameters map to method parameters
*
*/ */
public class NTtBFormatMsg { public class NTtBFormatMsg {
private String msgToClient; private String msgToClient;
private NightTrainProtocol.NTtBCommands command; private NightTrainProtocol.NTtBCommands command;
private final Queue<String> parameters; //TODO maybe use array? private final String[] parameters; //TODO maybe use array?
public NTtBFormatMsg(String msgToClient, NightTrainProtocol.NTtBCommands command, Queue<String> parameters) { public NTtBFormatMsg(String msgToClient, NightTrainProtocol.NTtBCommands command,
String[] parameters) {
this.msgToClient = msgToClient; this.msgToClient = msgToClient;
this.command = command; this.command = command;
this.parameters = parameters; this.parameters = parameters;
@ -27,7 +25,7 @@ public class NTtBFormatMsg {
public NTtBFormatMsg() { public NTtBFormatMsg() {
this.msgToClient = ""; this.msgToClient = "";
this.command = null; this.command = null;
this.parameters = new LinkedList<>(); this.parameters = new String[]{""};
} }
public String getMessage() { public String getMessage() {
@ -38,15 +36,15 @@ public class NTtBFormatMsg {
return command; return command;
} }
public Queue<String> getParameters() { public String[] getParameters() {
return parameters; return parameters;
} }
public void setMsgToClient(String msgToClient) { protected void setMsgToClient(String msgToClient) {
this.msgToClient = msgToClient; this.msgToClient = msgToClient;
} }
public void setCommand(NightTrainProtocol.NTtBCommands command) { protected void setCommand(NightTrainProtocol.NTtBCommands command) {
this.command = command; this.command = command;
} }
} }

View File

@ -10,9 +10,11 @@
* VOTEH: humans voting whos the ghost * VOTEH: humans voting whos the ghost
* QUITS: quit server/ leave servr * QUITS: quit server/ leave servr
* LISTP: list players/clients in session with the Server * LISTP: list players/clients in session with the Server
* CPING: Ping from client to server.
*/ */
/** /**
Server Commands: Server Commands:
* MSGRS: "Message recieved": Paramaters: a string detailing to the client that and what the server recieved as command. * MSGRS: "Message recieved": Paramaters: a string detailing to the client that and what the server recieved as command.
* SEROR: Server had an error. (used for debugging) * SEROR: Server had an error. (used for debugging)
* SPING: Ping from server to client;
*/ */

View File

@ -19,9 +19,9 @@ public class NightTrainProtocol {
public enum NTtBCommands { public enum NTtBCommands {
//Client Commands //Client Commands
CRTGM, CHATA, CHATW, CHATG, LEAVG, JOING, VOTEG, QUITS, LISTP, CUSRN, CRTGM, CHATA, CHATW, CHATG, LEAVG, JOING, VOTEG, QUITS, LISTP, CUSRN,CPING,
//Server Responses //Server Responses
MSGRS, SEROR; MSGRS, SEROR, SPING;
} }
private static HashMap<String, NTtBCommands> initializeMapping(){ private static HashMap<String, NTtBCommands> initializeMapping(){

View File

@ -1,5 +1,6 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.server; package ch.unibas.dmi.dbis.cs108.multiplayer.server;
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NTtBFormatMsg;
import java.io.*; import java.io.*;
import java.net.Socket; import java.net.Socket;
import java.util.HashSet; import java.util.HashSet;
@ -12,7 +13,7 @@ public class ClientHandler implements Runnable {
private Socket socket; private Socket socket;
Scanner sc; Scanner sc;
public static HashSet<ClientHandler> connectedClients = new HashSet<>(); public static HashSet<ClientHandler> connectedClients = new HashSet<>();
public static HashSet<ClientHandler> inGameClients = new HashSet<>(); public static HashSet<ClientHandler> lobby = new HashSet<>();
public static HashSet<ClientHandler> ghostClients = new HashSet<>(); public static HashSet<ClientHandler> ghostClients = new HashSet<>();
private ClientMsgDecoder clientMsgDecoder = new ClientMsgDecoder(); private ClientMsgDecoder clientMsgDecoder = new ClientMsgDecoder();
@ -35,19 +36,47 @@ public class ClientHandler implements Runnable {
} }
} }
//Getters:
public BufferedWriter getOut() {
return out;
}
public BufferedReader getIn() {
return in;
}
public static HashSet<ClientHandler> getConnectedClients() {
return connectedClients;
}
public static HashSet<ClientHandler> getLobby() {
return lobby;
}
public static HashSet<ClientHandler> getGhostClients() {
return ghostClients;
}
public ClientMsgDecoder getClientMsgDecoder() {
return clientMsgDecoder;
}
//Setters
@Override @Override
/** /**
* point of contact for client and server. * point of contact for client and server.
*/ */
public void run() { public void run() {
String msg; String msg;
String response; NTtBFormatMsg response;
while(socket.isConnected()) { while(socket.isConnected()) {
try { try {
msg = in.readLine(); msg = in.readLine();
response = clientMsgDecoder.decodeMsg(msg).getMessage(); //The response of the server to the clients message response = clientMsgDecoder.decodeMsg(msg); //The response of the server to the clients message
out.write(response); out.write(response.getMessage());
out.newLine(); out.newLine();
out.flush(); out.flush();
//TODO if merely an acknowledgement is sent back to the client, how does the client recieve game updates? //TODO if merely an acknowledgement is sent back to the client, how does the client recieve game updates?

View File

@ -6,43 +6,36 @@ import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.NoLegalProtocolCommandStrin
import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.ProtocolDecoder; import ch.unibas.dmi.dbis.cs108.multiplayer.protocol.ProtocolDecoder;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
import java.util.Queue; import java.util.Queue;
public class ClientMsgDecoder implements ProtocolDecoder { public class ClientMsgDecoder implements ProtocolDecoder {
private NightTrainProtocol protocol; private NightTrainProtocol protocol;
@Override @Override
//TODO this method IS NOT FINNISHED. @return is not correct as of now! //TODO this method IS NOT FINNISHED. @return is not correct as of now!
public NTtBFormatMsg decodeMsg(String msg) { public NTtBFormatMsg decodeMsg(String msg) {
List<String> msgTokens = tokenizeMsg(msg); //List where we'll put the string tokens seperated by $. //Declare needed variables
String cmd; //The command token String[] msgTokens; //List where we'll put the string tokens seperated by $.
String ackMsg; //The command token
String[] parameters;
NightTrainProtocol.NTtBCommands cmdObject; NightTrainProtocol.NTtBCommands cmdObject;
Queue<String> parameters; //Initalize fields for return object
NTtBFormatMsg util = new NTtBFormatMsg(); msgTokens = tokenizeMsg(msg);
cmd = serverResponseBuilder(msgTokens); ackMsg = serverResponseBuilder(msgTokens);
cmdObject = getCommandConstant(cmd); parameters = new String[msgTokens.length-1];
util.setCommand(cmdObject); cmdObject = getCommandConstant(msgTokens[0]);
try{ return new NTtBFormatMsg(ackMsg, cmdObject, parameters);
cmd = getCommandStringToken(msgTokens);
} catch (NoCommandTokenException e) {
//TODO: decide what to do here. How can we catch this smartly and where do we send it?
System.out.println(("ClientMsgDecoder cannot find a command token"));
e.printStackTrace(System.out);
return new NTtBFormatMsg("ERROR$NoCommandTokenException caught!", null, null);
}
return null;
} }
/* /*
* Builds the servers response message * Builds the servers response message
* to client * to client
*/ */
private String serverResponseBuilder(List<String> msgTokens){ private String serverResponseBuilder(String[] msgTokens) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
//assumes not empty list! //assumes not empty list!
NightTrainProtocol.NTtBCommands cmd = getCommandConstant(msgTokens.get(0)); NightTrainProtocol.NTtBCommands cmd = getCommandConstant(msgTokens[0]);
sb.append("SERVER: "); sb.append("SERVER: ");
sb.append("Command *" + cmd.toString() + "* recieved!"); sb.append("Command *" + cmd.toString() + "* recieved!");
@ -53,9 +46,11 @@ public class ClientMsgDecoder implements ProtocolDecoder {
private boolean isLegalCmdString(String cmd) { private boolean isLegalCmdString(String cmd) {
return protocol.isLegalCmdString(cmd); return protocol.isLegalCmdString(cmd);
} }
private String getCommandStringToken(List<String> msgTokens) throws NoCommandTokenException {
return msgTokens.get(0); private String getCommandStringToken(String[] msgTokens) throws NoCommandTokenException {
return msgTokens[0];
} }
private NightTrainProtocol.NTtBCommands getCommandConstant(String stringToken) { private NightTrainProtocol.NTtBCommands getCommandConstant(String stringToken) {
try { try {
return protocol.getCmdEnumObject(stringToken); return protocol.getCmdEnumObject(stringToken);
@ -69,8 +64,9 @@ public class ClientMsgDecoder implements ProtocolDecoder {
} }
//Creates tokens from the clientMsg and puts them in a list //Creates tokens from the clientMsg and puts them in a list
private List<String> tokenizeMsg(String msg) { //TODO what side effects could be here?
return null; private String[] tokenizeMsg(String msg) {
return msg.split("$");
} }
/* /*

View File

@ -0,0 +1,73 @@
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.server.ClientHandler;
import java.io.IOException;
/**
* This Class implements actually acting on the clients
* messages.
*/
public class CommandExecuter {
ClientHandler caller;
public static 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;
}
}
/**
* 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) throws IOException {
for(ClientHandler clients: ClientHandler.connectedClients) {
clients.getOut().write(parameters[0]);
}
}
}

View File

@ -0,0 +1,8 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.server.cmd.methods;
public interface msgToMethod {
void quit();
}