refactored a lot and added possibility to play games on DedicatedServer (#43)

This commit is contained in:
Valentin Heiserer
2024-04-19 16:15:51 +02:00
committed by GitHub
parent 6259d0bef3
commit cab2d36f48
31 changed files with 492 additions and 155 deletions

View File

@@ -17,6 +17,9 @@ void setup(void) {
} }
nfc.SAMConfig(); nfc.SAMConfig();
// Send a marker string to identify the device
Serial.println("Adafruit PN532 NFC Marker");
} }
void loop(void) { void loop(void) {

View File

@@ -66,7 +66,7 @@
<configuration> <configuration>
<archive> <archive>
<manifest> <manifest>
<mainClass>org.schafkopf.BackendServer</mainClass> <mainClass>org.schafkopf.DedicatedServer</mainClass>
</manifest> </manifest>
</archive> </archive>
</configuration> </configuration>

View File

@@ -1,6 +1,5 @@
package org.schafkopf; package org.schafkopf;
import com.google.gson.JsonObject;
import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer; import com.sun.net.httpserver.HttpServer;
@@ -25,9 +24,12 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlets.CrossOriginFilter; import org.eclipse.jetty.servlets.CrossOriginFilter;
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer; import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
import org.schafkopf.cardreader.UsbCardReader; import org.schafkopf.cardreader.UsbCardReader;
import org.schafkopf.player.BotPlayer;
import org.schafkopf.player.LocalPlayer;
import org.schafkopf.player.Player;
/** Main Class that represents the Backend Server. */ /** Main Class that represents the Backend Server. */
public class BackendServer { public class BackendServer implements MessageSender {
private final Server server; private final Server server;
private final ServerConnector connector; private final ServerConnector connector;
private CountDownLatch nfcLatch = new CountDownLatch(1); private CountDownLatch nfcLatch = new CountDownLatch(1);
@@ -39,6 +41,8 @@ public class BackendServer {
private final List<FrontendEndpoint> frontendEndpoints = new ArrayList<>(); private final List<FrontendEndpoint> frontendEndpoints = new ArrayList<>();
private DedicatedServerConnection dedicatedServerConnection;
/** Creates an Instance of the Backend Server. */ /** Creates an Instance of the Backend Server. */
public BackendServer() throws URISyntaxException, IOException { public BackendServer() throws URISyntaxException, IOException {
server = new Server(); server = new Server();
@@ -48,7 +52,9 @@ public class BackendServer {
connector.setPort(address.getPort()); connector.setPort(address.getPort());
server.addConnector(connector); server.addConnector(connector);
schafkopfGame = new Schafkopf(this); schafkopfGame = new Schafkopf(new Player[]{new BotPlayer(), new LocalPlayer(this),
new LocalPlayer(this),
new LocalPlayer(this)}, this);
new UsbCardReader(this); new UsbCardReader(this);
@@ -86,6 +92,13 @@ public class BackendServer {
startHttpServer(); startHttpServer();
URI uri = new URI("http://localhost:8081"); // Replace with your target URL URI uri = new URI("http://localhost:8081"); // Replace with your target URL
Desktop.getDesktop().browse(uri); Desktop.getDesktop().browse(uri);
startDedicatedServerConnectionThread();
}
private void startDedicatedServerConnectionThread() {
dedicatedServerConnection = new DedicatedServerConnection(this);
dedicatedServerConnection.connect();
} }
private void startHttpServer() { private void startHttpServer() {
@@ -147,7 +160,6 @@ public class BackendServer {
/** The main entrypoint of the Application. */ /** The main entrypoint of the Application. */
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
BackendServer server = new BackendServer(); BackendServer server = new BackendServer();
server.setPort(8080);
server.start(); server.start();
server.join(); server.join();
} }
@@ -166,10 +178,6 @@ public class BackendServer {
context.addFilter(cors, "*", types); context.addFilter(cors, "*", types);
} }
private void setPort(int port) {
connector.setPort(port);
}
private void start() throws Exception { private void start() throws Exception {
server.start(); server.start();
} }
@@ -191,23 +199,12 @@ public class BackendServer {
* *
* @param message Message to send (String). * @param message Message to send (String).
*/ */
public void sendMessageToAllFrontendEndpoints(String message) { private void sendMessageToAllFrontendEndpoints(String message) {
for (FrontendEndpoint endpoint : frontendEndpoints) { for (FrontendEndpoint endpoint : frontendEndpoints) {
endpoint.sendMessage(message); endpoint.sendMessage(message);
} }
} }
/**
* Sends Message to all Frontend Instances.
*
* @param message Message to send (JsonObject).
*/
public void sendMessageToAllFrontendEndpoints(JsonObject message) {
for (FrontendEndpoint endpoint : frontendEndpoints) {
endpoint.sendMessage(message.toString());
}
}
/** method to call to wait for NFC input. */ /** method to call to wait for NFC input. */
public String waitForCardScan() throws InterruptedException { public String waitForCardScan() throws InterruptedException {
this.readingMode = true; this.readingMode = true;
@@ -234,4 +231,13 @@ public class BackendServer {
this.uidString = uidString; this.uidString = uidString;
nfcLatch.countDown(); nfcLatch.countDown();
} }
public void startDedicatedServerGame() {
dedicatedServerConnection.start();
}
@Override
public void sendMessage(String message) {
sendMessageToAllFrontendEndpoints(message);
}
} }

View File

@@ -0,0 +1,101 @@
package org.schafkopf;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
/** Main Class that represents the Backend Server. */
@WebSocket
public class DedicatedServerConnection {
private final MessageSender messageSender;
private final CountDownLatch closeLatch;
private static Session session;
public DedicatedServerConnection(MessageSender messageSender) {
this.messageSender = messageSender;
this.closeLatch = new CountDownLatch(1);
}
@OnWebSocketConnect
public void onConnect(Session session) {
this.session = session;
System.out.println("Connected to server.");
}
@OnWebSocketMessage
public void onMessage(String message) {
messageSender.sendMessage(message);
System.out.println("Received message from server: " + message);
}
@OnWebSocketClose
public void onClose(int statusCode, String reason) {
System.out.println("Connection closed: " + reason);
closeLatch.countDown();
}
@OnWebSocketError
public void onError(Throwable cause) {
System.err.println("Error occurred: " + cause.getMessage());
}
/** Main Class that represents the Backend Server. */
public static void sendMessage(String message) {
try {
session.getRemote().sendString(message);
System.out.println("Sent message to server: " + message);
} catch (Exception e) {
System.err.println("Error sending message: " + e.getMessage());
}
}
public void awaitClose() throws InterruptedException {
closeLatch.await();
}
/** Main Class that represents the Backend Server. */
public void connect() {
Thread connectionThread = new Thread(() -> {
try {
String serverUri = "ws://localhost:8085/";
WebSocketClient client = new WebSocketClient();
try {
client.start();
//DedicatedServerConnection socketClient = new DedicatedServerConnection();
HeartbeatSender heartbeatSender = new HeartbeatSender(this);
heartbeatSender.start(); // Start sending heartbeat messages
URI uri = new URI(serverUri);
ClientUpgradeRequest request = new ClientUpgradeRequest();
client.connect(this, uri, request);
System.out.println("Connecting to : " + uri);
this.awaitClose();
} catch (Exception e) {
System.err.println("Error connecting to server: " + e.getMessage());
} finally {
try {
client.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
System.err.println("Error starting dedicated server connection: " + e.getMessage());
}
});
connectionThread.start();
start();
}
public static void start() {
sendMessage("START_GAME");
}
}

View File

@@ -37,17 +37,10 @@ public class FrontendEndpoint extends WebSocketAdapter {
backendServer.schafkopfGame.stopGame(); backendServer.schafkopfGame.stopGame();
} }
if (message.contains("showtrumpf")) { if (message.contains("startdedicated")) {
backendServer.schafkopfGame.showTrumpf(); backendServer.startDedicatedServerGame();
} }
if (message.contains("showfarben")) {
backendServer.schafkopfGame.showFarbe();
}
if (message.contains("setgame")) {
backendServer.schafkopfGame.setGame(message);
}
} }
@Override @Override

View File

@@ -0,0 +1,26 @@
package org.schafkopf;
import java.util.Timer;
import java.util.TimerTask;
/** Creates an Instance of the Backend Server. */
public class HeartbeatSender {
private static final int HEARTBEAT_INTERVAL = 15000; // 1 minute
private final DedicatedServerConnection client;
public HeartbeatSender(DedicatedServerConnection client) {
this.client = client;
}
/** Creates an Instance of the Backend Server. */
public void start() {
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
client.sendMessage("HEARTBEAT SYN"); // Send a heartbeat message
}
}, HEARTBEAT_INTERVAL, HEARTBEAT_INTERVAL);
}
}

View File

@@ -1,6 +1,7 @@
package org.schafkopf.cardreader; package org.schafkopf.cardreader;
import com.fazecast.jSerialComm.SerialPort; import com.fazecast.jSerialComm.SerialPort;
import com.sun.tools.jconsole.JConsoleContext;
import io.github.cdimascio.dotenv.Dotenv; import io.github.cdimascio.dotenv.Dotenv;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import org.schafkopf.BackendServer; import org.schafkopf.BackendServer;
@@ -10,7 +11,7 @@ public class UsbCardReader extends CardReader {
private volatile boolean isRunning = true; private volatile boolean isRunning = true;
Dotenv dotenv = Dotenv.configure().directory("./").load(); Dotenv dotenv = Dotenv.configure().directory("./").load();
private final String comPort = dotenv.get("COM_PORT"); private String comPort = null;
/** /**
* Creates an Instance of the KartenLeser. * Creates an Instance of the KartenLeser.
@@ -19,7 +20,6 @@ public class UsbCardReader extends CardReader {
*/ */
public UsbCardReader(BackendServer server) { public UsbCardReader(BackendServer server) {
super(server); super(server);
new Thread(this::run).start(); new Thread(this::run).start();
} }
@@ -27,29 +27,46 @@ public class UsbCardReader extends CardReader {
isRunning = false; isRunning = false;
} }
/** run the reader. */ /** Run the reader. */
public void run() { public void run() {
SerialPort[] ports = SerialPort.getCommPorts(); // SerialPort[] ports = SerialPort.getCommPorts();
SerialPort selectedPort = null; //
// for (SerialPort port : ports) {
// if (port.openPort()) {
// System.out.println(port.getSystemPortName());
// try {
// Thread.sleep(5000);
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
// // Read any data available on the serial port
// byte[] initialBuffer = new byte[port.bytesAvailable()];
// int initialBytesRead = port.readBytes(initialBuffer, initialBuffer.length);
// String initialData = null;
// try {
// initialData = new String(initialBuffer, 0, initialBytesRead, "UTF-8").trim();
// } catch (UnsupportedEncodingException e) {
// throw new RuntimeException(e);
// }
// System.out.print("Raw data: ");
// for (byte b : initialBuffer) {
// System.out.print(b + " ");
// }
// System.out.println(initialData);
// if (initialData.contains("Adafruit PN532 NFC Marker")) {
// comPort = port.getSystemPortName();
// }
// }
// }
for (SerialPort port : ports) { comPort = dotenv.get("COM_PORT");
if (port.getSystemPortName().equals(this.comPort)) {
selectedPort = port;
break;
}
}
if (selectedPort == null) { if (comPort == null) {
System.out.println(this.comPort + " not found"); System.out.println("Adafruit PN532 NFC device not found");
return; return;
} }
if (ports.length == 0) { SerialPort serialPort = SerialPort.getCommPort(comPort);
System.out.println("No serial ports found");
return;
}
SerialPort serialPort = selectedPort; // You may need to adjust this based on your setup
serialPort.setBaudRate(115200); serialPort.setBaudRate(115200);
if (serialPort.openPort()) { if (serialPort.openPort()) {
@@ -60,8 +77,9 @@ public class UsbCardReader extends CardReader {
if (serialPort.bytesAvailable() > 0) { if (serialPort.bytesAvailable() > 0) {
byte[] buffer = new byte[serialPort.bytesAvailable()]; byte[] buffer = new byte[serialPort.bytesAvailable()];
int bytesRead = serialPort.readBytes(buffer, buffer.length); int bytesRead = serialPort.readBytes(buffer, buffer.length);
String data = new String(buffer, 0, bytesRead, "UTF-8").trim(); String data = new String(buffer, 0, bytesRead, "UTF-8").trim();
// Process the received data
server.nfcGelesen(data); server.nfcGelesen(data);
} }

View File

@@ -1,8 +1,9 @@
package org.schafkopf.player; package org.schafkopf.player;
import org.schafkopf.Schafkopf; import org.schafkopf.BackendServer;
import org.schafkopf.karte.Karte; import org.schafkopf.karte.Karte;
import org.schafkopf.karte.KartenListe; import org.schafkopf.karte.KartenListe;
import org.schafkopf.karte.KartenUtil;
import org.schafkopf.spielcontroller.SpielController; import org.schafkopf.spielcontroller.SpielController;
/** /**
@@ -10,14 +11,35 @@ import org.schafkopf.spielcontroller.SpielController;
*/ */
public class LocalPlayer extends Player { public class LocalPlayer extends Player {
private final Schafkopf schafkopf; private final BackendServer server;
public LocalPlayer(Schafkopf schafkopf) { public LocalPlayer(BackendServer server) {
this.schafkopf = schafkopf; this.server = server;
} }
@Override @Override
public Karte play(SpielController spiel, KartenListe tischKarten, KartenListe gespielteKarten) { public Karte play(SpielController spiel, KartenListe tischKarten, KartenListe gespielteKarten) {
return schafkopf.wartetAufKarte(); return wartetAufKarte();
}
/** Waits for a Card and returns a Karte Object. */
private Karte wartetAufKarte() {
String uid = null;
System.out.println("Starte Warten auf Karte");
try {
uid = server.waitForCardScan();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
Karte karte = KartenUtil.getIdOfUid(uid);
if (karte == null) {
System.out.println("Ungültige Karte");
return wartetAufKarte();
}
System.out.println("Karte gescannt: " + karte.getName());
System.out.println("Beende Warten auf Karte");
return karte;
} }
} }

View File

@@ -36,7 +36,7 @@
</descriptorRefs> </descriptorRefs>
<archive> <archive>
<manifest> <manifest>
<mainClass>org.schafkopf.Main</mainClass> <mainClass>org.schafkopf.DedicatedServer</mainClass>
</manifest> </manifest>
</archive> </archive>
</configuration> </configuration>

View File

@@ -0,0 +1,75 @@
package org.schafkopf;
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.player.BotPlayer;
import org.schafkopf.player.Player;
/** Class that represents one Frontend Connection. */
public class ClientConnection extends WebSocketAdapter implements MessageSender {
private final CountDownLatch closureLatch = new CountDownLatch(1);
private DedicatedServer dedicatedServer;
private Session session;
public ClientConnection(DedicatedServer dedicatedServer) {
this.dedicatedServer = dedicatedServer;
System.out.println("new ClientConnection created.");
}
@Override
public void onWebSocketConnect(Session session) {
this.session = session;
super.onWebSocketConnect(session);
String clientIp = session.getRemoteAddress().toString();
System.out.println("Endpoint connected from ip: " + clientIp);
dedicatedServer.addFrontendEndpoint(this);
}
@Override
public void onWebSocketText(String message) {
super.onWebSocketText(message);
if (message.equals("HEARTBEAT SYN")) {
System.out.println("Received HEARTBEAT message from " + session.getRemoteAddress() + ".");
sendMessage("HEARTBEAT ACK");
return;
}
if (message.equals("START_GAME")) {
System.out.println("Received START_GAME message from " + session.getRemoteAddress() + ".");
dedicatedServer.addGameSession(new GameSession(new Schafkopf(new Player[] {
new BotPlayer(), new BotPlayer(), new BotPlayer(), new BotPlayer()
}, this)));
return;
}
System.out.println("Received TEXT message:" + message);
}
@Override
public void onWebSocketClose(int statusCode, String reason) {
super.onWebSocketClose(statusCode, reason);
dedicatedServer.removeFrontendEndpoint(this);
System.out.println("Socket Closed: [" + statusCode + "] " + reason);
closureLatch.countDown();
}
@Override
public void onWebSocketError(Throwable cause) {
super.onWebSocketError(cause);
cause.printStackTrace(System.err);
}
/** send a Message to the connected FrontEnd. */
@Override
public void sendMessage(String message) {
try {
getRemote().sendString(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,94 @@
package org.schafkopf;
import jakarta.servlet.DispatcherType;
import java.net.InetSocketAddress;
import java.time.Duration;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
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;
/** Main Class that represents the Backend Server. */
public class DedicatedServer {
private final Server server;
private final ServerConnector connector;
private final List<ClientConnection> clientConnections = new ArrayList<>();
private final List<GameSession> gameSessions = new ArrayList<>();
/** Creates an Instance of the Backend Server. */
public DedicatedServer() {
server = new Server();
InetSocketAddress address = new InetSocketAddress("localhost", 8085);
connector = new ServerConnector(server);
connector.setHost(address.getHostName());
connector.setPort(address.getPort());
server.addConnector(connector);
// Setup the basic application "context" for this application at "/"
// This is also known as the handler tree (in jetty speak)
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
// Configure CORS settings
configureCors(context);
// Configure specific websocket behavior
JettyWebSocketServletContainerInitializer.configure(
context,
(servletContext, wsContainer) -> {
// Configure default max size
wsContainer.setMaxTextMessageSize(65535);
wsContainer.setIdleTimeout(Duration.ofDays(300000));
// Add websockets
wsContainer.addMapping("/*", new FrontendEndpointCreator(this));
});
}
/** The main entrypoint of the Application. */
public static void main(String[] args) throws Exception {
DedicatedServer server = new DedicatedServer();
server.start();
server.join();
}
private void configureCors(ServletContextHandler context) {
// Enable CORS for all paths
FilterHolder cors = context.addFilter(CrossOriginFilter.class, "/*", null);
// Configure allowed origins, headers, and methods
cors.setInitParameter("allowedOrigins", "*");
cors.setInitParameter("allowedHeaders", "X-Requested-With,Content-Type,Accept,Origin");
cors.setInitParameter("allowedMethods", "GET,POST,PUT,DELETE,OPTIONS");
// Add filter mappings
EnumSet<DispatcherType> types = EnumSet.of(DispatcherType.REQUEST);
context.addFilter(cors, "*", types);
}
private void start() throws Exception {
server.start();
}
private void join() throws InterruptedException {
server.join();
}
public void addFrontendEndpoint(ClientConnection endpoint) {
clientConnections.add(endpoint);
}
public void removeFrontendEndpoint(ClientConnection endpoint) {
clientConnections.remove(endpoint);
}
public void addGameSession(GameSession gameSession) {
gameSessions.add(gameSession);
}
}

View File

@@ -0,0 +1,23 @@
package org.schafkopf;
import org.eclipse.jetty.websocket.server.JettyServerUpgradeRequest;
import org.eclipse.jetty.websocket.server.JettyServerUpgradeResponse;
import org.eclipse.jetty.websocket.server.JettyWebSocketCreator;
/**
* Creater to make new Instances of the FrontendConnection.
*/
public class FrontendEndpointCreator implements JettyWebSocketCreator {
private DedicatedServer dedicatedServer;
public FrontendEndpointCreator(DedicatedServer dedicatedServer) {
this.dedicatedServer = dedicatedServer;
}
@Override
public Object createWebSocket(
JettyServerUpgradeRequest jettyServerUpgradeRequest,
JettyServerUpgradeResponse jettyServerUpgradeResponse) {
return new ClientConnection(this.dedicatedServer);
}
}

View File

@@ -0,0 +1,19 @@
package org.schafkopf;
/** The main entrypoint of the Application. */
public class GameSession {
private Schafkopf schafkopf;
/** The main entrypoint of the Application. */
public GameSession(Schafkopf schafkopf) {
this.schafkopf = schafkopf;
System.out.println("new GameSession created.");
startGame();
}
private void startGame() {
schafkopf.startGame();
}
}

View File

@@ -1,18 +0,0 @@
package org.schafkopf;
import org.schafkopf.karte.Karte;
import org.schafkopf.karte.KartenListe;
import org.schafkopf.karte.KartenUtil;
/** Creates an Instance of the Backend Server. */
public class Main {
/** Creates an Instance of the Backend Server. */
public static void main(String[] args) {
System.out.println("Hello and welcome!");
KartenListe testHand = KartenUtil.zieheZufallsHand(8);
for (Karte karte : testHand.getKartenListe()) {
System.out.println(karte.getName());
}
}
}

View File

@@ -0,0 +1,6 @@
package org.schafkopf;
/** The main entrypoint of the Application. */
public interface MessageSender {
void sendMessage(String message);
}

View File

@@ -6,7 +6,6 @@ import org.schafkopf.karte.KartenFarbe;
import org.schafkopf.karte.KartenListe; import org.schafkopf.karte.KartenListe;
import org.schafkopf.karte.KartenUtil; import org.schafkopf.karte.KartenUtil;
import org.schafkopf.player.BotPlayer; import org.schafkopf.player.BotPlayer;
import org.schafkopf.player.LocalPlayer;
import org.schafkopf.player.Player; import org.schafkopf.player.Player;
import org.schafkopf.spielcontroller.FarbGeierController; import org.schafkopf.spielcontroller.FarbGeierController;
import org.schafkopf.spielcontroller.FarbSoloController; import org.schafkopf.spielcontroller.FarbSoloController;
@@ -18,14 +17,12 @@ import org.schafkopf.spielcontroller.WenzController;
/** The main class representing the Schafkopf game. */ /** The main class representing the Schafkopf game. */
public class Schafkopf { public class Schafkopf {
private final BackendServer server; private final MessageSender messageSender;
/** The game controller. This is the class that implements the game logic. */ /** The game controller. This is the class that implements the game logic. */
private SpielController spiel = new SauSpielController(0, KartenFarbe.EICHEL); private SpielController spiel = new SauSpielController(0, KartenFarbe.EICHEL);
private final Player[] player = { private final Player[] player;
new BotPlayer(), new LocalPlayer(this), new LocalPlayer(this), new LocalPlayer(this)
};
private GameState gameState = new GameState(GamePhase.GAME_STOP); private GameState gameState = new GameState(GamePhase.GAME_STOP);
private Thread spielThread; private Thread spielThread;
@@ -33,10 +30,11 @@ public class Schafkopf {
/** /**
* Constructor for the Schafkopf class. * Constructor for the Schafkopf class.
* *
* @param server The backend server associated with the game. * @param messageSender MessageSender
*/ */
Schafkopf(BackendServer server) { public Schafkopf(Player[] player, MessageSender messageSender) {
this.server = server; this.player = player;
this.messageSender = messageSender;
System.out.println("SchaffKopfGame erstellt"); System.out.println("SchaffKopfGame erstellt");
} }
@@ -44,62 +42,26 @@ public class Schafkopf {
return player; return player;
} }
/** Sends all Trumpf Karten of the current GameType to the Frontend. */
public void showTrumpf() {
server.sendMessageToAllFrontendEndpoints(spiel.getTrumpfKarten().getJson());
}
/** Sends all Farb Karten of the current GameType to the Frontend. */
public void showFarbe() {
server.sendMessageToAllFrontendEndpoints(spiel.getFarbKarten().getJson());
}
/** Waits for a Card and returns a Karte Object. */
public Karte wartetAufKarte() {
String uid = null;
System.out.println("Starte Warten auf Karte");
try {
uid = server.waitForCardScan();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
Karte karte = KartenUtil.getIdOfUid(uid);
if (karte == null) {
System.out.println("Ungültige Karte");
return wartetAufKarte();
}
System.out.println("Karte gescannt: " + karte.getName());
System.out.println("Beende Warten auf Karte");
return karte;
}
/** Set GameState to "started" and start Game Thread. */ /** Set GameState to "started" and start Game Thread. */
public void startGame() { public void startGame() {
if (gameState.getGamePhase() != GamePhase.GAME_STOP) { if (gameState.getGamePhase() != GamePhase.GAME_STOP) {
System.out.println("Game already started!"); System.out.println("Game already started!");
server.sendMessageToAllFrontendEndpoints("Game already started!"); messageSender.sendMessage("Game already started!");
} else { } else {
gameState = new GameState(GamePhase.GAME_START); gameState = new GameState(GamePhase.GAME_START);
setAndSendGameState(gameState); setAndSendGameState(gameState);
System.out.println("Start Game"); System.out.println("Start Game");
// KartenListe botHand = KartenUtil.zieheZufallsHand(8); KartenListe austeilen = KartenUtil.initializeSchafKopfCardDeck();
KartenListe botHand = new KartenListe();
botHand.addKarten(Karte.EICHEL_7);
botHand.addKarten(Karte.SCHELL_7);
botHand.addKarten(Karte.BLATT_7);
botHand.addKarten(Karte.EICHEL_X);
botHand.addKarten(Karte.HERZ_X);
botHand.addKarten(Karte.HERZ_7);
botHand.addKarten(Karte.EICHEL_U);
botHand.addKarten(Karte.EICHEL_O);
for (Player currentPlayer : player) { for (Player currentPlayer : player) {
if (currentPlayer instanceof BotPlayer botPlayer) { if (currentPlayer instanceof BotPlayer botPlayer) {
// Perform actions specific to BotPlayer KartenListe botHand = new KartenListe();
for (int i = 7; i >= 0; i--) {
System.out.println("Austeilen: " + austeilen.size());
System.out.println("Bot Hand: " + i);
botHand.addKarten(austeilen.removeKarten(austeilen.getByIndex(i)));
}
System.out.println("Bot Hand: " + botHand.getJson().toString());
botPlayer.setCards(botHand); // Replace with the actual method you want to call botPlayer.setCards(botHand); // Replace with the actual method you want to call
} }
} }
@@ -114,7 +76,7 @@ public class Schafkopf {
public void stopGame() { public void stopGame() {
if (gameState.getGamePhase() == GamePhase.GAME_STOP) { if (gameState.getGamePhase() == GamePhase.GAME_STOP) {
System.out.println("no active Game!"); System.out.println("no active Game!");
server.sendMessageToAllFrontendEndpoints("no active Game!"); messageSender.sendMessage("no active Game!");
} else { } else {
gameState = new GameState(GamePhase.GAME_STOP); gameState = new GameState(GamePhase.GAME_STOP);
setAndSendGameState(gameState); setAndSendGameState(gameState);
@@ -126,7 +88,7 @@ public class Schafkopf {
/** Set GameType. */ /** Set GameType. */
public void setGame(String message) { public void setGame(String message) {
System.out.println("Set Game: " + message); System.out.println("Set Game: " + message);
server.sendMessageToAllFrontendEndpoints("Set Game: " + message); messageSender.sendMessage("Set Game: " + message);
switch (message) { switch (message) {
case "setgame:herzsolo": case "setgame:herzsolo":
this.spiel = new FarbSoloController(0, KartenFarbe.HERZ); this.spiel = new FarbSoloController(0, KartenFarbe.HERZ);
@@ -184,7 +146,7 @@ public class Schafkopf {
public void setAndSendGameState(GameState gameState) { public void setAndSendGameState(GameState gameState) {
this.gameState = gameState; this.gameState = gameState;
this.server.sendMessageToAllFrontendEndpoints(this.gameState.getJson()); this.messageSender.sendMessage(this.gameState.getJson().toString());
} }
public GameState getGameState() { public GameState getGameState() {

View File

@@ -21,6 +21,12 @@ function startSimulation(): void {
} }
function startDedicated(): void {
sendMessageToServer("startdedicated");
}
function stopSimulation(): void { function stopSimulation(): void {
sendMessageToServer("stopsimulation"); sendMessageToServer("stopsimulation");
} }
@@ -131,32 +137,33 @@ onMounted(() => {
<div v-for="message in messageFromServer" :key="message">{{ message }}</div> <div v-for="message in messageFromServer" :key="message">{{ message }}</div>
<div v-if="showGameSelect"> <div v-if="showGameSelect">
<!-- <div class="flex gap-2 place-content-center">-->
<!-- <button @click="setGame('setgame:sauspiel')">Sauspiel</button>-->
<!-- <button @click="setGame('setgame:herzsolo')">herzsolo</button>-->
<!-- <button @click="setGame('setgame:eichelsolo')">eichelsolo</button>-->
<!-- <button @click="setGame('setgame:blattsolo')">blattsolo</button>-->
<!-- <button @click="setGame('setgame:schellsolo')">schellsolo</button>-->
<!-- <button @click="setGame('setgame:eichelwenz')">eichelwenz</button>-->
<!-- <button @click="setGame('setgame:blattwenz')">blattwenz</button>-->
<!-- <button @click="setGame('setgame:herzwenz')">herzwenz</button>-->
<!-- <button @click="setGame('setgame:schellwenz')">schellwenz</button>-->
<!-- <button @click="setGame('setgame:eichelgeier')">eichelgeier</button>-->
<!-- <button @click="setGame('setgame:blattgeier')">blattgeier</button>-->
<!-- <button @click="setGame('setgame:herzgeier')">herzgeier</button>-->
<!-- <button @click="setGame('setgame:schellgeier')">schellgeier</button>-->
<!-- <button @click="setGame('setgame:geier')">Geier</button>-->
<!-- <button @click="setGame('setgame:wenz')">Wenz</button>-->
<!-- </div>-->
<!-- <div class="flex gap-2 place-content-center">-->
<!-- <button @click="showFarben">Zeige alle Farben</button>-->
<!-- <button @click="showTrumpf">Zeige alle Trumpfkarten</button>-->
<!-- </div>-->
<div class="flex gap-2 place-content-center"> <div class="flex gap-2 place-content-center">
<button @click="setGame('setgame:sauspiel')">Sauspiel</button> <button class="v-button" @click="startDedicated">Dedicated Starten</button>
<!-- <button @click="setGame('setgame:herzsolo')">herzsolo</button>-->
<!-- <button @click="setGame('setgame:eichelsolo')">eichelsolo</button>-->
<!-- <button @click="setGame('setgame:blattsolo')">blattsolo</button>-->
<!-- <button @click="setGame('setgame:schellsolo')">schellsolo</button>-->
<!-- <button @click="setGame('setgame:eichelwenz')">eichelwenz</button>-->
<!-- <button @click="setGame('setgame:blattwenz')">blattwenz</button>-->
<!-- <button @click="setGame('setgame:herzwenz')">herzwenz</button>-->
<!-- <button @click="setGame('setgame:schellwenz')">schellwenz</button>-->
<!-- <button @click="setGame('setgame:eichelgeier')">eichelgeier</button>-->
<!-- <button @click="setGame('setgame:blattgeier')">blattgeier</button>-->
<!-- <button @click="setGame('setgame:herzgeier')">herzgeier</button>-->
<!-- <button @click="setGame('setgame:schellgeier')">schellgeier</button>-->
<button @click="setGame('setgame:geier')">Geier</button>
<button @click="setGame('setgame:wenz')">Wenz</button>
</div>
<div class="flex gap-2 place-content-center">
<button @click="showFarben">Zeige alle Farben</button>
<button @click="showTrumpf">Zeige alle Trumpfkarten</button>
</div>
<div class="flex gap-2 place-content-center">
<button class="v-button" @click="startSimulation">Starten</button> <button class="v-button" @click="startSimulation">Starten</button>
<button class="v-button" @click="stopSimulation">Stoppen</button> <button class="v-button" @click="stopSimulation">Stoppen</button>
</div> </div>