mirror of
https://github.com/Vale54321/schafkopf-bot.git
synced 2025-12-15 19:29:33 +01:00
Message types and server (#44)
* message type and handling * deleted web-content and fixed bug * edited main page
This commit is contained in:
committed by
GitHub
parent
cab2d36f48
commit
a0a1cfaa4a
@@ -1,75 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
package org.schafkopf;
|
||||
|
||||
import jakarta.servlet.DispatcherType;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
@@ -13,27 +17,50 @@ 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. */
|
||||
/**
|
||||
* 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<SchafkopfClientConnection> clientConnections = new ArrayList<>();
|
||||
|
||||
private final List<GameSession> gameSessions = new ArrayList<>();
|
||||
|
||||
/** Creates an Instance of the Backend Server. */
|
||||
private GameSession currentGameSession;
|
||||
|
||||
/**
|
||||
* Creates an Instance of the Backend Server.
|
||||
*/
|
||||
public DedicatedServer() {
|
||||
server = new Server();
|
||||
InetSocketAddress address = new InetSocketAddress("localhost", 8085);
|
||||
InetAddress address;
|
||||
|
||||
try (final DatagramSocket socket = new DatagramSocket()) {
|
||||
socket.connect(InetAddress.getByName("8.8.8.8"), 10002);
|
||||
address = socket.getLocalAddress();
|
||||
} catch (UnknownHostException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (SocketException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
InetSocketAddress socketAddress = new InetSocketAddress(address.getHostAddress(), 8085);
|
||||
System.out.println(
|
||||
"Server started at: " + socketAddress.getAddress() + ":" + socketAddress.getPort());
|
||||
connector = new ServerConnector(server);
|
||||
connector.setHost(address.getHostName());
|
||||
connector.setPort(address.getPort());
|
||||
connector.setHost(socketAddress.getHostName());
|
||||
connector.setPort(socketAddress.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);
|
||||
|
||||
// Add the health check servlet to the servlet context
|
||||
context.addServlet(HealthCheckServlet.class, "/health");
|
||||
context.setContextPath("/");
|
||||
server.setHandler(context);
|
||||
// Configure CORS settings
|
||||
@@ -48,9 +75,13 @@ public class DedicatedServer {
|
||||
// Add websockets
|
||||
wsContainer.addMapping("/*", new FrontendEndpointCreator(this));
|
||||
});
|
||||
|
||||
currentGameSession = new GameSession();
|
||||
}
|
||||
|
||||
/** The main entrypoint of the Application. */
|
||||
/**
|
||||
* The main entrypoint of the Application.
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
DedicatedServer server = new DedicatedServer();
|
||||
server.start();
|
||||
@@ -79,16 +110,23 @@ public class DedicatedServer {
|
||||
server.join();
|
||||
}
|
||||
|
||||
public void addFrontendEndpoint(ClientConnection endpoint) {
|
||||
public void addFrontendEndpoint(SchafkopfClientConnection endpoint) {
|
||||
clientConnections.add(endpoint);
|
||||
}
|
||||
|
||||
public void removeFrontendEndpoint(ClientConnection endpoint) {
|
||||
public void removeFrontendEndpoint(SchafkopfClientConnection endpoint) {
|
||||
clientConnections.remove(endpoint);
|
||||
}
|
||||
|
||||
|
||||
public void addGameSession(GameSession gameSession) {
|
||||
gameSessions.add(gameSession);
|
||||
}
|
||||
|
||||
public List<GameSession> getGameSessions() {
|
||||
return gameSessions;
|
||||
}
|
||||
|
||||
public GameSession getCurrentGameSession() {
|
||||
return currentGameSession;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ 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) {
|
||||
@@ -18,6 +19,6 @@ public class FrontendEndpointCreator implements JettyWebSocketCreator {
|
||||
public Object createWebSocket(
|
||||
JettyServerUpgradeRequest jettyServerUpgradeRequest,
|
||||
JettyServerUpgradeResponse jettyServerUpgradeResponse) {
|
||||
return new ClientConnection(this.dedicatedServer);
|
||||
return new SchafkopfClientConnection(this.dedicatedServer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,86 @@
|
||||
package org.schafkopf;
|
||||
|
||||
/** The main entrypoint of the Application. */
|
||||
public class GameSession {
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.schafkopf.SchafkopfException.NotEnoughPlayersException;
|
||||
import org.schafkopf.SchafkopfMessage.SchafkopfBaseMessage;
|
||||
import org.schafkopf.player.BotPlayer;
|
||||
import org.schafkopf.player.OnlinePlayer;
|
||||
import org.schafkopf.player.Player;
|
||||
|
||||
/**
|
||||
* The main entrypoint of the Application.
|
||||
*/
|
||||
public class GameSession implements MessageSender {
|
||||
|
||||
private Schafkopf schafkopf;
|
||||
private List<Player> player;
|
||||
|
||||
/** The main entrypoint of the Application. */
|
||||
public GameSession(Schafkopf schafkopf) {
|
||||
this.schafkopf = schafkopf;
|
||||
System.out.println("new GameSession created.");
|
||||
startGame();
|
||||
private List<SchafkopfClientConnection> clients;
|
||||
|
||||
private Thread spielThread;
|
||||
|
||||
/**
|
||||
* The main entrypoint of the Application.
|
||||
*/
|
||||
public GameSession() {
|
||||
player = new ArrayList<>();
|
||||
clients = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void startGame() {
|
||||
schafkopf.startGame();
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public void addPlayer(SchafkopfClientConnection client) {
|
||||
if (this.player.size() >= 4) {
|
||||
throw new RuntimeException("Game is full");
|
||||
}
|
||||
System.out.println("Adding player to game: " + client);
|
||||
clients.add(client);
|
||||
|
||||
OnlinePlayer onlinePlayer = new OnlinePlayer(client);
|
||||
|
||||
this.player.add(onlinePlayer);
|
||||
|
||||
client.setOnlinePlayer(onlinePlayer);
|
||||
}
|
||||
|
||||
public Schafkopf getSchafkopf() {
|
||||
return schafkopf;
|
||||
}
|
||||
|
||||
void startGame() throws NotEnoughPlayersException {
|
||||
int playerCount = this.player.size();
|
||||
System.out.println("Starting game with " + playerCount + " players");
|
||||
if (playerCount < 4) {
|
||||
for (int i = 0; i < 4 - playerCount; i++) {
|
||||
this.player.add(new BotPlayer());
|
||||
}
|
||||
}
|
||||
System.out.println("Starting game with, now: " + this.player.size() + " players");
|
||||
|
||||
spielThread = new Thread(() -> {
|
||||
try {
|
||||
schafkopf = new Schafkopf(this.player.toArray(new Player[0]), this);
|
||||
schafkopf.startGame();
|
||||
} catch (NotEnoughPlayersException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
spielThread.start();
|
||||
|
||||
// schafkopf = new Schafkopf(this.player.toArray(new Player[0]), this);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(SchafkopfBaseMessage message) {
|
||||
System.out.println("Sending message to Client: " + message);
|
||||
for (SchafkopfClientConnection client : clients) {
|
||||
client.sendMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.schafkopf;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public class HealthCheckServlet extends HttpServlet {
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
resp.setContentType("text/plain");
|
||||
resp.getWriter().println("Backend server is up and running!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package org.schafkopf;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
|
||||
import org.schafkopf.SchafkopfException.NotEnoughPlayersException;
|
||||
import org.schafkopf.SchafkopfMessage.SchafkopfBaseMessage;
|
||||
import org.schafkopf.SchafkopfMessage.SchafkopfMessageOrigin;
|
||||
import org.schafkopf.SchafkopfMessage.SchafkopfMessageType;
|
||||
import org.schafkopf.karte.Karte;
|
||||
import org.schafkopf.player.OnlinePlayer;
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public class SchafkopfClientConnection extends WebSocketAdapter implements MessageSender {
|
||||
|
||||
private final CountDownLatch connectionLatch;
|
||||
private final CountDownLatch closureLatch = new CountDownLatch(1);
|
||||
private DedicatedServer dedicatedServer;
|
||||
|
||||
private GameSession gameSession;
|
||||
|
||||
private Session session;
|
||||
|
||||
private OnlinePlayer onlinePlayer;
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public SchafkopfClientConnection(DedicatedServer dedicatedServer) {
|
||||
this.dedicatedServer = dedicatedServer;
|
||||
this.connectionLatch = new CountDownLatch(1);
|
||||
System.out.println("new ClientConnection created.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWebSocketConnect(Session session) {
|
||||
this.session = session;
|
||||
super.onWebSocketConnect(session);
|
||||
String clientIp = session.getRemoteAddress().toString();
|
||||
System.out.println("Endpoint connected from ip: " + clientIp);
|
||||
|
||||
connectionLatch.countDown();
|
||||
dedicatedServer.addFrontendEndpoint(this);
|
||||
sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.SERVER_CONNECTION_SUCCESSFUL));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWebSocketText(String jsonMessage) {
|
||||
super.onWebSocketText(jsonMessage);
|
||||
Gson gson = new Gson();
|
||||
JsonObject jsonObject = gson.fromJson(jsonMessage, JsonObject.class);
|
||||
// Check if the origin is "frontend"
|
||||
String origin = jsonObject.get("origin").getAsString();
|
||||
if (SchafkopfMessageOrigin.BACKEND.toString().equals(origin)) {
|
||||
JsonObject message = jsonObject.getAsJsonObject("message");
|
||||
JsonObject content = message.getAsJsonObject("content");
|
||||
String messageType = message.get("message_type").getAsString();
|
||||
if ("HEARTBEAT_SYN".equals(messageType)) {
|
||||
|
||||
sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.HEARTBEAT_ACK));
|
||||
return;
|
||||
} else if (SchafkopfMessageType.JOIN_GAME.toString().equals(messageType)) {
|
||||
|
||||
gameSession = dedicatedServer.getCurrentGameSession();
|
||||
dedicatedServer.getCurrentGameSession().addPlayer(this);
|
||||
|
||||
} else if ("START_GAME".equals(messageType)) {
|
||||
|
||||
System.out.println("Received START_GAME message from " + session.getRemoteAddress() + ".");
|
||||
try {
|
||||
dedicatedServer.getCurrentGameSession().startGame();
|
||||
} catch (NotEnoughPlayersException e) {
|
||||
|
||||
sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.UNKNOWN_ERROR,
|
||||
"Not enough players to start the game."));
|
||||
|
||||
}
|
||||
|
||||
} else if (SchafkopfMessageType.PLAYER_CARD.toString().equals(messageType)) {
|
||||
|
||||
onlinePlayer.receiveCard(Karte.valueOf(content.get("card").getAsString()));
|
||||
|
||||
} else if ("list_online_games".equals(messageType)) {
|
||||
System.out.println(
|
||||
"Received list_online_games message from " + session.getRemoteAddress() + ".");
|
||||
}
|
||||
|
||||
System.out.println(
|
||||
"Received message from Client " + session.getRemoteAddress() + " " + jsonMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setOnlinePlayer(OnlinePlayer onlinePlayer) {
|
||||
this.onlinePlayer = onlinePlayer;
|
||||
}
|
||||
|
||||
@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(SchafkopfBaseMessage message) {
|
||||
SchafkopfMessage schafkopfMessage = new SchafkopfMessage(
|
||||
SchafkopfMessageOrigin.DEDICATED_SERVER,
|
||||
message);
|
||||
System.out.println("Sending message to Client: " + schafkopfMessage.getMessageAsString());
|
||||
try {
|
||||
getRemote().sendString(schafkopfMessage.getMessageAsString());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user