From 9e28deedf7c76f03455e77b822aaa72825563136 Mon Sep 17 00:00:00 2001 From: Luca Puderbach Date: Mon, 18 Nov 2024 18:30:35 +0100 Subject: [PATCH 1/3] Grundlagen Lobby --- .../java/pp/monopoly/client/MonopolyApp.java | 2 + .../java/pp/monopoly/client/StartMenu.java | 1 - .../monopoly/client/gui/CreateGameMenu.java | 69 ++++---- .../client/server/MonopolyServer.java | 167 ++++++++++++++++++ .../client/server/ReceivedMessages.java | 17 ++ 5 files changed, 223 insertions(+), 33 deletions(-) create mode 100644 Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/MonopolyServer.java create mode 100644 Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/ReceivedMessages.java diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/MonopolyApp.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/MonopolyApp.java index baac5f7..b2dfdbb 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/MonopolyApp.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/MonopolyApp.java @@ -206,4 +206,6 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga guiNode.detachAllChildren(); // Entferne die GUI StartMenu.createStartMenu(this); // Zeige das Startmenü erneut } + + } diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/StartMenu.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/StartMenu.java index e1796cc..302bd55 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/StartMenu.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/StartMenu.java @@ -1,7 +1,6 @@ package pp.monopoly.client; import com.jme3.material.Material; -import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; import com.jme3.scene.Geometry; import com.jme3.scene.shape.Quad; diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java index 3705593..f62a805 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java @@ -1,8 +1,5 @@ package pp.monopoly.client.gui; -import com.jme3.input.KeyInput; -import com.jme3.input.controls.ActionListener; -import com.jme3.input.controls.KeyTrigger; import com.jme3.material.Material; import com.jme3.math.Vector3f; import com.jme3.scene.Geometry; @@ -17,6 +14,7 @@ import com.simsilica.lemur.component.SpringGridLayout; import pp.monopoly.client.MonopolyApp; import pp.monopoly.client.StartMenu; +import pp.monopoly.client.server.MonopolyServer; /** * CreateGameMenu class represents the menu for creating a new game. @@ -26,6 +24,8 @@ public class CreateGameMenu { private final MonopolyApp app; private final Container menuContainer; private Geometry background; + private Label serverStatusLabel; + private MonopolyServer monopolyServer; public CreateGameMenu(MonopolyApp app) { this.app = app; @@ -64,15 +64,18 @@ public class CreateGameMenu { cancelButton.setPreferredSize(new Vector3f(120, 40, 0)); cancelButton.addClickCommands(source -> goBackToStartMenu()); - // "Spiel hosten"-Button (funktionslos) - Button hostButton = buttonContainer.addChild(new Button("Spiel hosten")); + // "Selber hosten"-Button + Button hostButton = buttonContainer.addChild(new Button("Selber hosten")); hostButton.setPreferredSize(new Vector3f(120, 40, 0)); - // Keine Funktion zugewiesen + hostButton.addClickCommands(source -> startServer()); - // "Beitreten"-Button (ebenfalls funktionslos, falls benötigt) + // "Beitreten"-Button (vorerst funktionslos) Button joinButton = buttonContainer.addChild(new Button("Beitreten")); joinButton.setPreferredSize(new Vector3f(120, 40, 0)); - // Keine Funktion zugewiesen + + // Serverstatus-Label + serverStatusLabel = menuContainer.addChild(new Label("Serverstatus: Noch nicht gestartet")); + serverStatusLabel.setFontSize(24); // Zentrierung des Containers menuContainer.setLocalTranslation( @@ -81,10 +84,17 @@ public class CreateGameMenu { 1 // Höhere Z-Ebene für den Vordergrund ); - app.getGuiNode().attachChild(menuContainer); + app.getInputManager().addMapping("OpenTestWorld", new com.jme3.input.controls.KeyTrigger(com.jme3.input.KeyInput.KEY_T)); + app.getInputManager().addListener(new com.jme3.input.controls.ActionListener() { + @Override + public void onAction(String name, boolean isPressed, float tpf) { + if (name.equals("OpenTestWorld") && isPressed) { + app.startTestWorld(); // Öffnet die TestWorld + } + } + }, "OpenTestWorld"); - // Key-Mapping für Taste "T" - setupKeyMappings(); + app.getGuiNode().attachChild(menuContainer); } /** @@ -112,28 +122,23 @@ public class CreateGameMenu { } /** - * Fügt ein Key-Mapping hinzu, um die TestWorld mit der Taste "T" zu öffnen. + * Startet den Server in einem neuen Thread. */ - private void setupKeyMappings() { - app.getInputManager().addMapping("OpenTestWorld", new KeyTrigger(KeyInput.KEY_T)); - app.getInputManager().addListener(actionListener, "OpenTestWorld"); - } - - /** - * ActionListener, um auf Tastendrücke zu reagieren. - */ - private final ActionListener actionListener = (name, isPressed, tpf) -> { - if (name.equals("OpenTestWorld") && isPressed) { - openTestWorld(); + private void startServer() { + if (monopolyServer == null) { + serverStatusLabel.setText("Serverstatus: Wird gestartet..."); + new Thread(() -> { + try { + monopolyServer = new MonopolyServer(); // Erstelle Serverinstanz + monopolyServer.run(); // Starte Serverlogik + serverStatusLabel.setText("Serverstatus: Läuft auf Port " + monopolyServer.getConfig().getPort()); + } catch (Exception e) { + serverStatusLabel.setText("Serverstatus: Fehler beim Starten"); + e.printStackTrace(); + } + }).start(); + } else { + serverStatusLabel.setText("Serverstatus: Bereits gestartet!"); } - }; - - /** - * Öffnet die TestWorld. - */ - private void openTestWorld() { - app.getGuiNode().detachChild(menuContainer); - app.getGuiNode().detachChild(background); // Entfernt das Hintergrundbild - app.startTestWorld(); // Öffne die TestWorld } } diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/MonopolyServer.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/MonopolyServer.java new file mode 100644 index 0000000..d3c5444 --- /dev/null +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/MonopolyServer.java @@ -0,0 +1,167 @@ +//////////////////////////////////////// +// Programming project code +// UniBw M, 2022, 2023, 2024 +// www.unibw.de/inf2 +// (c) Mark Minas (mark.minas@unibw.de) +//////////////////////////////////////// + +package pp.monopoly.client.server; + +import java.io.File; +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; + +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.monopoly.MonopolyConfig; +import pp.monopoly.game.server.Player; +import pp.monopoly.game.server.ServerGameLogic; +import pp.monopoly.game.server.ServerSender; +import pp.monopoly.message.client.ClientMessage; +import pp.monopoly.message.server.ServerMessage; +import pp.monopoly.model.IntPoint; + +/** + * Server implementing the visitor pattern as MessageReceiver for ClientMessages + */ +public class MonopolyServer implements MessageListener, ConnectionListener, ServerSender { + private static final Logger LOGGER = System.getLogger(MonopolyServer.class.getName()); + private static final File CONFIG_FILE = new File("server.properties"); + + private final MonopolyConfig config = new MonopolyConfig(); + 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 Monopolys server. + */ + public static void main(String[] args) { + new MonopolyServer().run(); + } + + /** + * Creates the server. + */ + public MonopolyServer() { + config.readFromIfExists(CONFIG_FILE); + LOGGER.log(Level.INFO, "Configuration: {0}", config); //NON-NLS + logic = new ServerGameLogic(this, config); + } + + public void run() { + startServer(); + while (true) + processNextMessage(); + } + + private void startServer() { + try { + LOGGER.log(Level.INFO, "Starting server..."); //NON-NLS + myServer = Network.createServer(config.getPort()); + 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(IntPoint.class); + } + + private void registerListeners() { + 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 + } + public MonopolyConfig getConfig() { + return config; + } +} \ No newline at end of file diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/ReceivedMessages.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/ReceivedMessages.java new file mode 100644 index 0000000..fc30df3 --- /dev/null +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/ReceivedMessages.java @@ -0,0 +1,17 @@ +//////////////////////////////////////// +// Programming project code +// UniBw M, 2022, 2023, 2024 +// www.unibw.de/inf2 +// (c) Mark Minas (mark.minas@unibw.de) +//////////////////////////////////////// + +package pp.monopoly.client.server; + +import pp.monopoly.message.client.ClientInterpreter; +import pp.monopoly.message.client.ClientMessage; + +record ReceivedMessage(ClientMessage message, int from) { + void process(ClientInterpreter interpreter) { + message.accept(interpreter, from); + } +} From 0b46d14650fce106cc4cdbe9d3b056a5b55f017e Mon Sep 17 00:00:00 2001 From: Luca Puderbach Date: Mon, 18 Nov 2024 18:56:42 +0100 Subject: [PATCH 2/3] =?UTF-8?q?LobbyServer=20Einf=C3=BCgen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/pp/battleship/client/Menu.java | 13 +- .../monopoly/client/gui/CreateGameMenu.java | 21 ++- .../pp/monopoly/client/gui/ServerScreen.java | 89 ++++++++++ .../pp/monopoly/client/gui/SettingsMenu.java | 1 + .../client/server/MonopolyServer.java | 167 ------------------ .../client/server/ReceivedMessages.java | 17 -- .../main/java/pp/monopoly/MonopolyConfig.java | 9 +- 7 files changed, 118 insertions(+), 199 deletions(-) create mode 100644 Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/ServerScreen.java delete mode 100644 Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/MonopolyServer.java delete mode 100644 Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/ReceivedMessages.java diff --git a/Projekte/battleship/client/src/main/java/pp/battleship/client/Menu.java b/Projekte/battleship/client/src/main/java/pp/battleship/client/Menu.java index 9143899..44a9a74 100644 --- a/Projekte/battleship/client/src/main/java/pp/battleship/client/Menu.java +++ b/Projekte/battleship/client/src/main/java/pp/battleship/client/Menu.java @@ -7,22 +7,21 @@ package pp.battleship.client; +import java.io.File; +import java.io.IOException; +import java.util.prefs.Preferences; + import com.simsilica.lemur.Button; import com.simsilica.lemur.Checkbox; import com.simsilica.lemur.Label; import com.simsilica.lemur.style.ElementId; +import static pp.battleship.Resources.lookup; import pp.battleship.client.gui.GameMusic; import pp.battleship.client.gui.VolumeSlider; import pp.dialog.Dialog; import pp.dialog.StateCheckboxModel; import pp.dialog.TextInputDialog; - -import java.io.File; -import java.io.IOException; -import java.util.prefs.Preferences; - -import static pp.battleship.Resources.lookup; import static pp.util.PreferencesUtils.getPreferences; /** @@ -39,7 +38,7 @@ class Menu extends Dialog { private final VolumeSlider slider; /** - * Constructs the Menu dialog for the Battleship application. + * Constructs the Menu dialog for the Battleship application.+ * * @param app the BattleshipApp instance */ diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java index f62a805..cc76a4d 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java @@ -1,7 +1,11 @@ package pp.monopoly.client.gui; +import javax.swing.JOptionPane; + import com.jme3.material.Material; import com.jme3.math.Vector3f; +import com.jme3.network.Client; +import com.jme3.network.Network; import com.jme3.scene.Geometry; import com.jme3.scene.shape.Quad; import com.jme3.texture.Texture; @@ -14,7 +18,7 @@ import com.simsilica.lemur.component.SpringGridLayout; import pp.monopoly.client.MonopolyApp; import pp.monopoly.client.StartMenu; -import pp.monopoly.client.server.MonopolyServer; +import pp.monopoly.server.MonopolyServer; /** * CreateGameMenu class represents the menu for creating a new game. @@ -26,6 +30,7 @@ public class CreateGameMenu { private Geometry background; private Label serverStatusLabel; private MonopolyServer monopolyServer; + private Client client; public CreateGameMenu(MonopolyApp app) { this.app = app; @@ -130,7 +135,6 @@ public class CreateGameMenu { new Thread(() -> { try { monopolyServer = new MonopolyServer(); // Erstelle Serverinstanz - monopolyServer.run(); // Starte Serverlogik serverStatusLabel.setText("Serverstatus: Läuft auf Port " + monopolyServer.getConfig().getPort()); } catch (Exception e) { serverStatusLabel.setText("Serverstatus: Fehler beim Starten"); @@ -141,4 +145,17 @@ public class CreateGameMenu { serverStatusLabel.setText("Serverstatus: Bereits gestartet!"); } } + + private void joinGame(String host, String port) { + try { + int portNumber = Integer.parseInt(port); + client = Network.connectToServer(host, portNumber); // Verbindet sich mit Server + client.start(); + JOptionPane.showMessageDialog(null, "Erfolgreich mit dem Server verbunden: " + host + ":" + port); + // Hier kannst du zusätzliche Logik für das Verbinden hinzufügen + } catch (Exception e) { + JOptionPane.showMessageDialog(null, "Fehler beim Verbinden mit dem Server: " + e.getMessage(), + "Verbindungsfehler", JOptionPane.ERROR_MESSAGE); + } + } } diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/ServerScreen.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/ServerScreen.java new file mode 100644 index 0000000..c2794ab --- /dev/null +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/ServerScreen.java @@ -0,0 +1,89 @@ +package pp.monopoly.client.gui; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; + +public class ServerScreen { + private JFrame frame; + private JTextField inputField; + private JLabel label; + private JButton startButton; + private JButton stopButton; + + public ServerScreen() { + initialize(); + } + + private void initialize() { + // Erstelle das Hauptfenster + frame = new JFrame("Server Placeholder"); // Setze den Titel + frame.setSize(400, 200); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setLayout(new BorderLayout()); + + // Eingabefeld und Label im oberen Bereich + JPanel topPanel = new JPanel(); + topPanel.setLayout(new FlowLayout()); + + label = new JLabel("Server-Port:"); + inputField = new JTextField("42069", 10); + topPanel.add(label); + topPanel.add(inputField); + + // Buttons im unteren Bereich + JPanel bottomPanel = new JPanel(); + bottomPanel.setLayout(new FlowLayout()); + + startButton = new JButton("Start Server"); + stopButton = new JButton("Stop Server"); + stopButton.setEnabled(false); // Stop-Button ist anfangs deaktiviert + + bottomPanel.add(startButton); + bottomPanel.add(stopButton); + + // Füge die Panels zum Hauptfenster hinzu + frame.add(topPanel, BorderLayout.NORTH); + frame.add(bottomPanel, BorderLayout.SOUTH); + + // Aktion für Start-Button + startButton.addActionListener(e -> startServer()); + + // Aktion für Stop-Button + stopButton.addActionListener(e -> stopServer()); + + // Zeige das Fenster + frame.setVisible(true); + } + + private void startServer() { + String port = inputField.getText(); + try { + int portNumber = Integer.parseInt(port); + // Server-Startlogik hier einfügen + JOptionPane.showMessageDialog(frame, "Server gestartet auf Port " + portNumber); + startButton.setEnabled(false); // Deaktiviere den Start-Button + stopButton.setEnabled(true); // Aktiviere den Stop-Button + } catch (NumberFormatException e) { + JOptionPane.showMessageDialog(frame, "Ungültiger Port: " + port, "Fehler", JOptionPane.ERROR_MESSAGE); + } + } + + private void stopServer() { + // Server-Stoplogik hier einfügen + JOptionPane.showMessageDialog(frame, "Server gestoppt."); + startButton.setEnabled(true); // Aktiviere den Start-Button + stopButton.setEnabled(false); // Deaktiviere den Stop-Button + } + + public static void main(String[] args) { + SwingUtilities.invokeLater(ServerScreen::new); + } +} diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/SettingsMenu.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/SettingsMenu.java index 6997c45..1539b19 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/SettingsMenu.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/SettingsMenu.java @@ -56,6 +56,7 @@ public class SettingsMenu extends Dialog { Button quitButton = settingsContainer.addChild(new Button("Beenden", new ElementId("menu-button"))); quitButton.setFontSize(32); quitButton.addClickCommands(source -> app.stop()); + // Zentriere das Menü settingsContainer.setLocalTranslation( diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/MonopolyServer.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/MonopolyServer.java deleted file mode 100644 index d3c5444..0000000 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/MonopolyServer.java +++ /dev/null @@ -1,167 +0,0 @@ -//////////////////////////////////////// -// Programming project code -// UniBw M, 2022, 2023, 2024 -// www.unibw.de/inf2 -// (c) Mark Minas (mark.minas@unibw.de) -//////////////////////////////////////// - -package pp.monopoly.client.server; - -import java.io.File; -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; - -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.monopoly.MonopolyConfig; -import pp.monopoly.game.server.Player; -import pp.monopoly.game.server.ServerGameLogic; -import pp.monopoly.game.server.ServerSender; -import pp.monopoly.message.client.ClientMessage; -import pp.monopoly.message.server.ServerMessage; -import pp.monopoly.model.IntPoint; - -/** - * Server implementing the visitor pattern as MessageReceiver for ClientMessages - */ -public class MonopolyServer implements MessageListener, ConnectionListener, ServerSender { - private static final Logger LOGGER = System.getLogger(MonopolyServer.class.getName()); - private static final File CONFIG_FILE = new File("server.properties"); - - private final MonopolyConfig config = new MonopolyConfig(); - 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 Monopolys server. - */ - public static void main(String[] args) { - new MonopolyServer().run(); - } - - /** - * Creates the server. - */ - public MonopolyServer() { - config.readFromIfExists(CONFIG_FILE); - LOGGER.log(Level.INFO, "Configuration: {0}", config); //NON-NLS - logic = new ServerGameLogic(this, config); - } - - public void run() { - startServer(); - while (true) - processNextMessage(); - } - - private void startServer() { - try { - LOGGER.log(Level.INFO, "Starting server..."); //NON-NLS - myServer = Network.createServer(config.getPort()); - 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(IntPoint.class); - } - - private void registerListeners() { - 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 - } - public MonopolyConfig getConfig() { - return config; - } -} \ No newline at end of file diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/ReceivedMessages.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/ReceivedMessages.java deleted file mode 100644 index fc30df3..0000000 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/server/ReceivedMessages.java +++ /dev/null @@ -1,17 +0,0 @@ -//////////////////////////////////////// -// Programming project code -// UniBw M, 2022, 2023, 2024 -// www.unibw.de/inf2 -// (c) Mark Minas (mark.minas@unibw.de) -//////////////////////////////////////// - -package pp.monopoly.client.server; - -import pp.monopoly.message.client.ClientInterpreter; -import pp.monopoly.message.client.ClientMessage; - -record ReceivedMessage(ClientMessage message, int from) { - void process(ClientInterpreter interpreter) { - message.accept(interpreter, from); - } -} diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/MonopolyConfig.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/MonopolyConfig.java index b65c514..3a5da01 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/MonopolyConfig.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/MonopolyConfig.java @@ -7,13 +7,10 @@ package pp.monopoly; -import pp.util.config.Config; - -import java.util.Map; -import java.util.TreeMap; - import static java.lang.Math.max; +import pp.util.config.Config; + /** * Provides access to the configuration settings for the Monopoly game. *

@@ -31,7 +28,7 @@ public class MonopolyConfig extends Config { * The default port number for the Monopoly server. */ @Property("port") - private int port = 1234; + private int port = 42069; /** * The width of the game map in terms of grid units. From e2126a7ea7a1c3b15f70ec79526a0d68fb23da0e Mon Sep 17 00:00:00 2001 From: Johannes Schmelz Date: Mon, 18 Nov 2024 23:01:34 +0100 Subject: [PATCH 3/3] implemented self host for server --- Projekte/.run/MonopolyApp.run.xml | 18 +++++++++ Projekte/.run/MonopolyServer.run.xml | 17 +++++++++ Projekte/monopoly/client/build.gradle | 1 + .../java/pp/monopoly/client/MonopolyApp.java | 20 ++++++++++ .../monopoly/client/gui/CreateGameMenu.java | 37 +------------------ .../pp/monopoly/server/MonopolyServer.java | 2 +- 6 files changed, 58 insertions(+), 37 deletions(-) create mode 100644 Projekte/.run/MonopolyApp.run.xml create mode 100644 Projekte/.run/MonopolyServer.run.xml diff --git a/Projekte/.run/MonopolyApp.run.xml b/Projekte/.run/MonopolyApp.run.xml new file mode 100644 index 0000000..ccd1e2f --- /dev/null +++ b/Projekte/.run/MonopolyApp.run.xml @@ -0,0 +1,18 @@ + + + + \ No newline at end of file diff --git a/Projekte/.run/MonopolyServer.run.xml b/Projekte/.run/MonopolyServer.run.xml new file mode 100644 index 0000000..d892cf3 --- /dev/null +++ b/Projekte/.run/MonopolyServer.run.xml @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/Projekte/monopoly/client/build.gradle b/Projekte/monopoly/client/build.gradle index 7582682..66985e3 100644 --- a/Projekte/monopoly/client/build.gradle +++ b/Projekte/monopoly/client/build.gradle @@ -7,6 +7,7 @@ description = 'Monopoly Client' dependencies { implementation project(":jme-common") implementation project(":monopoly:model") + implementation project(":monopoly:server") implementation libs.jme3.desktop diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/MonopolyApp.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/MonopolyApp.java index b2dfdbb..0a7df7d 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/MonopolyApp.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/MonopolyApp.java @@ -9,8 +9,10 @@ import com.jme3.font.BitmapText; import com.jme3.input.KeyInput; import com.jme3.input.controls.ActionListener; import com.jme3.input.controls.KeyTrigger; + import com.jme3.system.AppSettings; import com.simsilica.lemur.GuiGlobals; +import com.simsilica.lemur.Label; import com.simsilica.lemur.style.BaseStyles; import pp.dialog.DialogBuilder; @@ -23,6 +25,7 @@ import pp.monopoly.game.client.MonopolyClient; import pp.monopoly.game.client.ServerConnection; import pp.monopoly.notification.GameEventListener; import pp.monopoly.notification.InfoTextEvent; +import pp.monopoly.server.MonopolyServer; public class MonopolyApp extends SimpleApplication implements MonopolyClient, GameEventListener { private BitmapText topText; @@ -37,6 +40,8 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga private TestWorld testWorld; private boolean isSettingsMenuOpen = false; private boolean inputBlocked = false; + private MonopolyServer monopolyServer; + /** * Path to the styles script for GUI elements. */ @@ -207,5 +212,20 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga StartMenu.createStartMenu(this); // Zeige das Startmenü erneut } + /** + * Startet den Server in einem neuen Thread. + */ + public void startServer() { + new Thread(() -> { + try { + monopolyServer = new MonopolyServer(); // Erstelle Serverinstanz + } catch (Exception e) { + e.printStackTrace(); + } + }).start(); + } + public MonopolyServer getMonopolyServer() { + return monopolyServer; + } } diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java index cc76a4d..d3529b0 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java @@ -29,8 +29,6 @@ public class CreateGameMenu { private final Container menuContainer; private Geometry background; private Label serverStatusLabel; - private MonopolyServer monopolyServer; - private Client client; public CreateGameMenu(MonopolyApp app) { this.app = app; @@ -72,7 +70,7 @@ public class CreateGameMenu { // "Selber hosten"-Button Button hostButton = buttonContainer.addChild(new Button("Selber hosten")); hostButton.setPreferredSize(new Vector3f(120, 40, 0)); - hostButton.addClickCommands(source -> startServer()); + hostButton.addClickCommands(source -> app.startServer()); // "Beitreten"-Button (vorerst funktionslos) Button joinButton = buttonContainer.addChild(new Button("Beitreten")); @@ -125,37 +123,4 @@ public class CreateGameMenu { app.getGuiNode().detachChild(background); // Entfernt das Hintergrundbild StartMenu.createStartMenu(app); } - - /** - * Startet den Server in einem neuen Thread. - */ - private void startServer() { - if (monopolyServer == null) { - serverStatusLabel.setText("Serverstatus: Wird gestartet..."); - new Thread(() -> { - try { - monopolyServer = new MonopolyServer(); // Erstelle Serverinstanz - serverStatusLabel.setText("Serverstatus: Läuft auf Port " + monopolyServer.getConfig().getPort()); - } catch (Exception e) { - serverStatusLabel.setText("Serverstatus: Fehler beim Starten"); - e.printStackTrace(); - } - }).start(); - } else { - serverStatusLabel.setText("Serverstatus: Bereits gestartet!"); - } - } - - private void joinGame(String host, String port) { - try { - int portNumber = Integer.parseInt(port); - client = Network.connectToServer(host, portNumber); // Verbindet sich mit Server - client.start(); - JOptionPane.showMessageDialog(null, "Erfolgreich mit dem Server verbunden: " + host + ":" + port); - // Hier kannst du zusätzliche Logik für das Verbinden hinzufügen - } catch (Exception e) { - JOptionPane.showMessageDialog(null, "Fehler beim Verbinden mit dem Server: " + e.getMessage(), - "Verbindungsfehler", JOptionPane.ERROR_MESSAGE); - } - } } diff --git a/Projekte/monopoly/server/src/main/java/pp/monopoly/server/MonopolyServer.java b/Projekte/monopoly/server/src/main/java/pp/monopoly/server/MonopolyServer.java index 73aaa17..f02f48d 100644 --- a/Projekte/monopoly/server/src/main/java/pp/monopoly/server/MonopolyServer.java +++ b/Projekte/monopoly/server/src/main/java/pp/monopoly/server/MonopolyServer.java @@ -65,7 +65,7 @@ public class MonopolyServer implements MessageListener, Connec /** * Creates the server. */ - MonopolyServer() { + public MonopolyServer() { config.readFromIfExists(CONFIG_FILE); LOGGER.log(Level.INFO, "Configuration: {0}", config); //NON-NLS logic = new ServerGameLogic(this, config);