Had to change ClientHandler fields vote and hasVoted to arrays and had to make sure, the position of the Passenger is always sent along in protocol ($position$msg)

This commit is contained in:
Seraina 2022-04-09 16:11:30 +02:00
parent 46f75d3292
commit 45597eee3c
15 changed files with 92 additions and 55 deletions

View File

@ -7,7 +7,7 @@ Implemented:
* PINGB Pingback from client to server.
* NAMEC$name Change name to whatever is specified
* STGAM start the Game
* CVOTE$position Client has voted for position
* CVOTE$position$vote Client at position has voted for position
Future / planned:
* CRTGM Create a new game
@ -24,8 +24,8 @@ Server Commands:
Implemented:
* SPING Ping from server to client
* PINGB Pingback from client to server.
* GVOTR Ghosts: Please vote now
* HVOTR Humans: Please vote now
* GVOTR$position$msg Ghosts: Please vote now
* HVOTR$position$msg Humans: Please vote now
Future / planned:
* MSGRS "Message received": Paramaters: a string detailing to the client that and what the server received as command.

View File

@ -89,11 +89,11 @@ public class Game implements Runnable {
while (i < order.length) {
int index = order[i];
if (passengerTrain[index].getIsGhost()) { //if they are a ghost
GhostNPC ghostNPC = new GhostNPC(passengerTrain[index].getPosition(), "NPC" + passengerTrain[index].getPosition(),passengerTrain[index].getIsOG() ,this);
GhostNPC ghostNPC = new GhostNPC(passengerTrain[index].getPosition(), "NPC" + passengerTrain[index].getPosition(),passengerTrain[index].getIsOG());
gameState.getPassengerTrain()[index] = ghostNPC;
} else {
//ToDo: give NPC nice usernames
HumanNPC humanNPC = new HumanNPC(passengerTrain[index].getPosition(), "NPC" + passengerTrain[index].getPosition(),this);
HumanNPC humanNPC = new HumanNPC(passengerTrain[index].getPosition(), "NPC" + passengerTrain[index].getPosition());
gameState.getPassengerTrain()[index] = humanNPC;
}
i++;

View File

@ -2,6 +2,7 @@ package ch.unibas.dmi.dbis.cs108.gamelogic;
import ch.unibas.dmi.dbis.cs108.BudaLogConfig;
import ch.unibas.dmi.dbis.cs108.gamelogic.klassenstruktur.Ghost;
import ch.unibas.dmi.dbis.cs108.gamelogic.klassenstruktur.GhostNPC;
import ch.unibas.dmi.dbis.cs108.gamelogic.klassenstruktur.GhostPlayer;
import ch.unibas.dmi.dbis.cs108.gamelogic.klassenstruktur.Passenger;
import org.apache.logging.log4j.LogManager;
@ -19,11 +20,23 @@ public class GhostifyHandler {
public Ghost ghost(Passenger p, Game game) { //TODO: Adjust for not only players but also npcs
LOGGER.debug("Passenger Position " + p.getPosition());
p.setGhost();
Ghost g;
g = new Ghost();
g.setGhost();
g.setPosition(p.getPosition());
if (p.getIsPlayer()) {
p.setGhost();
GhostPlayer ghostPlayer;
ghostPlayer = new GhostPlayer(p.getPosition(), p.getName(), p.getClientHandler(),p.getIsOG());
ghostPlayer.setGhost();
ghostPlayer.setPosition(p.getPosition());
g = ghostPlayer;
} else {
p.setGhost();
GhostNPC ghostNPC;
ghostNPC = new GhostNPC(p.getPosition(), p.getName(),p.getIsOG());
ghostNPC.setGhost();
ghostNPC.setPosition(p.getPosition());
g = ghostNPC;
}
game.gameState.addNewPassenger(g, g.getPosition());
LOGGER.info("Passenger at position " + p.getPosition() + "has been ghostified");
return g;

View File

@ -25,16 +25,16 @@ public class ServerGameInfoHandler {
* @param msg the message to be formatted
* @return a message in a protocol format
*/
public static String format(String msg, Game game) {
public static String format(String msg, Passenger p, Game game) {
switch (msg) {
case "Vote on who to ghostify!":
msg = Protocol.serverRequestsGhostVote + "$" + game.gameState.toString();
msg = Protocol.serverRequestsGhostVote + "$" + p.getPosition() +"$" + game.gameState.toString();
break;
case "Vote for a ghost to kick off!":
msg = Protocol.serverRequestsHumanVote + "$" + game.gameState.humanToString();
msg = Protocol.serverRequestsHumanVote + "$" + p.getPosition() +"$"+ game.gameState.humanToString();
break;
default:
msg = Protocol.printToClientConsole + "$" + msg;
msg = Protocol.printToClientConsole + "$" + p.getPosition() +"$"+ msg;
}
LOGGER.info(msg);
return msg;

View File

@ -33,6 +33,7 @@ public class VoteHandler {
*/
public void ghostVote(Passenger[] passengers, Game game) {
LOGGER.debug("ghostVote has been called");
LOGGER.info(game.getGameState().toString());
// array to collect votes for all players during voting, i.e. votes for player 1 (passengers[0])
// are saved in
@ -101,6 +102,7 @@ public class VoteHandler {
passengers[ghostPosition].send(
"You are now a ghost!", game); // TODO: ServerGameInfoHandler might deal with this one
LOGGER.info(game.getGameState().toString());
// set hasVoted to false for all passengers for future votings
for (Passenger passenger : passengers) {
passenger.setHasVoted(false);
@ -117,7 +119,7 @@ public class VoteHandler {
* @param passengers: train passengers
*/
public String humanVote(Passenger[] passengers, Game game) {
LOGGER.info(game.getGameState().toString());
// array to collect votes for all players during voting, i.e. votes for player 1 are saved in
// votesForPlayers[0]
@ -134,20 +136,19 @@ public class VoteHandler {
}
try { // waits 20 seconds before votes get collected
Thread.sleep(30*1000);
Thread.sleep(20*1000);
} catch (InterruptedException e) {
LOGGER.warn("Thread " + Thread.currentThread() + " was interrupted");
}
for (Passenger passenger : passengers) {
passenger.getVoteFromClientHandler();
// collecting the votes - distribute them among the vote counters for all players
// TODO: Perhaps the vote results should be handled by ClientGameInfoHandler
if (passenger.getHasVoted()) {
for (int i = 0; i < votesForPlayers.length; i++) {
LOGGER.info("Passenger: " + passenger.getPosition() + " voted for: " + passenger.getVote() );
if (passenger.getVote() == i) {
votesForPlayers[i]++;
}
}
}
@ -202,6 +203,7 @@ public class VoteHandler {
}
}
}
LOGGER.info(game.getGameState().toString());
// set hasVoted to false for all passengers for future voting
for (Passenger passenger : passengers) {
passenger.setHasVoted(false);

View File

@ -19,7 +19,7 @@ public class GhostNPC extends Ghost {
* @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, Game game) {
public GhostNPC(int position, String name, boolean isOG) {
this.isOG = isOG;
this.position = position;
this.clientHandler = null;

View File

@ -35,7 +35,7 @@ public class GhostPlayer extends Ghost {
@Override
public void send(String msg, Game game) {
String formattedMsg = ServerGameInfoHandler.format(msg, game);
String formattedMsg = ServerGameInfoHandler.format(msg, this, game);
clientHandler.sendMsgToClient(formattedMsg);
}
@ -45,10 +45,11 @@ public class GhostPlayer extends Ghost {
*/
@Override
public void getVoteFromClientHandler() {
vote = clientHandler.getVote();
hasVoted = clientHandler.getHasVoted();
clientHandler.setVote(Integer.MAX_VALUE);
clientHandler.setHasVoted(false);
vote = clientHandler.getVote()[position];
hasVoted = clientHandler.getHasVoted()[position];
clientHandler.setVote(position,Integer.MAX_VALUE);
clientHandler.setHasVoted(position,false);
LOGGER.info("Ghost at Pos: " + position + " has voted for: " + vote);
/*
* if vote wasn't valid, make sure, the passenger field hasVoted == false, probably redundant but better be safe than sorry
*/

View File

@ -16,7 +16,7 @@ public class HumanNPC extends Human {
* @param position position on the train
* @param name player name. if null, then a default name is used.
*/
public HumanNPC(int position, String name, Game game) {
public HumanNPC(int position, String name) {
this.position = position;
this.clientHandler = null;
isGhost = false;
@ -38,8 +38,11 @@ public class HumanNPC extends Human {
* Currently returns a random integer for voting
* @return integer between 0 and 5
*/
public int vote(){
return (int) (Math.random()*6);
public void vote(){
int randomNr = (int) (Math.random()*6);
vote = randomNr;
hasVoted = true;
LOGGER.info("HumanNPC at Position: " + this.getPosition() + " has voted for: " + vote);
}
public void noise() {

View File

@ -32,7 +32,7 @@ public class HumanPlayer extends Human {
@Override
public void send(String msg, Game game) {
String formattedMsg = ServerGameInfoHandler.format(msg, game);
String formattedMsg = ServerGameInfoHandler.format(msg,this, game);
clientHandler.sendMsgToClient(formattedMsg);
}
@ -42,10 +42,12 @@ public class HumanPlayer extends Human {
*/
@Override
public void getVoteFromClientHandler() {
vote = clientHandler.getVote();
hasVoted = clientHandler.getHasVoted();
clientHandler.setVote(Integer.MAX_VALUE);
clientHandler.setHasVoted(false);
LOGGER.info("method was called by: " + position);
vote = clientHandler.getVote()[position];
LOGGER.info("Human at Pos: " + position + " has voted for: " + vote);
hasVoted = clientHandler.getHasVoted()[position];
clientHandler.setVote(position,Integer.MAX_VALUE);
clientHandler.setHasVoted(position,false);
/*
* if vote wasn't valid, make sure, the passenger field hasVoted == false, probably redundant but better be safe than sorry
*/

View File

@ -28,7 +28,7 @@ public class Passenger {
**/
public void send(String msg, Game game) {
if (isPlayer) {
String formattedMsg = ServerGameInfoHandler.format(msg,game);
String formattedMsg = ServerGameInfoHandler.format(msg,this,game);
clientHandler.sendMsgToClient(formattedMsg);
}
LOGGER.warn("This object should not just be a passenger. Position:" + position);
@ -113,6 +113,7 @@ public class Passenger {
* When called by NPC nothing should happen, because clientHandler = null
*/
public void getVoteFromClientHandler() {
LOGGER.debug("a NPC called this method hopefully: " + position);
}
}

View File

@ -5,6 +5,7 @@ import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.ClientPinger;
import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.Protocol;
import ch.unibas.dmi.dbis.cs108.multiplayer.server.JServerProtocolParser;
import java.net.Socket;
import java.io.*;
import java.net.UnknownHostException;
@ -77,6 +78,9 @@ public class Client {
*/
public void voteGetter(String msg) {
int msgIndex = msg.indexOf('$');
String position = msg.substring(0, msgIndex);;
msg = msg.substring(msgIndex + 1);
Scanner userInput = new Scanner(System.in);
//TODO(Seraina): implement
System.out.println(msg);
@ -91,10 +95,9 @@ public class Client {
LOGGER.warn(e.getMessage());
System.out.println("Invalid vote");
input = String.valueOf(Integer.MAX_VALUE);
} finally {
sendMsgToServer(Protocol.votedFor + "$" + input);
}
sendMsgToServer(Protocol.votedFor + "$" + position + "$" + input);
LOGGER.info("msg to server is: " + Protocol.votedFor + "$" + position + "$" + input);
}

View File

@ -44,10 +44,12 @@ public class JClientProtocolParser {
break;
case Protocol.serverRequestsGhostVote:
System.out.println("Ghost received Vote request");
c.voteGetter(msg.substring(6));
//TODO(Seraina): How can be enforced, that clients won't vote otherwise? Trigger a methode here that listens to input
break;
case Protocol.serverRequestsHumanVote:
System.out.println("Human received Vote request");
LOGGER.info("Human received Vote request");
c.voteGetter(msg.substring(6));
//TODO(Seraina): How can be enforced, that clients won't vote otherwise? Trigger a methode here that listens to input
break;
default:

View File

@ -56,9 +56,8 @@ public class ServerPinger implements Runnable {
System.out.println(
"Lost connection to user " + c.getClientUserName() + ". Waiting to reconnect...");
} else {
c.disconnectClient();
LOGGER.debug(
"gotPingBack has not been set to true and isConnected has been set to false before");
//c.disconnectClient();
//LOGGER.debug("gotPingBack has not been set to true and isConnected has been set to false before");
}
}
}

View File

@ -6,6 +6,7 @@ import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.ServerPinger;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
import org.apache.logging.log4j.LogManager;
@ -35,8 +36,8 @@ public class ClientHandler implements Runnable {
public static HashSet<ClientHandler> disconnectedClients = new HashSet<>(); //todo: implement re-connection
public static HashSet<ClientHandler> lobby = new HashSet<>();
public static HashSet<ClientHandler> ghostClients = new HashSet<>();
private int vote; //saves vote of clientHandler for later transmission to passenger, by default MAX_VALUE
private boolean hasVoted; //saves hasVoted status of clientHandler for later transmission to passenger, by default false
private int[] vote; //saves vote of clientHandler for later transmission to passenger, by default MAX_VALUE, index corresponds to Passenger position
private boolean[] hasVoted; //saves hasVoted status of clientHandler for later transmission to passenger, by default false, index corresponds to Passenger position
/**
* Implements the login logic in client-server architecture.
@ -51,8 +52,10 @@ public class ClientHandler implements Runnable {
this.in = new BufferedReader(new InputStreamReader((socket.getInputStream())));
this.loggedIn = false;
this.clientUserName = nameDuplicateChecker.checkName("U.N. Owen");
this.vote = Integer.MAX_VALUE;
this.hasVoted = false;
int[] h = new int[1000];
Arrays.fill(h,Integer.MAX_VALUE);
this.vote = h;
this.hasVoted = new boolean[1000];
connectedClients.add(this);
serverPinger = new ServerPinger(socket, this);
Thread sP = new Thread(serverPinger);
@ -91,11 +94,11 @@ public class ClientHandler implements Runnable {
return loggedIn;
}
public int getVote() {
public int[] getVote() {
return vote;
}
public boolean getHasVoted() {
public boolean[] getHasVoted() {
return hasVoted;
}
@ -108,12 +111,12 @@ public class ClientHandler implements Runnable {
this.loggedIn = loggedIn;
}
public void setVote(int vote) {
this.vote = vote;
public void setVote(int position, int vote) {
this.vote[position] = vote;
}
public void setHasVoted(boolean hasVoted) {
this.hasVoted = hasVoted;
public void setHasVoted(int position, boolean hasVoted) {
this.hasVoted[position] = hasVoted;
}
@Override

View File

@ -32,6 +32,9 @@ public class JServerProtocolParser {
String header = ""; //"header" is the first 5 characters, i.e. the protocol part
try {
header = msg.substring(0, 5);
if(!header.equals(Protocol.pingBack) &&!header.equals(Protocol.pingFromClient)) { //for debuging without constant pings
LOGGER.debug("got message: " + msg + ".");
}
} catch (IndexOutOfBoundsException e) {
System.out.println("Received unknown command");
}
@ -70,16 +73,21 @@ public class JServerProtocolParser {
LOGGER.debug(Protocol.listLobbies + " command received from: " + h.getClientUserName());
break;
case Protocol.votedFor:
msg = msg.substring(6);
int msgIndex = msg.indexOf('$');
int vote = Integer.MAX_VALUE;
int position = 0;
LOGGER.debug("Message is " + msg.substring(6));
try {
vote = Integer.parseInt(msg.substring(6));
position = Integer.parseInt(msg.substring(0,msgIndex));
vote = Integer.parseInt(msg.substring(msgIndex + 1));
} catch (Exception e) {
LOGGER.warn("Invalid vote " + e.getMessage());
} finally {
if(vote != Integer.MAX_VALUE) { //gets MAX_VALUE when the vote wasn't valid
h.setVote(vote);
h.setHasVoted(true);
}
}
if(vote != Integer.MAX_VALUE) { //gets MAX_VALUE when the vote wasn't valid
h.setVote(position,vote);
LOGGER.debug("Player vote: " + vote);
h.setHasVoted(position,true);
}
break;
case Protocol.startANewGame: