From ddbf79c928b60a0ea1aad0a849e139734b6c70b3 Mon Sep 17 00:00:00 2001 From: Luca Puderbach Date: Wed, 20 Nov 2024 02:37:00 +0100 Subject: [PATCH 1/2] can now add players --- .../java/pp/monopoly/client/MonopolyApp.java | 32 +++++---- .../pp/monopoly/client/NetworkSupport.java | 38 +++++++++- .../monopoly/client/gui/CreateGameMenu.java | 71 +++++++------------ .../monopoly/game/server/ServerGameLogic.java | 21 +++--- .../pp/monopoly/server/MonopolyServer.java | 34 ++++----- 5 files changed, 111 insertions(+), 85 deletions(-) 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 9bfea69..4adde8d 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,10 +9,8 @@ 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; @@ -28,6 +26,7 @@ import pp.monopoly.notification.InfoTextEvent; import pp.monopoly.server.MonopolyServer; public class MonopolyApp extends SimpleApplication implements MonopolyClient, GameEventListener { + private BitmapText topText; private final ServerConnection serverConnection; private final ClientGameLogic logic; @@ -41,16 +40,16 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga private boolean isSettingsMenuOpen = false; private boolean inputBlocked = false; private MonopolyServer monopolyServer; + private NetworkSupport networkSupport; /** * Path to the styles script for GUI elements. */ - private static final String STYLES_SCRIPT = "Interface/Lemur/pp-styles.groovy"; //NON-NLS + private static final String STYLES_SCRIPT = "Interface/Lemur/pp-styles.groovy"; // NON-NLS /** * Path to the font resource used in the GUI. */ - private static final String FONT = "Interface/Fonts/Default.fnt"; //NON-NLS - + private static final String FONT = "Interface/Fonts/Default.fnt"; // NON-NLS public static void main(String[] args) { new MonopolyApp().start(); @@ -59,7 +58,8 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga public MonopolyApp() { this.draw = new Draw(assetManager); config = new MonopolyAppConfig(); - serverConnection = new NetworkSupport(this); + networkSupport = new NetworkSupport(this); // Initialize NetworkSupport + serverConnection = networkSupport; logic = new ClientGameLogic(serverConnection); logic.addListener(this); setShowSettings(config.getShowSettings()); @@ -76,6 +76,10 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga return logic; } + public NetworkSupport getNetworkSupport() { + return networkSupport; + } + private AppSettings makeSettings() { final AppSettings settings = new AppSettings(true); settings.setTitle("Monopoly Game"); @@ -88,8 +92,8 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga public void simpleInitApp() { GuiGlobals.initialize(this); BaseStyles.loadStyleResources(STYLES_SCRIPT); - GuiGlobals.getInstance().getStyles().setDefaultStyle("pp"); //NON-NLS - final BitmapFont normalFont = assetManager.loadFont(FONT); //NON-NLS + GuiGlobals.getInstance().getStyles().setDefaultStyle("pp"); // NON-NLS + final BitmapFont normalFont = assetManager.loadFont(FONT); // NON-NLS setupInput(); setupGui(); @@ -129,18 +133,16 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga } } } - - private void blockInputs() { if (!inputBlocked) { System.out.println("Blockiere Eingaben..."); inputManager.setCursorVisible(true); // Cursor sichtbar machen - inputManager.clearMappings(); // Alle Mappings entfernen + inputManager.clearMappings(); // Alle Mappings entfernen inputBlocked = true; } } - + public void unblockInputs() { if (inputBlocked) { System.out.println("Aktiviere Eingaben..."); @@ -204,7 +206,7 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga public void startTestWorld() { guiNode.detachAllChildren(); // Entferne GUI testWorld = new TestWorld(this); // Erstelle eine Instanz von TestWorld - testWorld.initializeScene(); // Initialisiere die Szene + testWorld.initializeScene(); // Initialisiere die Szene } public void returnToMenu() { @@ -218,9 +220,9 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga public void startServer() { new Thread(() -> { try { - monopolyServer = new MonopolyServer(); // Erstelle Serverinstanz + MonopolyServer.main(new String[0]); // Startet den MonopolyServer } catch (Exception e) { - e.printStackTrace(); + errorDialog("Fehler: Server konnte nicht gestartet werden."); } }).start(); } diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/NetworkSupport.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/NetworkSupport.java index 3ea11b0..6ae24fd 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/NetworkSupport.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/NetworkSupport.java @@ -18,7 +18,7 @@ import pp.monopoly.message.server.ServerMessage; * Manages the network connection for the Monopoly application. * Handles connecting to and disconnecting from the server, and sending messages. */ -class NetworkSupport implements MessageListener, ClientStateListener, ServerConnection { +public class NetworkSupport implements MessageListener, ClientStateListener, ServerConnection { private static final Logger LOGGER = System.getLogger(NetworkSupport.class.getName()); private final MonopolyApp app; private Client client; @@ -141,4 +141,40 @@ class NetworkSupport implements MessageListener, ClientStateListener, Se client.send(message); } } + public void startServerAndJoin() { + new Thread(() -> { + // Server starten + app.startServer(); + + // Warten, bis der Server tatsächlich betriebsbereit ist + int retries = 5; + while (retries > 0) { + try { + initNetwork("localhost", app.getConfig().getPort()); + app.enqueue(() -> app.setInfoText("Erfolgreich verbunden!")); + return; // Verbindung erfolgreich + } catch (IOException e) { + retries--; + try { + Thread.sleep(1000); // Eine Sekunde warten und erneut versuchen + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + break; // Abbrechen, wenn der Thread unterbrochen wird + } + } + } + + // Wenn alle Versuche fehlschlagen + app.enqueue(() -> app.errorDialog("Fehler: Verbindung zum Server fehlgeschlagen.")); + }).start(); + } + + public void connectToServer(String host, int port) { + try { + initNetwork(host, port); // Verbindung initialisieren + app.setInfoText("Erfolgreich mit Server verbunden!"); + } catch (IOException e) { + app.errorDialog("Fehler: Verbindung zum Server fehlgeschlagen."); + } + } } \ No newline at end of file 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 cd10d18..c406272 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 @@ -15,13 +15,16 @@ import com.simsilica.lemur.component.SpringGridLayout; import pp.monopoly.client.MonopolyApp; import pp.monopoly.client.StartMenu; + +/** + * CreateGameMenu class represents the menu for creating a new game. + */ public class CreateGameMenu { private final MonopolyApp app; private final Container menuContainer; private Geometry background; - private TextField serverAddressField; - private TextField portField; + private Label serverStatusLabel; public CreateGameMenu(MonopolyApp app) { this.app = app; @@ -43,12 +46,12 @@ public class CreateGameMenu { inputContainer.setLocalTranslation(20, 0, 0); // Abstand vom Rand inputContainer.addChild(new Label("Server-Adresse:")); - serverAddressField = inputContainer.addChild(new TextField("localhost")); - serverAddressField.setPreferredWidth(400); // Breite des Textfelds + TextField playerNameField = inputContainer.addChild(new TextField("localhost")); + playerNameField.setPreferredWidth(400); // Breite des Textfelds inputContainer.addChild(new Label("Port:")); - portField = inputContainer.addChild(new TextField("42069")); - portField.setPreferredWidth(400); // Breite des Textfelds + TextField serverAddressField = inputContainer.addChild(new TextField("42069")); + serverAddressField.setPreferredWidth(400); // Breite des Textfelds // Button-Container Container buttonContainer = menuContainer.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y))); @@ -63,15 +66,29 @@ public class CreateGameMenu { // "Selber hosten"-Button Button hostButton = buttonContainer.addChild(new Button("Selber hosten")); hostButton.setPreferredSize(new Vector3f(120, 40, 0)); - // hostButton.addClickCommands(source -> startServerAndJoin()); + hostButton.addClickCommands(source -> app.getNetworkSupport().startServerAndJoin()); - // "Beitreten"-Button (vorerst funktionslos) + // "Beitreten"-Button Button joinButton = buttonContainer.addChild(new Button("Beitreten")); joinButton.setPreferredSize(new Vector3f(120, 40, 0)); - // joinButton.addClickCommands(source -> joinServer()); + joinButton.addClickCommands(source -> { + try { + String host = playerNameField.getText().trim(); + int port = Integer.parseInt(serverAddressField.getText().trim()); + app.getNetworkSupport().connectToServer(host, port); + + // LobbyMenu öffnen + app.enqueue(() -> { + app.getGuiNode().detachAllChildren(); // Bestehende GUI entfernen + new LobbyMenu(app); // LobbyMenu erstellen + }); + } catch (NumberFormatException e) { + app.errorDialog("Port muss eine Zahl sein."); + } + }); // Serverstatus-Label - Label serverStatusLabel = menuContainer.addChild(new Label("Serverstatus: Noch nicht gestartet")); + serverStatusLabel = menuContainer.addChild(new Label("Serverstatus: Noch nicht gestartet")); serverStatusLabel.setFontSize(24); // Zentrierung des Containers @@ -116,38 +133,4 @@ public class CreateGameMenu { app.getGuiNode().detachChild(background); // Entfernt das Hintergrundbild StartMenu.createStartMenu(app); } - - /** - * Startet den Server und tritt nach 2 Sekunden der Lobby bei. - */ - //private void startServerAndJoin() { - // new Thread(() -> { - // app.start(); - // app.startServer(); -// - // // Warte 2 Sekunden - // try { - // Thread.sleep(2000); - // } catch (InterruptedException e) { - // Thread.currentThread().interrupt(); - // } -// - // // Verbinde mit dem Server - // app.enqueue(() -> joinServer()); - // }).start(); - //} - - /** - * Tritt dem Server basierend auf den Eingaben bei. - */ - //private void joinServer() { - // String serverAddress = serverAddressField.getText(); - // int port = Integer.parseInt(portField.getText()); - // app.getServerConnection().connect(serverAddress, port); - - // // Öffnet die Lobby - // app.getGuiNode().detachChild(menuContainer); - // app.getGuiNode().detachChild(background); // Entfernt das Hintergrundbild - // new LobbyMenu(app); - //} } diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/game/server/ServerGameLogic.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/game/server/ServerGameLogic.java index 62cdd72..a65b791 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/game/server/ServerGameLogic.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/game/server/ServerGameLogic.java @@ -1,7 +1,17 @@ package pp.monopoly.game.server; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; + import pp.monopoly.MonopolyConfig; -import pp.monopoly.message.client.*; +import pp.monopoly.message.client.BuyPropertyRequest; +import pp.monopoly.message.client.ClientInterpreter; +import pp.monopoly.message.client.EndTurn; +import pp.monopoly.message.client.PlayerReady; +import pp.monopoly.message.client.RollDice; +import pp.monopoly.message.client.TradeOffer; +import pp.monopoly.message.client.TradeResponse; +import pp.monopoly.message.client.ViewAssetsRequest; import pp.monopoly.message.server.ServerMessage; import pp.monopoly.message.server.TradeReply; import pp.monopoly.message.server.TradeRequest; @@ -9,13 +19,6 @@ import pp.monopoly.message.server.ViewAssetsResponse; import pp.monopoly.model.fields.BoardManager; import pp.monopoly.model.fields.PropertyField; -import java.lang.System.Logger; -import java.lang.System.Logger.Level; - -import pp.monopoly.MonopolyConfig; -import pp.monopoly.message.client.ClientInterpreter; -import pp.monopoly.message.server.ServerMessage; - /** * Controls the server-side game logic for Monopoly. * Manages game states, player interactions, and message handling. @@ -26,7 +29,7 @@ public class ServerGameLogic implements ClientInterpreter { private final MonopolyConfig config; private final PlayerHandler playerHandler = new PlayerHandler(this); private final ServerSender serverSender; - private ServerState state = ServerState.CREATEGAME; + private ServerState state = ServerState.LOBBY; private static final int MAX_PLAYERS = 6; private BoardManager boardManager = new BoardManager(); 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 f02f48d..f4bfa7e 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 @@ -7,21 +7,6 @@ package pp.monopoly.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.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; - import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -31,6 +16,22 @@ 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 */ @@ -119,8 +120,9 @@ public class MonopolyServer implements MessageListener, Connec @Override public void connectionAdded(Server server, HostedConnection hostedConnection) { - LOGGER.log(Level.INFO, "new connection {0}", hostedConnection); //NON-NLS + LOGGER.log(Level.INFO, "New connection established: {0}", hostedConnection); //NON-NLS logic.addPlayer(hostedConnection.getId()); + System.out.println("Spieler verbunden: ID = " + hostedConnection.getId()); } @Override From f6f708fd5b6f986f8414b16df9352bc08d499dc2 Mon Sep 17 00:00:00 2001 From: Simon Wilkening Date: Wed, 20 Nov 2024 03:17:10 +0100 Subject: [PATCH 2/2] Angepasste Toolbar --- .../java/pp/monopoly/client/gui/Toolbar.java | 76 ++++++++++++++++--- 1 file changed, 65 insertions(+), 11 deletions(-) diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/Toolbar.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/Toolbar.java index 5a9a3f0..a2201b5 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/Toolbar.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/Toolbar.java @@ -3,20 +3,22 @@ package pp.monopoly.client.gui; import java.util.Random; import com.jme3.font.BitmapText; +import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; import com.jme3.scene.Geometry; -import com.simsilica.lemur.Axis; -import com.simsilica.lemur.Button; -import com.simsilica.lemur.Container; +import com.simsilica.lemur.*; +import com.simsilica.lemur.component.QuadBackgroundComponent; import com.simsilica.lemur.component.SpringGridLayout; +import com.simsilica.lemur.style.ElementId; +import pp.dialog.Dialog; import pp.monopoly.client.MonopolyApp; /** * Toolbar Klasse, die am unteren Rand der Szene angezeigt wird. * Die Buttons bewegen den Würfel auf dem Spielfeld. */ -public class Toolbar { +public class Toolbar extends Dialog { private final MonopolyApp app; private final Container toolbarContainer; @@ -35,6 +37,7 @@ public class Toolbar { * @param cube Der Würfel, der bewegt werden soll */ public Toolbar(MonopolyApp app, Geometry cube) { + super(app.getDialogManager()); this.app = app; this.cube = cube; @@ -44,13 +47,41 @@ public class Toolbar { // Setze die Position am unteren Rand und die Breite toolbarContainer.setLocalTranslation( 0, // Links bündig - 100, // Höhe über dem unteren Rand + 200, // Höhe über dem unteren Rand 0 // Z-Ebene ); - toolbarContainer.setPreferredSize(new Vector3f(app.getCamera().getWidth(), 100, 0)); // Volle Breite + toolbarContainer.setPreferredSize(new Vector3f(app.getCamera().getWidth(), 200, 0)); // Volle Breite + + // Hintergrund Grau + toolbarContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Füge Buttons zur Toolbar hinzu - initializeButtons(); + //initializeButtons(); + + + // Menü-Container: Ein Nested-Container für Kontostand und "Meine Gulag Frei Karten" + Container accountContainer = toolbarContainer.addChild(new Container()); + accountContainer.addChild(new Label("Kontostand", new ElementId("label"))); + accountContainer.addChild(new Label("Gulag Frei Karten", new ElementId("label"))); + accountContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f))); + + // Menü-Container: Ein Container für Übersicht + Container overviewContainer = toolbarContainer.addChild(new Container()); + overviewContainer.addChild(new Label("Übersicht", new ElementId("label"))); + overviewContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f))); + + // Menü-Container: Ein Container für Würfel + Container diceContainer = toolbarContainer.addChild(new Container()); + diceContainer.addChild(new Label("Wo Würfel?", new ElementId("label"))); + diceContainer.addChild(new Button("Würfeln")); + diceContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f))); + + // Menü-Container: Ein Nested-Container für Handeln, Grundstücke und Zug beenden + Container menuContainer = toolbarContainer.addChild(new Container()); + menuContainer.addChild(new Button("Handeln")); + menuContainer.addChild(new Button("Grundstücke")); + menuContainer.addChild(new Button("Zug beenden")); + menuContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f))); // Füge die Toolbar zur GUI hinzu app.getGuiNode().attachChild(toolbarContainer); @@ -64,9 +95,10 @@ public class Toolbar { * Initialisiert die Buttons in der Toolbar. */ private void initializeButtons() { - addButton("Vorwärts", 1); // Bewegung nach vorne - addButton("Rückwärts", -1); // Bewegung nach hinten + addTradeMenuButton(); // Bewegung nach vorne + addEndTurnButton(); // Bewegung nach hinten addDiceRollButton(); // Würfel-Button + } /** @@ -75,12 +107,13 @@ public class Toolbar { * @param label Der Text des Buttons * @param step Schrittweite (+1 für vorwärts, -1 für rückwärts) */ - private void addButton(String label, int step) { + + /*private void addButton(String label, int step) { Button button = new Button(label); button.setPreferredSize(new Vector3f(150, 50, 0)); // Größe der Buttons button.addClickCommands(source -> moveCube(step)); toolbarContainer.addChild(button); - } + }*/ /** * Fügt den Würfel-Button hinzu, der die Figur entsprechend der gewürfelten Zahl bewegt. @@ -92,6 +125,27 @@ public class Toolbar { toolbarContainer.addChild(diceButton); } + private void addTradeMenuButton() { + Button diceButton = new Button("Handeln"); + diceButton.setPreferredSize(new Vector3f(150, 50, 0)); // Größe des Buttons + diceButton.addClickCommands(source -> rollDice()); + toolbarContainer.addChild(diceButton); + } + + private void addEndTurnButton() { + Button diceButton = new Button("Grundstücke"); + diceButton.setPreferredSize(new Vector3f(150, 50, 0)); // Größe des Buttons + diceButton.addClickCommands(source -> rollDice()); + toolbarContainer.addChild(diceButton); + } + + private void addPropertyMenuButton() { + Button diceButton = new Button("Zug beenden"); + diceButton.setPreferredSize(new Vector3f(150, 50, 0)); // Größe des Buttons + diceButton.addClickCommands(source -> rollDice()); + toolbarContainer.addChild(diceButton); + } + /** * Simuliert einen Würfelwurf und bewegt die Figur entsprechend. */