mirror of
https://github.com/Vale54321/schafkopf-bot.git
synced 2025-12-15 19:29:33 +01:00
refactored a lot and added possibility to play games on DedicatedServer (#43)
This commit is contained in:
committed by
GitHub
parent
6259d0bef3
commit
cab2d36f48
@@ -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) {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package org.schafkopf;
|
||||||
|
|
||||||
|
/** The main entrypoint of the Application. */
|
||||||
|
public interface MessageSender {
|
||||||
|
void sendMessage(String message);
|
||||||
|
}
|
||||||
@@ -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() {
|
||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user