Make fit for beta release (#51)

* removed

* edited a lot of stuff
This commit is contained in:
Valentin Heiserer
2024-04-26 01:41:50 +02:00
committed by GitHub
parent 2e5a42b6d3
commit 539e29dc56
94 changed files with 843 additions and 8636 deletions

View File

@@ -48,15 +48,13 @@ public class BackendServer implements MessageSender {
// Configure CORS settings
configureCors(context);
if (openFrontend) {
URL webContentUrl = getClass().getClassLoader().getResource("web-content");
if (webContentUrl == null) {
throw new RuntimeException("Unable to find 'web-content' directory");
}
String webContentPath = webContentUrl.toExternalForm();
context.setResourceBase(webContentPath);
context.addServlet(new ServletHolder("frontend", DefaultServlet.class), "/");
URL webContentUrl = getClass().getClassLoader().getResource("web-content");
if (webContentUrl == null) {
throw new RuntimeException("Unable to find 'web-content' directory");
}
String webContentPath = webContentUrl.toExternalForm();
context.setResourceBase(webContentPath);
context.addServlet(new ServletHolder("frontend", DefaultServlet.class), "/");
// Configure specific websocket behavior
JettyWebSocketServletContainerInitializer.configure(

View File

@@ -1,6 +1,5 @@
package org.schafkopf;
import com.google.gson.JsonObject;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
import org.eclipse.jetty.websocket.api.Session;
@@ -13,7 +12,6 @@ import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.schafkopf.SchafkopfMessage.SchafkopfBaseMessage;
import org.schafkopf.SchafkopfMessage.SchafkopfMessageOrigin;
import org.schafkopf.SchafkopfMessage.SchafkopfMessageType;
/**
* Main Class that represents the Backend Server.
@@ -75,7 +73,6 @@ public class DedicatedServerConnection implements MessageSender {
try {
session.getRemote().sendString(
new SchafkopfMessage(SchafkopfMessageOrigin.BACKEND, message).getMessageAsString());
System.out.println("Sent message to server: " + message);
} catch (Exception e) {
System.err.println("Error sending message: " + e.getMessage());
}
@@ -116,26 +113,5 @@ public class DedicatedServerConnection implements MessageSender {
}
});
connectionThread.start();
start();
}
/**
* Class that represents one Frontend Connection.
*/
public void start() {
JsonObject messageObject = new JsonObject();
messageObject.addProperty("message_type", "START_GAME");
sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.START_GAME));
}
/**
* Class that represents one Frontend Connection.
*/
public void join() {
JsonObject messageObject = new JsonObject();
messageObject.addProperty("message_type", "JOIN_GAME");
sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.JOIN_GAME));
}
}

View File

@@ -32,49 +32,90 @@ public class SchafkopfClient implements MessageListener {
public void receiveMessage(String jsonMessage) {
Gson gson = new Gson();
JsonObject jsonObject = gson.fromJson(jsonMessage, JsonObject.class);
// Check if the origin is "frontend"
// Check if the origin is "frontend" or "dedicated_server"
String origin = jsonObject.get("origin").getAsString();
if (SchafkopfMessageOrigin.FRONTEND.toString().equals(origin)) {
JsonObject message = jsonObject.getAsJsonObject("message");
JsonObject content = message.getAsJsonObject("content");
String messageType = message.get("message_type").getAsString();
if (SchafkopfMessageType.REQUEST_SERVER_CONNECTION.toString().equals(messageType)) {
switch (SchafkopfMessageOrigin.valueOf(origin)) {
case FRONTEND:
handleFrontendMessage(jsonObject);
break;
case DEDICATED_SERVER:
handleDedicatedServerMessage(jsonObject);
break;
default:
// Handle messages from unknown origins
System.out.println("Received message from unknown origin: " + origin);
break;
}
}
private void handleFrontendMessage(JsonObject jsonObject) {
JsonObject message = jsonObject.getAsJsonObject("message");
JsonObject content = message.getAsJsonObject("content");
String messageType = message.get("message_type").getAsString();
switch (SchafkopfMessageType.valueOf(messageType)) {
case REQUEST_SERVER_CONNECTION:
dedicatedServerConnection = new DedicatedServerConnection(
content.get("serverAddress").getAsString(),
this);
} else if ("JOIN_GAME".equals(messageType)) {
dedicatedServerConnection.join();
} else if ("START_DEDICATED_GAME".equals(messageType)) {
dedicatedServerConnection.start();
} else if (SchafkopfMessageType.PLAYER_CARD.toString().equals(messageType)) {
break;
case PLAYER_CARD:
case CREATE_ONLINE_GAME:
case JOIN_ONLINE_GAME:
case SET_PLAYER_NAME:
dedicatedServerConnection.sendMessage(
new SchafkopfBaseMessage(SchafkopfMessageType.PLAYER_CARD, content));
}
new SchafkopfBaseMessage(SchafkopfMessageType.valueOf(messageType), content));
break;
case LIST_ONLINE_GAMES:
case GET_ONLINE_GAME:
case SET_STATUS_READY:
case LEAVE_ONLINE_GAME:
case START_DEDICATED_GAME:
dedicatedServerConnection.sendMessage(
new SchafkopfBaseMessage(SchafkopfMessageType.valueOf(messageType)));
break;
default:
// Handle unknown message types
System.out.println("Received unknown message type from frontend server: " + messageType);
break;
}
System.out.println("Received message from frontend server: " + jsonMessage);
System.out.println("Received message from frontend: " + jsonObject);
}
} else if (SchafkopfMessageOrigin.DEDICATED_SERVER.toString().equals(origin)) {
private void handleDedicatedServerMessage(JsonObject jsonObject) {
JsonObject message = jsonObject.getAsJsonObject("message");
JsonObject content = message.getAsJsonObject("content");
String messageType = message.get("message_type").getAsString();
JsonObject message = jsonObject.getAsJsonObject("message");
JsonObject content = message.getAsJsonObject("content");
String messageType = message.get("message_type").getAsString();
if (SchafkopfMessageType.GET_CARD_ONLINE_PLAYER.toString().equals(messageType)) {
System.out.println("Received get_card_online_player message from dedicated server.");
} else if (SchafkopfMessageType.GAME_STATE.toString().equals(messageType)) {
switch (SchafkopfMessageType.valueOf(messageType)) {
case GET_CARD_ONLINE_PLAYER:
case HEARTBEAT_ACK:
break;
case GAME_STATE:
case ONLINE_PLAYER_HAND:
case UNKNOWN_ERROR:
case INFO_MESSAGE:
case GET_ONLINE_GAME:
case LIST_ONLINE_GAMES:
backendServer.sendMessage(
new SchafkopfBaseMessage(SchafkopfMessage.SchafkopfMessageType.GAME_STATE, content));
} else if (SchafkopfMessageType.ONLINE_PLAYER_HAND.toString().equals(messageType)) {
new SchafkopfBaseMessage(SchafkopfMessageType.valueOf(messageType), content));
break;
case SERVER_CONNECTION_SUCCESSFUL:
case GAME_START_READY:
backendServer.sendMessage(
new SchafkopfBaseMessage(SchafkopfMessage.SchafkopfMessageType.ONLINE_PLAYER_HAND,
content));
} else if (SchafkopfMessageType.SERVER_CONNECTION_SUCCESSFUL.toString().equals(messageType)) {
System.out.println("Received server_connection_successful message from dedicated server.");
backendServer.sendMessage(new SchafkopfBaseMessage(
SchafkopfMessage.SchafkopfMessageType.SERVER_CONNECTION_SUCCESSFUL));
} else if (SchafkopfMessageType.HEARTBEAT_ACK.toString().equals(messageType)) {
return;
}
System.out.println("Received message from dedicated server: " + jsonMessage);
new SchafkopfBaseMessage(SchafkopfMessageType.valueOf(messageType)));
break;
default:
// Handle unknown message types
System.out.println("Received unknown message type from dedicated server: " + messageType);
break;
}
if (!messageType.equals("HEARTBEAT_ACK")) {
System.out.println("Received message from dedicated server: " + jsonObject);
}
}
}

View File

@@ -1,6 +1,5 @@
package org.schafkopf.player;
import org.schafkopf.BackendServer;
import org.schafkopf.cardreader.CardReader;
import org.schafkopf.karte.Karte;
import org.schafkopf.karte.KartenListe;
@@ -15,6 +14,7 @@ public class LocalPlayer extends Player {
private final CardReader cardReader;
public LocalPlayer(CardReader cardReader) {
super("Local Player");
this.cardReader = cardReader;
}
@@ -23,7 +23,9 @@ public class LocalPlayer extends Player {
return wartetAufKarte();
}
/** Waits for a Card and returns a Karte Object. */
/**
* Waits for a Card and returns a Karte Object.
*/
private Karte wartetAufKarte() {
String uid = null;
System.out.println("Starte Warten auf Karte");

View File

@@ -1,5 +1,6 @@
package org.schafkopf;
import com.google.gson.JsonArray;
import jakarta.servlet.DispatcherType;
import java.net.DatagramSocket;
import java.net.InetAddress;
@@ -16,6 +17,7 @@ import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlets.CrossOriginFilter;
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
import org.schafkopf.SchafkopfException.NoGameSessionException;
/**
* Main Class that represents the Backend Server.
@@ -29,8 +31,6 @@ public class DedicatedServer {
private final List<GameSession> gameSessions = new ArrayList<>();
private GameSession currentGameSession;
/**
* Creates an Instance of the Backend Server.
*/
@@ -73,10 +73,8 @@ public class DedicatedServer {
wsContainer.setMaxTextMessageSize(65535);
wsContainer.setIdleTimeout(Duration.ofDays(300000));
// Add websockets
wsContainer.addMapping("/*", new FrontendEndpointCreator(this));
wsContainer.addMapping("/*", new SchafkopfClientConnectionCreator(this));
});
currentGameSession = new GameSession();
}
/**
@@ -126,7 +124,44 @@ public class DedicatedServer {
return gameSessions;
}
public GameSession getCurrentGameSession() {
return currentGameSession;
/**
* The main entrypoint of the Application.
*/
public JsonArray getGameSessionsAsJson() throws NoGameSessionException {
if (gameSessions.isEmpty()) {
throw new NoGameSessionException();
}
JsonArray gameSessionsJson = new JsonArray();
for (GameSession gameSession : gameSessions) {
gameSessionsJson.add(gameSession.getJson());
}
return gameSessionsJson;
}
/**
* The main entrypoint of the Application.
*/
public GameSession getCurrentGameSession() throws NoGameSessionException {
if (gameSessions.isEmpty()) {
throw new NoGameSessionException();
}
return gameSessions.get(gameSessions.size() - 1);
}
/**
* The main entrypoint of the Application.
*/
public GameSession getGameSessionByName(String gameId) throws NoGameSessionException {
for (GameSession gameSession : gameSessions) {
if (gameSession.getServerName().equals(gameId)) {
return gameSession;
}
}
throw new NoGameSessionException();
}
public void removeGameSession(GameSession gameSession) {
gameSessions.remove(gameSession);
}
}

View File

@@ -1,68 +1,108 @@
package org.schafkopf;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.util.ArrayList;
import java.util.List;
import org.schafkopf.SchafkopfException.NotEnoughPlayersException;
import org.schafkopf.SchafkopfException.PlayerNotReadyException;
import org.schafkopf.SchafkopfMessage.SchafkopfBaseMessage;
import org.schafkopf.SchafkopfMessage.SchafkopfMessageType;
import org.schafkopf.player.BotPlayer;
import org.schafkopf.player.OnlinePlayer;
import org.schafkopf.player.Player;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The main entrypoint of the Application.
*/
public class GameSession implements MessageSender {
private static final Logger logger = LoggerFactory.getLogger(GameSession.class);
private Schafkopf schafkopf;
private List<Player> player;
private List<SchafkopfClientConnection> clients;
private Thread spielThread;
private String serverName;
private DedicatedServer dedicatedServer;
/**
* The main entrypoint of the Application.
*/
public GameSession() {
player = new ArrayList<>();
clients = new ArrayList<>();
public GameSession(String serverName, DedicatedServer dedicatedServer) {
this.dedicatedServer = dedicatedServer;
this.serverName = serverName;
this.clients = new ArrayList<>();
logger.info(serverName + " created.");
}
/**
* Class that represents one Frontend Connection.
*/
public void addPlayer(SchafkopfClientConnection client) {
if (this.player.size() >= 4) {
if (this.clients.size() >= 4) {
throw new RuntimeException("Game is full");
}
System.out.println("Adding player to game: " + client);
logger.info("Adding player to game: " + client);
clients.add(client);
OnlinePlayer onlinePlayer = new OnlinePlayer(client);
this.player.add(onlinePlayer);
OnlinePlayer onlinePlayer = new OnlinePlayer(client, client.getName());
client.setOnlinePlayer(onlinePlayer);
this.sendSessionInfo();
}
public Schafkopf getSchafkopf() {
return schafkopf;
/**
* Class that represents one Frontend Connection.
*/
public void removePlayer(SchafkopfClientConnection client) {
logger.info("Removing player from game: " + client);
clients.remove(client);
if (clients.isEmpty()) {
logger.info("No players left in game: " + serverName);
if (spielThread != null) {
spielThread.interrupt();
}
this.dedicatedServer.removeGameSession(this);
return;
}
this.sendSessionInfo();
}
void startGame() throws NotEnoughPlayersException {
int playerCount = this.player.size();
System.out.println("Starting game with " + playerCount + " players");
if (playerCount < 4) {
for (int i = 0; i < 4 - playerCount; i++) {
this.player.add(new BotPlayer());
void startGame() throws PlayerNotReadyException {
logger.info("Starting game: " + serverName + " with " + clients.size() + " players");
List<Player> players = new ArrayList<>();
for (SchafkopfClientConnection client : clients) {
players.add(client.getOnlinePlayer());
}
for (int i = players.size(); i < 4; i++) {
players.add(new BotPlayer("Bot " + i));
}
for (SchafkopfClientConnection client : clients) {
if (!client.isReady()) {
throw new PlayerNotReadyException();
}
}
System.out.println("Starting game with, now: " + this.player.size() + " players");
sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.GAME_START_READY));
//wait for 5 seconds
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
spielThread = new Thread(() -> {
try {
schafkopf = new Schafkopf(this.player.toArray(new Player[0]), this);
schafkopf = new Schafkopf(players.toArray(Player[]::new), this);
schafkopf.startGame();
clients.forEach(client -> client.resetReady());
} catch (NotEnoughPlayersException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
@@ -72,15 +112,65 @@ public class GameSession implements MessageSender {
spielThread.start();
// schafkopf = new Schafkopf(this.player.toArray(new Player[0]), this);
}
@Override
public void sendMessage(SchafkopfBaseMessage message) {
System.out.println("Sending message to Client: " + message);
for (SchafkopfClientConnection client : clients) {
client.sendMessage(message);
}
}
/**
* The main entrypoint of the Application.
*/
public JsonObject getJson() {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("serverName", serverName);
jsonObject.addProperty("playerCount", getPlayerCount());
// Create an array to hold player information
JsonArray playersArray = new JsonArray();
for (SchafkopfClientConnection client : clients) {
JsonObject playerObject = new JsonObject();
playerObject.addProperty("playerName",
client.getName()); // Assuming you have a method to get player name
playerObject.addProperty("isReady",
client.isReady()); // Assuming you have a method to check player readiness
playersArray.add(playerObject);
}
for (int i = clients.size(); i < 4; i++) {
JsonObject playerObject = new JsonObject();
playerObject.addProperty("playerName",
"Bot " + i); // Assuming you have a method to get player name
playerObject.addProperty("isReady",
true);
playerObject.addProperty("isBot",
true);
playersArray.add(playerObject);
}
jsonObject.add("players", playersArray);
return jsonObject;
}
public String getServerName() {
return serverName;
}
public int getPlayerCount() {
return clients.size();
}
/**
* Class that represents one Frontend Connection.
*/
public void sendSessionInfo() {
JsonObject messageObject2 = new JsonObject();
messageObject2.add("game", this.getJson());
sendMessage(
new SchafkopfBaseMessage(SchafkopfMessageType.GET_ONLINE_GAME,
messageObject2));
}
}

View File

@@ -6,18 +6,21 @@ import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
import org.schafkopf.SchafkopfException.NotEnoughPlayersException;
import org.schafkopf.SchafkopfException.NoGameSessionException;
import org.schafkopf.SchafkopfMessage.SchafkopfBaseMessage;
import org.schafkopf.SchafkopfMessage.SchafkopfMessageOrigin;
import org.schafkopf.SchafkopfMessage.SchafkopfMessageType;
import org.schafkopf.karte.Karte;
import org.schafkopf.player.OnlinePlayer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class that represents one Frontend Connection.
*/
public class SchafkopfClientConnection extends WebSocketAdapter implements MessageSender {
private static final Logger logger = LoggerFactory.getLogger(SchafkopfClientConnection.class);
private final CountDownLatch connectionLatch;
private final CountDownLatch closureLatch = new CountDownLatch(1);
private DedicatedServer dedicatedServer;
@@ -28,13 +31,15 @@ public class SchafkopfClientConnection extends WebSocketAdapter implements Messa
private OnlinePlayer onlinePlayer;
private boolean ready = false;
private String name = "player";
/**
* Class that represents one Frontend Connection.
*/
public SchafkopfClientConnection(DedicatedServer dedicatedServer) {
this.dedicatedServer = dedicatedServer;
this.connectionLatch = new CountDownLatch(1);
System.out.println("new ClientConnection created.");
}
@Override
@@ -42,8 +47,7 @@ public class SchafkopfClientConnection extends WebSocketAdapter implements Messa
this.session = session;
super.onWebSocketConnect(session);
String clientIp = session.getRemoteAddress().toString();
System.out.println("Endpoint connected from ip: " + clientIp);
logger.info("Endpoint connected from ip: " + clientIp);
connectionLatch.countDown();
dedicatedServer.addFrontendEndpoint(this);
sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.SERVER_CONNECTION_SUCCESSFUL));
@@ -54,44 +58,82 @@ public class SchafkopfClientConnection extends WebSocketAdapter implements Messa
super.onWebSocketText(jsonMessage);
Gson gson = new Gson();
JsonObject jsonObject = gson.fromJson(jsonMessage, JsonObject.class);
// Check if the origin is "frontend"
// Check if the origin is "backend"
String origin = jsonObject.get("origin").getAsString();
if (SchafkopfMessageOrigin.BACKEND.toString().equals(origin)) {
JsonObject message = jsonObject.getAsJsonObject("message");
JsonObject content = message.getAsJsonObject("content");
String messageType = message.get("message_type").getAsString();
if ("HEARTBEAT_SYN".equals(messageType)) {
if (!SchafkopfMessageOrigin.BACKEND.toString().equals(origin)) {
return;
}
JsonObject message = jsonObject.getAsJsonObject("message");
JsonObject content = message.getAsJsonObject("content");
String messageType = message.get("message_type").getAsString();
switch (SchafkopfMessageType.valueOf(messageType)) {
case HEARTBEAT_SYN:
sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.HEARTBEAT_ACK));
return;
} else if (SchafkopfMessageType.JOIN_GAME.toString().equals(messageType)) {
gameSession = dedicatedServer.getCurrentGameSession();
dedicatedServer.getCurrentGameSession().addPlayer(this);
} else if ("START_GAME".equals(messageType)) {
System.out.println("Received START_GAME message from " + session.getRemoteAddress() + ".");
break;
case JOIN_ONLINE_GAME:
GameSession gameSession = null;
try {
dedicatedServer.getCurrentGameSession().startGame();
} catch (NotEnoughPlayersException e) {
gameSession = dedicatedServer.getGameSessionByName(
content.get("serverName").getAsString());
} catch (NoGameSessionException e) {
JsonObject messageObject = new JsonObject();
messageObject.addProperty("error",
"No GameSession with name \"" + content.get("serverName").getAsString()
+ "\" found.");
sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.UNKNOWN_ERROR,
"Not enough players to start the game."));
messageObject));
break;
}
} else if (SchafkopfMessageType.PLAYER_CARD.toString().equals(messageType)) {
joinGame(gameSession);
sendServerList();
JsonObject messageObject = new JsonObject();
messageObject.addProperty("message",
"Joined GameSession \"" + gameSession.getServerName() + "\".");
sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.INFO_MESSAGE,
messageObject));
break;
case START_DEDICATED_GAME:
try {
this.gameSession.startGame();
} catch (SchafkopfException e) {
sendError(e);
}
break;
case SET_PLAYER_NAME:
this.name = content.get("playerName").getAsString();
break;
case PLAYER_CARD:
onlinePlayer.receiveCard(Karte.valueOf(content.get("card").getAsString()));
} else if ("list_online_games".equals(messageType)) {
System.out.println(
"Received list_online_games message from " + session.getRemoteAddress() + ".");
}
System.out.println(
"Received message from Client " + session.getRemoteAddress() + " " + jsonMessage);
break;
case LIST_ONLINE_GAMES:
sendServerList();
break;
case GET_ONLINE_GAME:
this.gameSession.sendSessionInfo();
break;
case CREATE_ONLINE_GAME:
String servername = content.get("serverName").getAsString();
GameSession gameSession2 = new GameSession(servername, this.dedicatedServer);
dedicatedServer.addGameSession(gameSession2);
joinGame(gameSession2);
sendServerList();
break;
case SET_STATUS_READY:
ready = !ready;
this.gameSession.sendSessionInfo();
break;
case LEAVE_ONLINE_GAME:
this.gameSession.removePlayer(this);
this.gameSession = null;
sendServerList();
break;
default:
// Handle unknown message types
logger.warn("Received unknown message type: " + messageType);
break;
}
}
@@ -100,13 +142,20 @@ public class SchafkopfClientConnection extends WebSocketAdapter implements Messa
this.onlinePlayer = onlinePlayer;
}
public OnlinePlayer getOnlinePlayer() {
return this.onlinePlayer;
}
@Override
public void onWebSocketClose(int statusCode, String reason) {
if (this.gameSession != null) {
this.gameSession.removePlayer(this);
}
super.onWebSocketClose(statusCode, reason);
dedicatedServer.removeFrontendEndpoint(this);
System.out.println("Socket Closed: [" + statusCode + "] " + reason);
logger.warn("Socket Closed: [" + statusCode + "] " + reason);
closureLatch.countDown();
}
@@ -124,11 +173,61 @@ public class SchafkopfClientConnection extends WebSocketAdapter implements Messa
SchafkopfMessage schafkopfMessage = new SchafkopfMessage(
SchafkopfMessageOrigin.DEDICATED_SERVER,
message);
System.out.println("Sending message to Client: " + schafkopfMessage.getMessageAsString());
try {
getRemote().sendString(schafkopfMessage.getMessageAsString());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* The main entrypoint of the Application.
*/
public void joinGame(GameSession gameSession) {
if (this.gameSession != null) {
this.gameSession.removePlayer(this);
}
this.gameSession = gameSession;
gameSession.addPlayer(this);
}
private void sendServerList() {
JsonObject messageObject = new JsonObject();
try {
messageObject.add("games", dedicatedServer.getGameSessionsAsJson());
} catch (NoGameSessionException e) {
JsonObject error = new JsonObject();
error.addProperty("error",
"No GameSessions found.");
sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.UNKNOWN_ERROR,
error));
return;
}
sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.LIST_ONLINE_GAMES,
messageObject));
}
public boolean isReady() {
return ready;
}
public void resetReady() {
ready = false;
}
public String getName() {
return this.name;
}
/**
* Send a message to the connected FrontEnd.
*/
public void sendError(SchafkopfException e) {
JsonObject messageObject = new JsonObject();
messageObject.addProperty("error",
e.getMessage());
sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.UNKNOWN_ERROR,
messageObject));
}
}

View File

@@ -7,11 +7,11 @@ import org.eclipse.jetty.websocket.server.JettyWebSocketCreator;
/**
* Creater to make new Instances of the FrontendConnection.
*/
public class FrontendEndpointCreator implements JettyWebSocketCreator {
public class SchafkopfClientConnectionCreator implements JettyWebSocketCreator {
private DedicatedServer dedicatedServer;
public FrontendEndpointCreator(DedicatedServer dedicatedServer) {
public SchafkopfClientConnectionCreator(DedicatedServer dedicatedServer) {
this.dedicatedServer = dedicatedServer;
}

View File

@@ -41,7 +41,7 @@ public class GameState {
}
private GamePhase gamePhase;
private Integer currentPlayer; // Using Integer to allow for null
private String currentPlayer; // Using Integer to allow for null
private Karte card;
private KartenFarbe color;
private boolean trumpf;
@@ -52,7 +52,7 @@ public class GameState {
this.gamePhase = phase;
}
public GameState(GamePhase phase, Integer player) {
public GameState(GamePhase phase, String player) {
this.gamePhase = phase;
this.currentPlayer = player;
}
@@ -60,7 +60,7 @@ public class GameState {
/**
* GameState.
*/
public GameState(GamePhase phase, Integer player, Karte card, KartenFarbe color, boolean trumpf) {
public GameState(GamePhase phase, String player, Karte card, KartenFarbe color, boolean trumpf) {
this.gamePhase = phase;
this.currentPlayer = player;
this.card = card;
@@ -71,7 +71,7 @@ public class GameState {
/**
* GameState.
*/
public GameState(GamePhase phase, Integer player, Karte card) {
public GameState(GamePhase phase, String player, Karte card) {
this.gamePhase = phase;
this.currentPlayer = player;
this.card = card;

View File

@@ -28,7 +28,6 @@ public class Schafkopf {
private final Player[] player;
private GameState gameState = new GameState(GamePhase.GAME_STOP);
private Thread spielThread;
/**
* Constructor for the Schafkopf class.
@@ -100,8 +99,6 @@ public class Schafkopf {
gameState = new GameState(GamePhase.GAME_STOP);
setAndSendGameState(gameState);
}
spielThread.interrupt();
}
/**

View File

@@ -21,6 +21,31 @@ public class SchafkopfException extends Exception {
// You can also include additional constructors or methods if needed
}
/**
* The main entrypoint of the Application.
*/
public static class NoGameSessionException extends SchafkopfException {
public NoGameSessionException() {
super("No game session available");
}
// You can also include additional constructors or methods if needed
}
/**
* The main entrypoint of the Application.
*/
public static class PlayerNotReadyException extends SchafkopfException {
public PlayerNotReadyException() {
super("Not all Players are in Ready State");
}
// You can also include additional constructors or methods if needed
}
/**
* Class that represents one Frontend Connection.
*/

View File

@@ -13,22 +13,27 @@ public class SchafkopfMessage {
public static class SchafkopfBaseMessage {
private JsonObject message;
private SchafkopfMessageType messageType;
public SchafkopfBaseMessage(SchafkopfMessageType messageType, String content) {
this.messageType = messageType;
this.message = buildBaseMessage(messageType, content);
}
public SchafkopfBaseMessage(SchafkopfMessageType messageType, JsonObject content) {
this.messageType = messageType;
this.message = buildBaseMessage(messageType, content);
}
public SchafkopfBaseMessage(SchafkopfMessageType messageType) {
this.messageType = messageType;
this.message = buildBaseMessage(messageType);
}
public JsonObject getBaseMessage() {
return message;
}
}
JsonObject message;
@@ -118,6 +123,8 @@ public class SchafkopfMessage {
*/
public enum SchafkopfMessageType {
UNKNOWN_ERROR,
INFO_MESSAGE,
HEARTBEAT_SYN,
HEARTBEAT_ACK,
GET_CARD_ONLINE_PLAYER,
@@ -125,9 +132,17 @@ public class SchafkopfMessage {
GAME_STATE,
SERVER_CONNECTION_SUCCESSFUL,
REQUEST_SERVER_CONNECTION,
START_GAME,
JOIN_GAME,
PLAYER_CARD
JOIN_ONLINE_GAME,
START_DEDICATED_GAME,
PLAYER_CARD,
LIST_ONLINE_GAMES,
GET_ONLINE_GAME,
CREATE_ONLINE_GAME,
SET_STATUS_READY,
SET_PLAYER_NAME,
GAME_START_READY,
LEAVE_ONLINE_GAME
}
/**

View File

@@ -49,8 +49,9 @@ public class Spielablauf {
for (int i = 0; i < 4; i++) {
int currentPlayer = (i + startingPlayer) % 4;
logger.info("Spieler ist dran: {}", currentPlayer);
schafkopf.setAndSendGameState(new GameState(GamePhase.WAIT_FOR_CARD, currentPlayer));
logger.info("Spieler ist dran: {}", players[currentPlayer].getName());
schafkopf.setAndSendGameState(
new GameState(GamePhase.WAIT_FOR_CARD, players[currentPlayer].getName()));
Karte playedCard = players[currentPlayer].play(spiel, tischKarten, gespielteKarten);
tischKarten.addKarten(playedCard);
@@ -58,7 +59,7 @@ public class Spielablauf {
schafkopf.setAndSendGameState(
new GameState(
GamePhase.PLAYER_CARD,
currentPlayer,
players[currentPlayer].getName(),
playedCard,
tischKarten.getByIndex(0).getFarbe(),
spiel.isTrumpf(tischKarten.getByIndex(0))));
@@ -72,7 +73,8 @@ public class Spielablauf {
schafkopf.setAndSendGameState(
new GameState(
GamePhase.PLAYER_TRICK, winningPlayerIndex, tischKarten.getByIndex(stichSpieler)));
GamePhase.PLAYER_TRICK, players[winningPlayerIndex].getName(),
tischKarten.getByIndex(stichSpieler)));
try {
Thread.sleep(3000);

View File

@@ -13,8 +13,8 @@ public class BotPlayer extends Player {
private KartenListe eigeneKarten;
private KartenListe unbekannteKarten = KartenUtil.initializeSchafKopfCardDeck();
public BotPlayer() {
// TODO document why this constructor is empty
public BotPlayer(String name) {
super(name);
}
@Override

View File

@@ -20,7 +20,8 @@ public class OnlinePlayer extends Player {
private KartenListe karten = new KartenListe();
public OnlinePlayer(MessageSender messageSender) {
public OnlinePlayer(MessageSender messageSender, String name) {
super(name);
this.messageSender = messageSender;
}

View File

@@ -9,6 +9,16 @@ import org.schafkopf.spielcontroller.SpielController;
*/
public abstract class Player {
private String name;
protected Player(String name) {
this.name = name;
}
public String getName() {
return name;
}
public abstract Karte play(
SpielController spiel, KartenListe tischKarten, KartenListe gespielteKarten)
throws InterruptedException;