Oppdaterer server og klient for å kunne sjekke om en forespørsel ble godkjent

Oppdaterer brukernavn-skjermen til å bekrefte at brukernavnet ble godkjent
This commit is contained in:
Kristian Knarvik 2020-04-27 09:57:23 +02:00
parent fcbbc83da6
commit 5207a6a0bc
8 changed files with 210 additions and 43 deletions

View File

@ -8,8 +8,11 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.viewport.FitViewport; import com.badlogic.gdx.utils.viewport.FitViewport;
import inf112.fiasko.roborally.gamewrapper.RoboRallyWrapper; import inf112.fiasko.roborally.gamewrapper.RoboRallyWrapper;
import inf112.fiasko.roborally.networking.RequestState;
import inf112.fiasko.roborally.networking.containers.UsernameRequest;
import javax.swing.*; import javax.swing.*;
import java.util.concurrent.TimeUnit;
/** /**
* This screen allows a user to choose their player name * This screen allows a user to choose their player name
@ -37,10 +40,9 @@ public class UsernameScreen extends AbstractScreen {
@Override @Override
public void touchUp(InputEvent e, float x, float y, int point, int button) { public void touchUp(InputEvent e, float x, float y, int point, int button) {
String userName = textInput.getText(); if (nameInvalid(textInput.getText())) {
if (nameInvalid(userName)) { JOptionPane.showMessageDialog(null, "Username must be unique, not " +
JOptionPane.showMessageDialog(null, "Username cannot be empty or more " + "empty and less than 21 characters.");
"than 20 characters.");
return; return;
} }
if (roboRallyWrapper.server == null) { if (roboRallyWrapper.server == null) {
@ -48,7 +50,7 @@ public class UsernameScreen extends AbstractScreen {
} else { } else {
roboRallyWrapper.setScreen(roboRallyWrapper.screenManager.getLobbyScreen(roboRallyWrapper)); roboRallyWrapper.setScreen(roboRallyWrapper.screenManager.getLobbyScreen(roboRallyWrapper));
} }
roboRallyWrapper.client.sendElement(userName);
} }
}); });
textInput = new TextField("", skin); textInput = new TextField("", skin);
@ -70,8 +72,20 @@ public class UsernameScreen extends AbstractScreen {
* @return False if the username can be used * @return False if the username can be used
*/ */
private boolean nameInvalid(String userName) { private boolean nameInvalid(String userName) {
//TODO: Find a way to ask the server if the name is taken if ("".equals(userName) || userName.length() > 20) {
return "".equals(userName) || userName.length() > 20; return true;
}
UsernameRequest usernameRequest = new UsernameRequest(userName);
roboRallyWrapper.client.sendElement(usernameRequest);
while (roboRallyWrapper.client.getLastRequestState() == RequestState.SENT_NOT_RECEIVED) {
//Wait for the server to respond
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return roboRallyWrapper.client.getLastRequestState() == RequestState.SENT_REJECTED;
} }
@Override @Override

View File

@ -0,0 +1,23 @@
package inf112.fiasko.roborally.networking;
/**
* This enum represents states of a request sent to the server
*/
public enum RequestState {
/**
* The request has been send to the server, but no response has been received
*/
SENT_NOT_RECEIVED,
/**
* The request has been sent to the server, and the server confirmed the receipt
*/
SENT_OKAY,
/**
* The request has been sent to the server, but the server rejected the request
*/
SENT_REJECTED,
/**
* No request has been sent to the server
*/
NOT_SENT
}

View File

@ -14,6 +14,7 @@ import java.util.List;
public class RoboRallyClient { public class RoboRallyClient {
private final Client client; private final Client client;
private final RoboRallyWrapper wrapper; private final RoboRallyWrapper wrapper;
private RoboRallyClientListener listener;
/** /**
* Instantiates a new Robo Rally client * Instantiates a new Robo Rally client
@ -25,7 +26,8 @@ public class RoboRallyClient {
client = new Client(); client = new Client();
client.start(); client.start();
NetworkUtil.registerClasses(client.getKryo()); NetworkUtil.registerClasses(client.getKryo());
client.addListener(new RoboRallyClientListener(wrapper)); this.listener = new RoboRallyClientListener(wrapper);
client.addListener(this.listener);
} }
/** /**
@ -49,6 +51,15 @@ public class RoboRallyClient {
return client.discoverHosts(wrapper.discoverUDPPort, 1000); return client.discoverHosts(wrapper.discoverUDPPort, 1000);
} }
/**
* Gets the state of the lastly sent request
*
* @return The state of the lastly sent request
*/
public RequestState getLastRequestState() {
return this.listener.getLastRequestState();
}
/** /**
* Sends something to the server * Sends something to the server
* *
@ -57,6 +68,7 @@ public class RoboRallyClient {
public void sendElement(Object object) { public void sendElement(Object object) {
try { try {
client.sendTCP(object); client.sendTCP(object);
listener.resetLastRequestState();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -6,6 +6,7 @@ import inf112.fiasko.roborally.elementproperties.GameState;
import inf112.fiasko.roborally.gamewrapper.RoboRallyWrapper; import inf112.fiasko.roborally.gamewrapper.RoboRallyWrapper;
import inf112.fiasko.roborally.networking.containers.ErrorResponse; import inf112.fiasko.roborally.networking.containers.ErrorResponse;
import inf112.fiasko.roborally.networking.containers.GameStartInfoResponse; import inf112.fiasko.roborally.networking.containers.GameStartInfoResponse;
import inf112.fiasko.roborally.networking.containers.OkayResponse;
import inf112.fiasko.roborally.networking.containers.PowerDownContainerResponse; import inf112.fiasko.roborally.networking.containers.PowerDownContainerResponse;
import inf112.fiasko.roborally.networking.containers.ProgramsContainerResponse; import inf112.fiasko.roborally.networking.containers.ProgramsContainerResponse;
import inf112.fiasko.roborally.objects.ProgrammingCardDeck; import inf112.fiasko.roborally.objects.ProgrammingCardDeck;
@ -18,6 +19,7 @@ import java.util.ArrayList;
*/ */
class RoboRallyClientListener extends Listener { class RoboRallyClientListener extends Listener {
private final RoboRallyWrapper wrapper; private final RoboRallyWrapper wrapper;
private RequestState lastRequestState = RequestState.NOT_SENT;
/** /**
* Instantiates a new Robo Rally client listener * Instantiates a new Robo Rally client listener
@ -29,6 +31,31 @@ class RoboRallyClientListener extends Listener {
this.wrapper = wrapper; this.wrapper = wrapper;
} }
/**
* Gets the robo rally wrapper stored
*
* @return A robo rally wrapper
*/
public RoboRallyWrapper getWrapper() {
return wrapper;
}
/**
* Gets the state of the lastly sent request
*
* @return The state of the lastly sent request
*/
public RequestState getLastRequestState() {
return lastRequestState;
}
/**
* Resets the state of the last request to sent not received
*/
public void resetLastRequestState() {
this.lastRequestState = RequestState.SENT_NOT_RECEIVED;
}
@Override @Override
public void disconnected(Connection connection) { public void disconnected(Connection connection) {
this.wrapper.quit("The server closed the connection."); this.wrapper.quit("The server closed the connection.");
@ -37,40 +64,76 @@ class RoboRallyClientListener extends Listener {
@Override @Override
public void received(Connection connection, Object object) { public void received(Connection connection, Object object) {
if (object instanceof ErrorResponse) { if (object instanceof ErrorResponse) {
ErrorResponse errorResponse = (ErrorResponse) object; handleError((ErrorResponse) object);
if (errorResponse.isCritical()) {
wrapper.quit(errorResponse.getErrorMessage());
}
System.out.println(errorResponse.getErrorMessage());
} else if (object instanceof GameStartInfoResponse) { } else if (object instanceof GameStartInfoResponse) {
GameStartInfoResponse info = (GameStartInfoResponse) object; receiveGameStartInfo((GameStartInfoResponse) object);
wrapper.roboRallyGame = new RoboRallyGame(info.getPlayerList(), info.getBoardName(),
wrapper.server != null, info.getPlayerName(), wrapper.server);
new Thread(() -> wrapper.roboRallyGame.runTurn()).start();
} else if (object instanceof ProgrammingCardDeck) { } else if (object instanceof ProgrammingCardDeck) {
if (((ProgrammingCardDeck) object).isEmpty()) { receiveHand((ProgrammingCardDeck) object);
wrapper.roboRallyGame.setProgram(new ArrayList<>());
if (wrapper.roboRallyGame.getRobotPowerDown()) {
wrapper.roboRallyGame.setGameState(GameState.SKIP_POWER_DOWN_SCREEN);
} else {
wrapper.roboRallyGame.setGameState(GameState.CHOOSING_POWER_DOWN);
}
} else {
wrapper.roboRallyGame.setGameState(GameState.CHOOSING_CARDS);
}
wrapper.roboRallyGame.setPlayerHand((ProgrammingCardDeck) object);
} else if (object instanceof ProgramsContainerResponse) { } else if (object instanceof ProgramsContainerResponse) {
new Thread(() -> { receivePrograms((ProgramsContainerResponse) object);
try {
wrapper.roboRallyGame.receiveAllPrograms((ProgramsContainerResponse) object);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
} else if (object instanceof PowerDownContainerResponse) { } else if (object instanceof PowerDownContainerResponse) {
new Thread(() -> wrapper.roboRallyGame.receiveStayInPowerDown((PowerDownContainerResponse) object)).start(); new Thread(() -> wrapper.roboRallyGame.receiveStayInPowerDown((PowerDownContainerResponse) object)).start();
} else if (object instanceof OkayResponse) {
this.lastRequestState = RequestState.SENT_OKAY;
} }
}
/**
* Handle an error received from the server
*
* @param errorResponse The error response received
*/
private void handleError(ErrorResponse errorResponse) {
this.lastRequestState = RequestState.SENT_REJECTED;
if (errorResponse.isCritical()) {
wrapper.quit(errorResponse.getErrorMessage());
}
System.out.println(errorResponse.getErrorMessage());
}
/**
* Receive information about the game and start the turn
*
* @param info The information received from the server
*/
private void receiveGameStartInfo(GameStartInfoResponse info) {
wrapper.roboRallyGame = new RoboRallyGame(info.getPlayerList(), info.getBoardName(),
wrapper.server != null, info.getPlayerName(), wrapper.server);
new Thread(() -> wrapper.roboRallyGame.runTurn()).start();
}
/**
* Receive a hand from the server
*
* @param newHand The new hand this client can choose from
*/
private void receiveHand(ProgrammingCardDeck newHand) {
if (newHand.isEmpty()) {
wrapper.roboRallyGame.setProgram(new ArrayList<>());
if (wrapper.roboRallyGame.getRobotPowerDown()) {
wrapper.roboRallyGame.setGameState(GameState.SKIP_POWER_DOWN_SCREEN);
} else {
wrapper.roboRallyGame.setGameState(GameState.CHOOSING_POWER_DOWN);
}
} else {
wrapper.roboRallyGame.setGameState(GameState.CHOOSING_CARDS);
}
wrapper.roboRallyGame.setPlayerHand(newHand);
}
/**
* Receive and handle programs send from server
*
* @param response The response received from the server
*/
private void receivePrograms(ProgramsContainerResponse response) {
new Thread(() -> {
try {
wrapper.roboRallyGame.receiveAllPrograms(response);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
} }
} }

View File

@ -5,9 +5,11 @@ import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener; import com.esotericsoftware.kryonet.Listener;
import inf112.fiasko.roborally.elementproperties.RobotID; import inf112.fiasko.roborally.elementproperties.RobotID;
import inf112.fiasko.roborally.networking.containers.ErrorResponse; import inf112.fiasko.roborally.networking.containers.ErrorResponse;
import inf112.fiasko.roborally.networking.containers.OkayResponse;
import inf112.fiasko.roborally.networking.containers.PowerDownContainerResponse; import inf112.fiasko.roborally.networking.containers.PowerDownContainerResponse;
import inf112.fiasko.roborally.networking.containers.ProgramsContainerResponse;
import inf112.fiasko.roborally.networking.containers.ProgramAndPowerdownRequest; import inf112.fiasko.roborally.networking.containers.ProgramAndPowerdownRequest;
import inf112.fiasko.roborally.networking.containers.ProgramsContainerResponse;
import inf112.fiasko.roborally.networking.containers.UsernameRequest;
import inf112.fiasko.roborally.objects.ProgrammingCard; import inf112.fiasko.roborally.objects.ProgrammingCard;
import java.util.ArrayList; import java.util.ArrayList;
@ -105,8 +107,8 @@ class RoboRallyServerListener extends Listener {
@Override @Override
public void received(Connection connection, Object object) { public void received(Connection connection, Object object) {
if (object instanceof String) { if (object instanceof UsernameRequest) {
receivedString(connection, (String) object); receivedUsername(connection, (UsernameRequest) object);
} else if (object instanceof Boolean) { } else if (object instanceof Boolean) {
receiveContinuePowerDown(connection, (Boolean) object); receiveContinuePowerDown(connection, (Boolean) object);
} else if (object instanceof ProgramAndPowerdownRequest) { } else if (object instanceof ProgramAndPowerdownRequest) {
@ -118,13 +120,14 @@ class RoboRallyServerListener extends Listener {
* Handles the receiving of a string, handled as a player name in this context * Handles the receiving of a string, handled as a player name in this context
* *
* @param connection The connection sending the string * @param connection The connection sending the string
* @param playerName The player name received * @param request The username request received
*/ */
private void receivedString(Connection connection, String playerName) { private void receivedUsername(Connection connection, UsernameRequest request) {
String playerName = request.getUsername();
if (playerNames.containsValue(playerName)) { if (playerNames.containsValue(playerName)) {
String errorMessage = "The player playerName send is already taken."; connection.sendTCP(new ErrorResponse("The player playerName sent is already taken."));
connection.sendTCP(new ErrorResponse(errorMessage));
} else { } else {
connection.sendTCP(new OkayResponse());
playerNames.put(connection, playerName); playerNames.put(connection, playerName);
} }
} }
@ -137,6 +140,7 @@ class RoboRallyServerListener extends Listener {
*/ */
private void receiveContinuePowerDown(Connection connection, Boolean bool) { private void receiveContinuePowerDown(Connection connection, Boolean bool) {
stayInPowerDown.put(connection, bool); stayInPowerDown.put(connection, bool);
connection.sendTCP(new OkayResponse());
if (receivedDataFromAllConnections(stayInPowerDown)) { if (receivedDataFromAllConnections(stayInPowerDown)) {
Map<String, Boolean> powerDowns = new HashMap<>(); Map<String, Boolean> powerDowns = new HashMap<>();
for (Connection connected : stayInPowerDown.keySet()) { for (Connection connected : stayInPowerDown.keySet()) {
@ -155,6 +159,7 @@ class RoboRallyServerListener extends Listener {
*/ */
private void receiveProgramAndPowerDownRequest(Connection connection, ProgramAndPowerdownRequest request) { private void receiveProgramAndPowerDownRequest(Connection connection, ProgramAndPowerdownRequest request) {
programs.put(connection, request); programs.put(connection, request);
connection.sendTCP(new OkayResponse());
if (receivedDataFromAllConnections(programs)) { if (receivedDataFromAllConnections(programs)) {
Map<String, Boolean> powerDown = new HashMap<>(); Map<String, Boolean> powerDown = new HashMap<>();
Map<String, List<ProgrammingCard>> program = new HashMap<>(); Map<String, List<ProgrammingCard>> program = new HashMap<>();

View File

@ -0,0 +1,13 @@
package inf112.fiasko.roborally.networking.containers;
/**
* An empty response telling the client its request was fulfilled
*/
public class OkayResponse {
/**
* Empty constructor required by KryoNet. DO NOT REMOVE THIS!!!
*/
public OkayResponse() {
}
}

View File

@ -0,0 +1,33 @@
package inf112.fiasko.roborally.networking.containers;
/**
* A request for sending a username to the server
*/
public class UsernameRequest {
private String username;
/**
* Empty constructor required by KryoNet. DO NOT REMOVE THIS!!!
*/
public UsernameRequest() {
}
/**
* Instantiates a new username request
*
* @param username The username the player wants to use
*/
public UsernameRequest(String username) {
this.username = username;
}
/**
* Gets the username the user wants to use
*
* @return The username the user wants to use
*/
public String getUsername() {
return this.username;
}
}

View File

@ -5,9 +5,11 @@ import inf112.fiasko.roborally.elementproperties.Action;
import inf112.fiasko.roborally.elementproperties.RobotID; import inf112.fiasko.roborally.elementproperties.RobotID;
import inf112.fiasko.roborally.networking.containers.ErrorResponse; import inf112.fiasko.roborally.networking.containers.ErrorResponse;
import inf112.fiasko.roborally.networking.containers.GameStartInfoResponse; import inf112.fiasko.roborally.networking.containers.GameStartInfoResponse;
import inf112.fiasko.roborally.networking.containers.OkayResponse;
import inf112.fiasko.roborally.networking.containers.PowerDownContainerResponse; import inf112.fiasko.roborally.networking.containers.PowerDownContainerResponse;
import inf112.fiasko.roborally.networking.containers.ProgramsContainerResponse;
import inf112.fiasko.roborally.networking.containers.ProgramAndPowerdownRequest; import inf112.fiasko.roborally.networking.containers.ProgramAndPowerdownRequest;
import inf112.fiasko.roborally.networking.containers.ProgramsContainerResponse;
import inf112.fiasko.roborally.networking.containers.UsernameRequest;
import inf112.fiasko.roborally.objects.Deck; import inf112.fiasko.roborally.objects.Deck;
import inf112.fiasko.roborally.objects.Player; import inf112.fiasko.roborally.objects.Player;
import inf112.fiasko.roborally.objects.ProgrammingCard; import inf112.fiasko.roborally.objects.ProgrammingCard;
@ -40,5 +42,7 @@ public final class NetworkUtil {
kryo.register(ProgramsContainerResponse.class); kryo.register(ProgramsContainerResponse.class);
kryo.register(PowerDownContainerResponse.class); kryo.register(PowerDownContainerResponse.class);
kryo.register(HashMap.class); kryo.register(HashMap.class);
kryo.register(UsernameRequest.class);
kryo.register(OkayResponse.class);
} }
} }