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

@@ -36,7 +36,7 @@
</descriptorRefs>
<archive>
<manifest>
<mainClass>org.schafkopf.Main</mainClass>
<mainClass>org.schafkopf.DedicatedServer</mainClass>
</manifest>
</archive>
</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());
}
}
}