mirror of
https://github.com/Vale54321/schafkopf-bot.git
synced 2025-12-15 19:29:33 +01:00
committed by
GitHub
parent
2e5a42b6d3
commit
539e29dc56
@@ -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(
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user