edited a lot of stuff (#52)

This commit is contained in:
Valentin Heiserer
2024-04-26 20:54:39 +02:00
committed by GitHub
parent 539e29dc56
commit ea5df95228
9 changed files with 208 additions and 143 deletions

View File

@@ -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);
}
}

View File

@@ -29,7 +29,7 @@ public class DedicatedServer {
private final List<SchafkopfClientConnection> clientConnections = new ArrayList<>();
private final List<GameSession> gameSessions = new ArrayList<>();
private final List<OnlineGameSession> 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<GameSession> getGameSessions() {
return gameSessions;
public List<OnlineGameSession> 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);
}
}

View File

@@ -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<SchafkopfClientConnection> 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<Player> 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;
}
/**

View File

@@ -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.
*/

View File

@@ -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<Player> players;
void startGame(List<Player> 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();
}
}

View File

@@ -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
}
}

View File

@@ -15,14 +15,12 @@ import org.schafkopf.spielcontroller.SpielController;
*/
public class OnlinePlayer extends Player {
private final MessageSender messageSender;
private final BlockingQueue<Karte> 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);
}
}

View File

@@ -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;
}
}

View File

@@ -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<boolean>(false);
const isPingInProgress = ref<boolean>(false);
const secondsRemaining = ref<number>(10);