diff --git a/Backend/schafkopf-client/src/main/java/org/schafkopf/player/LocalPlayer.java b/Backend/schafkopf-client/src/main/java/org/schafkopf/player/LocalPlayer.java index c1f7804..18f5928 100644 --- a/Backend/schafkopf-client/src/main/java/org/schafkopf/player/LocalPlayer.java +++ b/Backend/schafkopf-client/src/main/java/org/schafkopf/player/LocalPlayer.java @@ -1,5 +1,7 @@ package org.schafkopf.player; +import org.schafkopf.MessageSender; +import org.schafkopf.SchafkopfMessage.SchafkopfBaseMessage; import org.schafkopf.cardreader.CardReader; import org.schafkopf.karte.Karte; import org.schafkopf.karte.KartenListe; @@ -13,8 +15,8 @@ public class LocalPlayer extends Player { private final CardReader cardReader; - public LocalPlayer(CardReader cardReader) { - super("Local Player"); + public LocalPlayer(CardReader cardReader, MessageSender messageSender) { + super("Local Player", messageSender); this.cardReader = cardReader; } @@ -23,6 +25,11 @@ public class LocalPlayer extends Player { return wartetAufKarte(); } + @Override + public void resetReady() { + // Not needed + } + /** * Waits for a Card and returns a Karte Object. */ @@ -45,4 +52,9 @@ public class LocalPlayer extends Player { System.out.println("Beende Warten auf Karte"); return karte; } + + @Override + public void sendMessage(SchafkopfBaseMessage message) { + System.out.println("LocalPlayer: " + message); + } } diff --git a/Backend/schafkopf-server/src/main/java/org/schafkopf/DedicatedServer.java b/Backend/schafkopf-server/src/main/java/org/schafkopf/DedicatedServer.java index 1dfef7f..22273d0 100644 --- a/Backend/schafkopf-server/src/main/java/org/schafkopf/DedicatedServer.java +++ b/Backend/schafkopf-server/src/main/java/org/schafkopf/DedicatedServer.java @@ -29,7 +29,7 @@ public class DedicatedServer { private final List clientConnections = new ArrayList<>(); - private final List gameSessions = new ArrayList<>(); + private final List onlineGameSessions = new ArrayList<>(); /** * Creates an Instance of the Backend Server. @@ -116,25 +116,25 @@ public class DedicatedServer { clientConnections.remove(endpoint); } - public void addGameSession(GameSession gameSession) { - gameSessions.add(gameSession); + public void addGameSession(OnlineGameSession onlineGameSession) { + onlineGameSessions.add(onlineGameSession); } - public List getGameSessions() { - return gameSessions; + public List getGameSessions() { + return onlineGameSessions; } /** * The main entrypoint of the Application. */ public JsonArray getGameSessionsAsJson() throws NoGameSessionException { - if (gameSessions.isEmpty()) { + if (onlineGameSessions.isEmpty()) { throw new NoGameSessionException(); } JsonArray gameSessionsJson = new JsonArray(); - for (GameSession gameSession : gameSessions) { - gameSessionsJson.add(gameSession.getJson()); + for (OnlineGameSession onlineGameSession : onlineGameSessions) { + gameSessionsJson.add(onlineGameSession.getJson()); } return gameSessionsJson; } @@ -142,26 +142,26 @@ public class DedicatedServer { /** * The main entrypoint of the Application. */ - public GameSession getCurrentGameSession() throws NoGameSessionException { - if (gameSessions.isEmpty()) { + public OnlineGameSession getCurrentGameSession() throws NoGameSessionException { + if (onlineGameSessions.isEmpty()) { throw new NoGameSessionException(); } - return gameSessions.get(gameSessions.size() - 1); + return onlineGameSessions.get(onlineGameSessions.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; + public OnlineGameSession getGameSessionByName(String gameId) throws NoGameSessionException { + for (OnlineGameSession onlineGameSession : onlineGameSessions) { + if (onlineGameSession.getServerName().equals(gameId)) { + return onlineGameSession; } } throw new NoGameSessionException(); } - public void removeGameSession(GameSession gameSession) { - gameSessions.remove(gameSession); + public void removeGameSession(OnlineGameSession onlineGameSession) { + onlineGameSessions.remove(onlineGameSession); } } diff --git a/Backend/schafkopf-server/src/main/java/org/schafkopf/GameSession.java b/Backend/schafkopf-server/src/main/java/org/schafkopf/OnlineGameSession.java similarity index 59% rename from Backend/schafkopf-server/src/main/java/org/schafkopf/GameSession.java rename to Backend/schafkopf-server/src/main/java/org/schafkopf/OnlineGameSession.java index 8bff155..665ac3c 100644 --- a/Backend/schafkopf-server/src/main/java/org/schafkopf/GameSession.java +++ b/Backend/schafkopf-server/src/main/java/org/schafkopf/OnlineGameSession.java @@ -3,28 +3,18 @@ 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 { +public class OnlineGameSession extends BaseGameSession { - private static final Logger logger = LoggerFactory.getLogger(GameSession.class); - private Schafkopf schafkopf; - - private List clients; - - private Thread spielThread; private String serverName; private DedicatedServer dedicatedServer; @@ -32,59 +22,32 @@ public class GameSession implements MessageSender { /** * The main entrypoint of the Application. */ - public GameSession(String serverName, DedicatedServer dedicatedServer) { + public OnlineGameSession(String serverName, DedicatedServer dedicatedServer) { + this.players = new ArrayList<>(); 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.clients.size() >= 4) { + public void addPlayer(Player player) { + if (this.players.size() >= 4) { throw new RuntimeException("Game is full"); } - logger.info("Adding player to game: " + client); - clients.add(client); + logger.info("Adding player to game: " + player); + players.add(player); - OnlinePlayer onlinePlayer = new OnlinePlayer(client, client.getName()); - client.setOnlinePlayer(onlinePlayer); this.sendSessionInfo(); } - /** - * 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 PlayerNotReadyException { - logger.info("Starting game: " + serverName + " with " + clients.size() + " players"); - List players = new ArrayList<>(); + logger.info("Starting game: " + serverName + " with " + players.size() + " Onlineplayers"); - 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()) { + for (Player player : players) { + if (!player.isReady()) { throw new PlayerNotReadyException(); } } @@ -98,27 +61,32 @@ public class GameSession implements MessageSender { e.printStackTrace(); } - spielThread = new Thread(() -> { - try { - 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) { - throw new RuntimeException(e); + super.startGame(players); + players.forEach(player -> player.resetReady()); + } + + /** + * Class that represents one Frontend Connection. + */ + public void removePlayer(OnlinePlayer player) { + logger.info("Removing player from game: " + player.getName()); + players.remove(player); + + if (this.getPlayerCount() == 0) { + logger.info("No players left in game: " + serverName); + if (spielThread != null) { + spielThread.interrupt(); } - }); - - spielThread.start(); - - + this.dedicatedServer.removeGameSession(this); + return; + } + this.sendSessionInfo(); } @Override public void sendMessage(SchafkopfBaseMessage message) { - for (SchafkopfClientConnection client : clients) { - client.sendMessage(message); + for (Player player : players) { + player.sendMessage(message); } } @@ -132,15 +100,17 @@ public class GameSession implements MessageSender { // Create an array to hold player information JsonArray playersArray = new JsonArray(); - for (SchafkopfClientConnection client : clients) { + for (Player player : players) { JsonObject playerObject = new JsonObject(); playerObject.addProperty("playerName", - client.getName()); // Assuming you have a method to get player name + player.getName()); // Assuming you have a method to get player name playerObject.addProperty("isReady", - client.isReady()); // Assuming you have a method to check player readiness + player.isReady()); // Assuming you have a method to check player readiness playersArray.add(playerObject); + playerObject.addProperty("isBot", + player instanceof BotPlayer); } - for (int i = clients.size(); i < 4; i++) { + for (int i = players.size(); i < 4; i++) { JsonObject playerObject = new JsonObject(); playerObject.addProperty("playerName", "Bot " + i); // Assuming you have a method to get player name @@ -159,8 +129,17 @@ public class GameSession implements MessageSender { return serverName; } + /** + * The main entrypoint of the Application. + */ public int getPlayerCount() { - return clients.size(); + int onlinePlayerCount = 0; + for (Player player : players) { + if (player instanceof OnlinePlayer) { + onlinePlayerCount++; + } + } + return onlinePlayerCount; } /** diff --git a/Backend/schafkopf-server/src/main/java/org/schafkopf/SchafkopfClientConnection.java b/Backend/schafkopf-server/src/main/java/org/schafkopf/SchafkopfClientConnection.java index 986973d..ae6590e 100644 --- a/Backend/schafkopf-server/src/main/java/org/schafkopf/SchafkopfClientConnection.java +++ b/Backend/schafkopf-server/src/main/java/org/schafkopf/SchafkopfClientConnection.java @@ -25,26 +25,21 @@ public class SchafkopfClientConnection extends WebSocketAdapter implements Messa private final CountDownLatch closureLatch = new CountDownLatch(1); private DedicatedServer dedicatedServer; - private GameSession gameSession; - - private Session session; + private OnlineGameSession onlineGameSession; 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); + this.onlinePlayer = new OnlinePlayer(this, "DefaultName"); } @Override public void onWebSocketConnect(Session session) { - this.session = session; super.onWebSocketConnect(session); String clientIp = session.getRemoteAddress().toString(); logger.info("Endpoint connected from ip: " + clientIp); @@ -74,9 +69,9 @@ public class SchafkopfClientConnection extends WebSocketAdapter implements Messa sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.HEARTBEAT_ACK)); break; case JOIN_ONLINE_GAME: - GameSession gameSession = null; + OnlineGameSession onlineGameSession = null; try { - gameSession = dedicatedServer.getGameSessionByName( + onlineGameSession = dedicatedServer.getGameSessionByName( content.get("serverName").getAsString()); } catch (NoGameSessionException e) { JsonObject messageObject = new JsonObject(); @@ -87,23 +82,24 @@ public class SchafkopfClientConnection extends WebSocketAdapter implements Messa messageObject)); break; } - joinGame(gameSession); + joinGame(onlineGameSession); sendServerList(); JsonObject messageObject = new JsonObject(); messageObject.addProperty("message", - "Joined GameSession \"" + gameSession.getServerName() + "\"."); + "Joined GameSession \"" + onlineGameSession.getServerName() + "\"."); sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.INFO_MESSAGE, messageObject)); break; case START_DEDICATED_GAME: try { - this.gameSession.startGame(); + this.onlineGameSession.startGame(); } catch (SchafkopfException e) { sendError(e); } break; case SET_PLAYER_NAME: - this.name = content.get("playerName").getAsString(); + String name = content.get("playerName").getAsString(); + onlinePlayer.setName(name); break; case PLAYER_CARD: onlinePlayer.receiveCard(Karte.valueOf(content.get("card").getAsString())); @@ -112,22 +108,23 @@ public class SchafkopfClientConnection extends WebSocketAdapter implements Messa sendServerList(); break; case GET_ONLINE_GAME: - this.gameSession.sendSessionInfo(); + this.onlineGameSession.sendSessionInfo(); break; case CREATE_ONLINE_GAME: String servername = content.get("serverName").getAsString(); - GameSession gameSession2 = new GameSession(servername, this.dedicatedServer); - dedicatedServer.addGameSession(gameSession2); - joinGame(gameSession2); + OnlineGameSession onlineGameSession2 = new OnlineGameSession(servername, + this.dedicatedServer); + dedicatedServer.addGameSession(onlineGameSession2); + joinGame(onlineGameSession2); sendServerList(); break; case SET_STATUS_READY: - ready = !ready; - this.gameSession.sendSessionInfo(); + onlinePlayer.setReady(!onlinePlayer.isReady()); + this.onlineGameSession.sendSessionInfo(); break; case LEAVE_ONLINE_GAME: - this.gameSession.removePlayer(this); - this.gameSession = null; + this.onlineGameSession.removePlayer(this.onlinePlayer); + this.onlineGameSession = null; sendServerList(); break; default: @@ -137,19 +134,10 @@ public class SchafkopfClientConnection extends WebSocketAdapter implements Messa } } - - public void setOnlinePlayer(OnlinePlayer onlinePlayer) { - 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); + if (this.onlineGameSession != null) { + this.onlineGameSession.removePlayer(this.onlinePlayer); } super.onWebSocketClose(statusCode, reason); @@ -183,12 +171,12 @@ public class SchafkopfClientConnection extends WebSocketAdapter implements Messa /** * The main entrypoint of the Application. */ - public void joinGame(GameSession gameSession) { - if (this.gameSession != null) { - this.gameSession.removePlayer(this); + public void joinGame(OnlineGameSession onlineGameSession) { + if (this.onlineGameSession != null) { + this.onlineGameSession.removePlayer(this.onlinePlayer); } - this.gameSession = gameSession; - gameSession.addPlayer(this); + this.onlineGameSession = onlineGameSession; + onlineGameSession.addPlayer(this.onlinePlayer); } private void sendServerList() { @@ -208,18 +196,6 @@ public class SchafkopfClientConnection extends WebSocketAdapter implements Messa messageObject)); } - public boolean isReady() { - return ready; - } - - public void resetReady() { - ready = false; - } - - public String getName() { - return this.name; - } - /** * Send a message to the connected FrontEnd. */ diff --git a/Backend/schafkopf-shared/src/main/java/org/schafkopf/BaseGameSession.java b/Backend/schafkopf-shared/src/main/java/org/schafkopf/BaseGameSession.java new file mode 100644 index 0000000..8d35337 --- /dev/null +++ b/Backend/schafkopf-shared/src/main/java/org/schafkopf/BaseGameSession.java @@ -0,0 +1,51 @@ +package org.schafkopf; + +import java.util.List; +import org.schafkopf.SchafkopfException.NotEnoughPlayersException; +import org.schafkopf.SchafkopfMessage.SchafkopfBaseMessage; +import org.schafkopf.SchafkopfMessage.SchafkopfMessageType; +import org.schafkopf.player.BotPlayer; +import org.schafkopf.player.Player; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * The main entrypoint of the Application. + */ +public abstract class BaseGameSession implements MessageSender { + + protected static final Logger logger = LoggerFactory.getLogger(BaseGameSession.class); + protected Thread spielThread; + protected Schafkopf schafkopf; + protected List players; + + void startGame(List players) { + logger.info("Starting game"); + for (int i = players.size(); i < 4; i++) { + players.add(new BotPlayer("Bot " + i)); + } + + 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(players.toArray(Player[]::new), this); + schafkopf.startGame(); + } catch (NotEnoughPlayersException e) { + throw new RuntimeException(e); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }); + + spielThread.start(); + } +} diff --git a/Backend/schafkopf-shared/src/main/java/org/schafkopf/player/BotPlayer.java b/Backend/schafkopf-shared/src/main/java/org/schafkopf/player/BotPlayer.java index 4190d4d..afd14a7 100644 --- a/Backend/schafkopf-shared/src/main/java/org/schafkopf/player/BotPlayer.java +++ b/Backend/schafkopf-shared/src/main/java/org/schafkopf/player/BotPlayer.java @@ -1,5 +1,7 @@ package org.schafkopf.player; +import org.schafkopf.MessageSender; +import org.schafkopf.SchafkopfMessage.SchafkopfBaseMessage; import org.schafkopf.karte.Karte; import org.schafkopf.karte.KartenListe; import org.schafkopf.karte.KartenUtil; @@ -13,8 +15,17 @@ public class BotPlayer extends Player { private KartenListe eigeneKarten; private KartenListe unbekannteKarten = KartenUtil.initializeSchafKopfCardDeck(); + /** + * Constructor for the BotPlayer. + */ public BotPlayer(String name) { - super(name); + super(name, new MessageSender() { + @Override + public void sendMessage(SchafkopfBaseMessage message) { + System.out.println("BotPlayer: " + message); + } + }); + this.setReady(true); } @Override @@ -45,4 +56,14 @@ public class BotPlayer extends Player { this.unbekannteKarten.removeKarten(eigeneKarten); System.out.println("Eigene Karte fertig"); } + + @Override + public void sendMessage(SchafkopfBaseMessage message) { + + } + + @Override + public void resetReady() { + // Not needed + } } diff --git a/Backend/schafkopf-shared/src/main/java/org/schafkopf/player/OnlinePlayer.java b/Backend/schafkopf-shared/src/main/java/org/schafkopf/player/OnlinePlayer.java index 7ebbdb0..1da2a92 100644 --- a/Backend/schafkopf-shared/src/main/java/org/schafkopf/player/OnlinePlayer.java +++ b/Backend/schafkopf-shared/src/main/java/org/schafkopf/player/OnlinePlayer.java @@ -15,14 +15,12 @@ import org.schafkopf.spielcontroller.SpielController; */ public class OnlinePlayer extends Player { - private final MessageSender messageSender; private final BlockingQueue receivedCardQueue = new LinkedBlockingQueue<>(); private KartenListe karten = new KartenListe(); public OnlinePlayer(MessageSender messageSender, String name) { - super(name); - this.messageSender = messageSender; + super(name, messageSender); } /** @@ -53,6 +51,11 @@ public class OnlinePlayer extends Player { return spielKarte; } + @Override + public void resetReady() { + this.setReady(false); + } + private void sendPlayerCards() { JsonObject messageObject = new JsonObject(); messageObject.add("cards", this.karten.getJson()); @@ -68,4 +71,9 @@ public class OnlinePlayer extends Player { System.out.println("Received Card before Queue: " + receivedCard.getName()); receivedCardQueue.add(receivedCard); } + + @Override + public void sendMessage(SchafkopfBaseMessage message) { + messageSender.sendMessage(message); + } } diff --git a/Backend/schafkopf-shared/src/main/java/org/schafkopf/player/Player.java b/Backend/schafkopf-shared/src/main/java/org/schafkopf/player/Player.java index 2e96cfc..9e0dc50 100644 --- a/Backend/schafkopf-shared/src/main/java/org/schafkopf/player/Player.java +++ b/Backend/schafkopf-shared/src/main/java/org/schafkopf/player/Player.java @@ -1,5 +1,6 @@ package org.schafkopf.player; +import org.schafkopf.MessageSender; import org.schafkopf.karte.Karte; import org.schafkopf.karte.KartenListe; import org.schafkopf.spielcontroller.SpielController; @@ -7,11 +8,14 @@ import org.schafkopf.spielcontroller.SpielController; /** * Class that represents one Player of the game. */ -public abstract class Player { +public abstract class Player implements MessageSender { + protected MessageSender messageSender; + private boolean ready = false; private String name; - protected Player(String name) { + protected Player(String name, MessageSender messageSender) { + this.messageSender = messageSender; this.name = name; } @@ -19,7 +23,21 @@ public abstract class Player { return name; } + public void setName(String name) { + this.name = name; + } + public abstract Karte play( SpielController spiel, KartenListe tischKarten, KartenListe gespielteKarten) throws InterruptedException; + + public abstract void resetReady(); + + public void setReady(boolean ready) { + this.ready = ready; + } + + public boolean isReady() { + return ready; + } } diff --git a/Frontend/src/pages/MainMenu.vue b/Frontend/src/pages/MainMenu.vue index 6b2c18f..860208a 100644 --- a/Frontend/src/pages/MainMenu.vue +++ b/Frontend/src/pages/MainMenu.vue @@ -6,7 +6,7 @@ import {BackendMessage, MessageType} from "../BackendMessage.ts"; const backendConnection = scg("BackendConnection"); -const serverAddress = ref("dyn.heiserer.de:8085") +const serverAddress = ref("10.6.9.57:8085") const isConnected = ref(false); const isPingInProgress = ref(false); const secondsRemaining = ref(10);