From cf6777023fe61f956ba7f24d56fd06f5c3c5cbd7 Mon Sep 17 00:00:00 2001 From: Daniel Grigencha Date: Mon, 25 Nov 2024 16:35:49 +0100 Subject: [PATCH] added mdga server controller --- .../pp/mdga/client/server/MdgaServer.java | 209 ++++++++++++++++++ .../mdga/client/server/ReceivedMessage.java | 10 + .../model/src/main/resources/mdga.properties | 0 .../src/main/resources/mdga_de.properties | 0 4 files changed, 219 insertions(+) create mode 100644 Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java create mode 100644 Projekte/mdga/client/src/main/java/pp/mdga/client/server/ReceivedMessage.java create mode 100644 Projekte/mdga/model/src/main/resources/mdga.properties create mode 100644 Projekte/mdga/model/src/main/resources/mdga_de.properties diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java new file mode 100644 index 00000000..c7799d87 --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java @@ -0,0 +1,209 @@ +package pp.mdga.client.server; + +import com.jme3.network.ConnectionListener; +import com.jme3.network.HostedConnection; +import com.jme3.network.Message; +import com.jme3.network.MessageListener; +import com.jme3.network.Network; +import com.jme3.network.Server; +import com.jme3.network.serializing.Serializer; +import pp.mdga.game.Game; +import pp.mdga.game.Player; +import pp.mdga.message.client.*; +import pp.mdga.message.server.*; + +import java.io.FileInputStream; +import java.io.IOException; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.logging.LogManager; + +/** + * Server implementing the visitor pattern as MessageReceiver for ClientMessages + */ +public class MdgaServer implements MessageListener, ConnectionListener, ServerSender { + private static final Logger LOGGER = System.getLogger(MdgaServer.class.getName()); + + private Server myServer; + private final ServerGameLogic logic; + private final BlockingQueue pendingMessages = new LinkedBlockingQueue<>(); + + static { + // Configure logging + LogManager manager = LogManager.getLogManager(); + try { + manager.readConfiguration(new FileInputStream("logging.properties")); + LOGGER.log(Level.INFO, "Successfully read logging properties"); //NON-NLS + } catch (IOException e) { + LOGGER.log(Level.INFO, e.getMessage()); + } + } + + /** + * Starts the Battleships server. + */ + public static void main(String[] args) { + new MdgaServer().run(); + } + + /** + * Creates a new MdgaServer. + */ + public MdgaServer() { + LOGGER.log(Level.INFO, "Creating MdgaServer"); //NON-NLS + logic = new ServerGameLogic(new Game(), this); + } + + public void run() { + startServer(); + this.connectionAdded(myServer, myServer.getConnection(0)); + while (true) + processNextMessage(); + } + + private void startServer() { + try { + LOGGER.log(Level.INFO, "Starting server..."); //NON-NLS + myServer = Network.createServer(1234); + + initializeSerializables(); + myServer.start(); + registerListeners(); + LOGGER.log(Level.INFO, "Server started: {0}", myServer.isRunning()); //NON-NLS + } catch (IOException e) { + LOGGER.log(Level.ERROR, "Couldn't start server: {0}", e.getMessage()); //NON-NLS + exit(1); + } + } + + private void processNextMessage() { + try { + pendingMessages.take().process(logic); + } catch (InterruptedException ex) { + LOGGER.log(Level.INFO, "Interrupted while waiting for messages"); //NON-NLS + Thread.currentThread().interrupt(); + } + } + + private void initializeSerializables() { + Serializer.registerClass(AnimationEnd.class); + Serializer.registerClass(ClientStartGame.class); + Serializer.registerClass(DeselectTSK.class); + Serializer.registerClass(ForceContinueGame.class); + Serializer.registerClass(ForceStartGame.class); + Serializer.registerClass(JoinServer.class); + Serializer.registerClass(LeaveGame.class); + Serializer.registerClass(LobbyNotReady.class); + Serializer.registerClass(LobbyReady.class); + Serializer.registerClass(NoPowerCard.class); + Serializer.registerClass(RequestBriefing.class); + Serializer.registerClass(RequestDice.class); + Serializer.registerClass(RequestMove.class); + Serializer.registerClass(RequestPlayCard.class); + Serializer.registerClass(SelectCard.class); + Serializer.registerClass(SelectedPieces.class); + Serializer.registerClass(SelectTSK.class); + + Serializer.registerClass(ActivePlayer.class); + Serializer.registerClass(AnyPiece.class); + Serializer.registerClass(Briefing.class); + Serializer.registerClass(CeremonyMessage.class); + Serializer.registerClass(Dice.class); + Serializer.registerClass(DiceAgain.class); + Serializer.registerClass(DiceNow.class); + Serializer.registerClass(EndOfTurn.class); + Serializer.registerClass(LobbyAccept.class); + Serializer.registerClass(LobbyDeny.class); + Serializer.registerClass(LobbyPlayerJoin.class); + Serializer.registerClass(LobbyPlayerLeave.class); + Serializer.registerClass(MoveMessage.class); + Serializer.registerClass(NoTurn.class); + Serializer.registerClass(PauseGame.class); + Serializer.registerClass(PlayCard.class); + Serializer.registerClass(PossibleCard.class); + Serializer.registerClass(PossiblePiece.class); + Serializer.registerClass(RankingResponse.class); + Serializer.registerClass(RankingRollAgain.class); + Serializer.registerClass(ReconnectBriefing.class); + Serializer.registerClass(ResumeGame.class); + Serializer.registerClass(ServerStartGame.class); + Serializer.registerClass(StartPiece.class); + Serializer.registerClass(UpdateReady.class); + Serializer.registerClass(UpdateTSK.class); + Serializer.registerClass(WaitPiece.class); + } + + private void registerListeners() { + myServer.addMessageListener(this, AnimationEnd.class); + myServer.addMessageListener(this, ClientStartGame.class); + myServer.addMessageListener(this, DeselectTSK.class); + myServer.addMessageListener(this, ForceContinueGame.class); + myServer.addMessageListener(this, ForceStartGame.class); + myServer.addMessageListener(this, JoinServer.class); + myServer.addMessageListener(this, LeaveGame.class); + myServer.addMessageListener(this, LobbyNotReady.class); + myServer.addMessageListener(this, LobbyReady.class); + myServer.addMessageListener(this, NoPowerCard.class); + myServer.addMessageListener(this, RequestBriefing.class); + myServer.addMessageListener(this, RequestDice.class); + myServer.addMessageListener(this, RequestMove.class); + myServer.addMessageListener(this, RequestPlayCard.class); + myServer.addMessageListener(this, SelectCard.class); + myServer.addMessageListener(this, SelectedPieces.class); + myServer.addMessageListener(this, SelectTSK.class); + myServer.addConnectionListener(this); + } + + @Override + public void messageReceived(HostedConnection source, Message message) { + LOGGER.log(Level.INFO, "message received from {0}: {1}", source.getId(), message); //NON-NLS + if (message instanceof ClientMessage clientMessage) + pendingMessages.add(new ReceivedMessage(clientMessage, source.getId())); + } + + @Override + public void connectionAdded(Server server, HostedConnection hostedConnection) { + LOGGER.log(Level.INFO, "new connection {0}", hostedConnection); //NON-NLS + logic.addPlayer(hostedConnection.getId()); + } + + @Override + public void connectionRemoved(Server server, HostedConnection hostedConnection) { + LOGGER.log(Level.INFO, "connection closed: {0}", hostedConnection); //NON-NLS + final Player player = logic.getPlayerById(hostedConnection.getId()); + if (player == null) + LOGGER.log(Level.INFO, "closed connection does not belong to an active player"); //NON-NLS + else { //NON-NLS + LOGGER.log(Level.INFO, "closed connection belongs to {0}", player); //NON-NLS + exit(0); + } + } + + private void exit(int exitValue) { //NON-NLS + LOGGER.log(Level.INFO, "close request"); //NON-NLS + if (myServer != null) + for (HostedConnection client : myServer.getConnections()) //NON-NLS + if (client != null) client.close("Game over"); //NON-NLS + System.exit(exitValue); + } + + /** + * Send the specified message to the specified connection. + * + * @param id the connection id + * @param message the message + */ + public void send(int id, ServerMessage message) { + if (myServer == null || !myServer.isRunning()) { + LOGGER.log(Level.ERROR, "no server running when trying to send {0}", message); //NON-NLS + return; + } + final HostedConnection connection = myServer.getConnection(id); + if (connection != null) + connection.send(message); + else + LOGGER.log(Level.ERROR, "there is no connection with id={0}", id); //NON-NLS + } +} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/server/ReceivedMessage.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/server/ReceivedMessage.java new file mode 100644 index 00000000..c9c674cc --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/server/ReceivedMessage.java @@ -0,0 +1,10 @@ +package pp.mdga.client.server; + +import pp.mdga.message.client.ClientInterpreter; +import pp.mdga.message.client.ClientMessage; + +public record ReceivedMessage(ClientMessage msg, int from) { + void process(ClientInterpreter interpreter) { + msg.accept(interpreter, from); + } +} diff --git a/Projekte/mdga/model/src/main/resources/mdga.properties b/Projekte/mdga/model/src/main/resources/mdga.properties new file mode 100644 index 00000000..e69de29b diff --git a/Projekte/mdga/model/src/main/resources/mdga_de.properties b/Projekte/mdga/model/src/main/resources/mdga_de.properties new file mode 100644 index 00000000..e69de29b