Add: initial client structure for game and network
This commit is contained in:
committed by
Mathis Ginkel
parent
f5138503cb
commit
79bd33ad75
@@ -0,0 +1,9 @@
|
||||
package ch.unibas.dmi.dbis.cs108.casono.client.game;
|
||||
|
||||
/**
|
||||
* Represents a playing card with a value and suit.
|
||||
*/
|
||||
public class Card {
|
||||
public String value;
|
||||
public String suit;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package ch.unibas.dmi.dbis.cs108.casono.client.game;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.casono.client.game.Card;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.client.game.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents the current state of the poker game, including the phase, pot
|
||||
* size, current bet, dealer position,
|
||||
* active player, community cards, and player information.
|
||||
*/
|
||||
public class GameState {
|
||||
public String phase;
|
||||
public int pot;
|
||||
public int currentBet;
|
||||
public int dealer;
|
||||
public int activePlayer;
|
||||
|
||||
public List<Card> communityCards = new ArrayList<>();
|
||||
public List<Player> players = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package ch.unibas.dmi.dbis.cs108.casono.client.game;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a player in the poker game, including their name, chip count,
|
||||
* current bet, state (e.g., "active", "folded"), and their hole cards.
|
||||
*/
|
||||
public class Player {
|
||||
public String name;
|
||||
public int chips;
|
||||
public int bet;
|
||||
public String state;
|
||||
|
||||
public List<Card> cards = new ArrayList<>();
|
||||
}
|
||||
@@ -5,36 +5,52 @@ import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The ChatClient class is responsible for sending messages to the server and
|
||||
* retrieving messages from the server. It uses the ClientService to send
|
||||
* commands and receive responses from the server.
|
||||
*/
|
||||
public class ChatClient {
|
||||
|
||||
private ClientService clientService;
|
||||
|
||||
/**
|
||||
* Constructs a ChatClient with the given ClientService for communication.
|
||||
*
|
||||
* @param clientService The ClientService instance used to send commands and
|
||||
* receive responses from the server.
|
||||
*/
|
||||
public ChatClient(ClientService clientService) {
|
||||
this.clientService = clientService;
|
||||
}
|
||||
|
||||
/**
|
||||
* sends a message to the server
|
||||
* @param message
|
||||
* Send a Message to the server by converting it to a string format and
|
||||
* sending a "SEND_MESSAGE" command with the message content as arguments.
|
||||
*
|
||||
* @param message The Message object to be sent to the server.
|
||||
*/
|
||||
|
||||
public void sendMessage(Message message) {
|
||||
String request = "SEND_MESSAGE " + message.toArgsString();
|
||||
clientService.processCommand(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a Request to get the number of Messages currently in the Queue for the client.
|
||||
* Then proceeds, if needed, to get the messages by sending
|
||||
* Retrieve messages from the server by first sending a "GET_MESSAGE_COUNT"
|
||||
* command to determine how many messages are available and then sending
|
||||
* "GET_NEXT_MESSAGE" commands in a loop to retrieve each message. The
|
||||
* retrieved messages are parsed into Message objects and returned as a list.
|
||||
*
|
||||
* @return A list of Message objects representing the messages retrieved from
|
||||
* the server.
|
||||
*/
|
||||
|
||||
public List<Message> getMessages() {
|
||||
String countStr = clientService.processCommand("GET_MESSAGE_COUNT");
|
||||
int count = Integer.parseInt(countStr);
|
||||
System.out.println("Got " + count + " messages");
|
||||
List<Message> messages = new ArrayList<>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
String message = clientService.processCommand("GET_NEXT_MESSAGE");
|
||||
String message = clientService.processCommand("GET_NEXT_MESSAGE");
|
||||
if (message != null) {
|
||||
Message message1 = Message.toMessage(message);
|
||||
messages.add(message1);
|
||||
|
||||
@@ -16,8 +16,11 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Responsible for the transferring of the data from the Client to the Server and the other way
|
||||
* around
|
||||
* The ClientService class is responsible for managing the connection to the
|
||||
* server,
|
||||
* sending commands, and receiving responses. It uses a TcpTransport to
|
||||
* communicate
|
||||
* with the server and an ExecutorService to handle asynchronous requests.
|
||||
*/
|
||||
public class ClientService {
|
||||
|
||||
@@ -29,13 +32,13 @@ public class ClientService {
|
||||
public static ArrayList<String> response;
|
||||
private final AtomicInteger idGenerator;
|
||||
private final Logger logger;
|
||||
|
||||
/**
|
||||
* Creates a new ClientSession with a Socket, a Reader and Writer of the Input- and the
|
||||
* Outputstream and a pool of threads to send requests and receive responses.
|
||||
/*
|
||||
* Constructs a ClientService with the given server IP and port. It establishes
|
||||
* a socket connection to the server and initializes the TcpTransport and
|
||||
* ExecutorService for communication.
|
||||
*
|
||||
* @param ip : ip-adress of the server
|
||||
* @param port : port of the server
|
||||
* @param ip The IP address of the server to connect to.
|
||||
* @param port The port number of the server to connect to.
|
||||
*/
|
||||
public ClientService(String ip, int port) {
|
||||
|
||||
@@ -55,7 +58,6 @@ public class ClientService {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends the Requests to the server and waits for the response If the response is "+OK" it
|
||||
* proceeds normal If the response "-ERROR" it throws a runtime exception
|
||||
@@ -88,7 +90,13 @@ public class ClientService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param request
|
||||
* Helper method to send a request to the server using the ExecutorService. It
|
||||
* submits the request as a Runnable task and waits for its completion. If
|
||||
* the task is interrupted or encounters an execution exception, it throws a
|
||||
* RuntimeException with the appropriate cause.
|
||||
*
|
||||
* @param request The Runnable task representing the request to be sent to the
|
||||
* server.
|
||||
*/
|
||||
private void sendRequest(Runnable request) {
|
||||
Future<?> future = executor.submit(request);
|
||||
@@ -102,10 +110,14 @@ public class ClientService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Runtime Exceptions thrown by the sendRequest method
|
||||
* Helper method to extract the cause of an exception and return it as a
|
||||
* RuntimeException. If the cause is null, it returns the original exception as
|
||||
* a RuntimeException. If the cause is already a RuntimeException, it returns
|
||||
* it directly. Otherwise, it wraps the cause in a new RuntimeException and
|
||||
* returns it.
|
||||
*
|
||||
* @param e - an Exception
|
||||
* @return - a Runtime Exception
|
||||
* @param e The exception from which to extract the cause.
|
||||
* @return A RuntimeException representing the cause of the original exception.
|
||||
*/
|
||||
private static RuntimeException getRuntimeException(Exception e) {
|
||||
Throwable reason = e.getCause();
|
||||
@@ -119,7 +131,12 @@ public class ClientService {
|
||||
return re;
|
||||
}
|
||||
|
||||
/** Closes the Socket and shuts down the Threadpool associated with that Socket-Connection. */
|
||||
/**
|
||||
* Closes the socket connection to the server and shuts down the
|
||||
* ExecutorService.
|
||||
* It also closes the TcpTransport used for communication. If any IOException
|
||||
* occurs during this process, it prints the exception to the console.
|
||||
*/
|
||||
public void closeSocket() {
|
||||
try {
|
||||
executor.shutdown();
|
||||
|
||||
@@ -1,17 +1,39 @@
|
||||
package ch.unibas.dmi.dbis.cs108.casono.client.network;
|
||||
|
||||
/**
|
||||
* The CoreClient class provides basic functionalities for communicating with
|
||||
* the
|
||||
* server, such as sending a ping command to check connectivity and logging in
|
||||
* with a username. It uses the ClientService to send commands and receive
|
||||
* responses from the server.
|
||||
*/
|
||||
public class CoreClient {
|
||||
private final ClientService clientService;
|
||||
|
||||
/**
|
||||
* Constructs a CoreClient with the given ClientService for communication.
|
||||
*
|
||||
* @param clientservice The ClientService instance used to send commands and
|
||||
* receive responses from the server.
|
||||
*/
|
||||
public CoreClient(ClientService clientservice) {
|
||||
this.clientService = clientservice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a "PING" command to the server to check connectivity. The server
|
||||
* should respond with a "PONG" message if the connection is successful.
|
||||
*/
|
||||
public void ping() {
|
||||
clientService.processCommand("PING");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs in to the server with the given username by sending a "LOGIN" command.
|
||||
*
|
||||
* @param user The username to log in with.
|
||||
*/
|
||||
public void login(String user) {
|
||||
clientService.processCommand("LOGIN USERNAME=" + user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
package ch.unibas.dmi.dbis.cs108.casono.client.network;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.casono.client.game.Card;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.client.game.GameState;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.client.game.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The GameClient class is responsible for communicating with the server to
|
||||
* retrieve the current game state. It sends a command to the server and
|
||||
* parses the response into a structured GameState object.
|
||||
*/
|
||||
public class GameClient {
|
||||
|
||||
private final ClientService client;
|
||||
|
||||
/**
|
||||
* Constructs a GameClient with the given ClientService for communication.
|
||||
*
|
||||
* @param client The ClientService instance used to send commands and receive
|
||||
* responses from the server.
|
||||
*/
|
||||
public GameClient(ClientService client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current game state from the server by sending a command and
|
||||
* parsing the response.
|
||||
*
|
||||
* @return A GameState object representing the current state of the game.
|
||||
*/
|
||||
public GameState getGameState() {
|
||||
String response = client.processCommand("GET_GAME_STATE");
|
||||
return parseGameState(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the raw response from the server into a structured GameState object.
|
||||
*
|
||||
* @param input The raw response string from the server.
|
||||
* @return A GameState object representing the current state of the game.
|
||||
*/
|
||||
private GameState parseGameState(String input) {
|
||||
|
||||
GameState state = new GameState();
|
||||
|
||||
String[] lines = input.split("\n");
|
||||
|
||||
Player currentPlayer = null;
|
||||
Card currentCard = null;
|
||||
|
||||
for (String rawLine : lines) {
|
||||
|
||||
String line = rawLine.trim();
|
||||
|
||||
if (line.startsWith("+OK") || line.equals("END")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.startsWith("PHASE=")) {
|
||||
state.phase = line.split("=")[1];
|
||||
}
|
||||
|
||||
else if (line.startsWith("POT=")) {
|
||||
state.pot = Integer.parseInt(line.split("=")[1]);
|
||||
}
|
||||
|
||||
else if (line.startsWith("CURRENT_BET=")) {
|
||||
state.currentBet = Integer.parseInt(line.split("=")[1]);
|
||||
}
|
||||
|
||||
else if (line.startsWith("DEALER=")) {
|
||||
state.dealer = Integer.parseInt(line.split("=")[1]);
|
||||
}
|
||||
|
||||
else if (line.startsWith("ACTIVE_PLAYER=")) {
|
||||
state.activePlayer = Integer.parseInt(line.split("=")[1]);
|
||||
}
|
||||
|
||||
else if (line.startsWith("PLAYER")) {
|
||||
currentPlayer = new Player();
|
||||
state.players.add(currentPlayer);
|
||||
}
|
||||
|
||||
else if (line.startsWith("NAME=") && currentPlayer != null) {
|
||||
currentPlayer.name = line.split("=")[1];
|
||||
}
|
||||
|
||||
else if (line.startsWith("CHIPS=") && currentPlayer != null) {
|
||||
currentPlayer.chips = Integer.parseInt(line.split("=")[1]);
|
||||
}
|
||||
|
||||
else if (line.startsWith("BET=") && currentPlayer != null) {
|
||||
currentPlayer.bet = Integer.parseInt(line.split("=")[1]);
|
||||
}
|
||||
|
||||
else if (line.startsWith("STATE=") && currentPlayer != null) {
|
||||
currentPlayer.state = line.split("=")[1];
|
||||
}
|
||||
|
||||
else if (line.startsWith("CARD")) {
|
||||
currentCard = new Card();
|
||||
|
||||
if (currentPlayer != null) {
|
||||
currentPlayer.cards.add(currentCard);
|
||||
} else {
|
||||
state.communityCards.add(currentCard);
|
||||
}
|
||||
}
|
||||
|
||||
else if (line.startsWith("VALUE=") && currentCard != null) {
|
||||
currentCard.value = line.split("=")[1];
|
||||
}
|
||||
|
||||
else if (line.startsWith("SUIT=") && currentCard != null) {
|
||||
currentCard.suit = line.split("=")[1];
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package ch.unibas.dmi.dbis.cs108.casono.client.network;
|
||||
|
||||
/**
|
||||
* The LobbyClient class is responsible for communicating with the server to
|
||||
* manage game lobbies. It provides methods to create a lobby, join a lobby,
|
||||
* and fetch the current status of a lobby by sending appropriate commands to
|
||||
* the server and processing the responses.
|
||||
*/
|
||||
public class LobbyClient {
|
||||
private final ClientService client;
|
||||
|
||||
/**
|
||||
* Constructs a LobbyClient with the given ClientService for communication.
|
||||
*
|
||||
* @param client The ClientService instance used to send commands and receive
|
||||
* responses from the server.
|
||||
*/
|
||||
public LobbyClient(ClientService client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the current status of the lobby with the given id from the server.
|
||||
*
|
||||
* @param lobbyId The id of the lobby to fetch the status for.
|
||||
* @return A string representing the current status of the lobby, as returned
|
||||
* by the server.
|
||||
*/
|
||||
public String fetchLobbyStatusString(int lobbyId) {
|
||||
return client.processCommand("GET_LOBBY_STATUS ID=" + lobbyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the server to create a new lobby and return the id of the newly
|
||||
* created lobby.
|
||||
*
|
||||
* @return The id of the newly created lobby, as returned by the server.
|
||||
*/
|
||||
public int createLobby() {
|
||||
String response = client.processCommand("CREATE_LOBBY");
|
||||
return Integer.parseInt(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the server to return the id of the lobby that the client is
|
||||
* currently in.
|
||||
*
|
||||
* @return The id of the lobby that the client is currently in, as returned by
|
||||
* the server.
|
||||
*/
|
||||
public int getLobbyId() {
|
||||
String response = client.processCommand("GET_LOBBY_ID");
|
||||
return Integer.parseInt(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the server to join the lobby with the given id.
|
||||
*
|
||||
* @param lobbyId The id of the lobby to join.
|
||||
*/
|
||||
public void joinLobby(int lobbyId) {
|
||||
client.processCommand("JOIN_LOBBY ID=" + lobbyId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user