Merge remote-tracking branch 'origin/gui' into gui

This commit is contained in:
Yvonne Schmidt 2024-11-20 03:24:46 +01:00
commit dafe1dab2a
6 changed files with 176 additions and 96 deletions

View File

@ -9,10 +9,8 @@ import com.jme3.font.BitmapText;
import com.jme3.input.KeyInput; import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener; import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger; import com.jme3.input.controls.KeyTrigger;
import com.jme3.system.AppSettings; import com.jme3.system.AppSettings;
import com.simsilica.lemur.GuiGlobals; import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.style.BaseStyles; import com.simsilica.lemur.style.BaseStyles;
import pp.dialog.DialogBuilder; import pp.dialog.DialogBuilder;
@ -28,6 +26,7 @@ import pp.monopoly.notification.InfoTextEvent;
import pp.monopoly.server.MonopolyServer; import pp.monopoly.server.MonopolyServer;
public class MonopolyApp extends SimpleApplication implements MonopolyClient, GameEventListener { public class MonopolyApp extends SimpleApplication implements MonopolyClient, GameEventListener {
private BitmapText topText; private BitmapText topText;
private final ServerConnection serverConnection; private final ServerConnection serverConnection;
private final ClientGameLogic logic; private final ClientGameLogic logic;
@ -41,16 +40,16 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
private boolean isSettingsMenuOpen = false; private boolean isSettingsMenuOpen = false;
private boolean inputBlocked = false; private boolean inputBlocked = false;
private MonopolyServer monopolyServer; private MonopolyServer monopolyServer;
private NetworkSupport networkSupport;
/** /**
* Path to the styles script for GUI elements. * 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. * 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) { public static void main(String[] args) {
new MonopolyApp().start(); new MonopolyApp().start();
@ -59,7 +58,8 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
public MonopolyApp() { public MonopolyApp() {
this.draw = new Draw(assetManager); this.draw = new Draw(assetManager);
config = new MonopolyAppConfig(); config = new MonopolyAppConfig();
serverConnection = new NetworkSupport(this); networkSupport = new NetworkSupport(this); // Initialize NetworkSupport
serverConnection = networkSupport;
logic = new ClientGameLogic(serverConnection); logic = new ClientGameLogic(serverConnection);
logic.addListener(this); logic.addListener(this);
setShowSettings(config.getShowSettings()); setShowSettings(config.getShowSettings());
@ -76,6 +76,10 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
return logic; return logic;
} }
public NetworkSupport getNetworkSupport() {
return networkSupport;
}
private AppSettings makeSettings() { private AppSettings makeSettings() {
final AppSettings settings = new AppSettings(true); final AppSettings settings = new AppSettings(true);
settings.setTitle("Monopoly Game"); settings.setTitle("Monopoly Game");
@ -88,8 +92,8 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
public void simpleInitApp() { public void simpleInitApp() {
GuiGlobals.initialize(this); GuiGlobals.initialize(this);
BaseStyles.loadStyleResources(STYLES_SCRIPT); BaseStyles.loadStyleResources(STYLES_SCRIPT);
GuiGlobals.getInstance().getStyles().setDefaultStyle("pp"); //NON-NLS GuiGlobals.getInstance().getStyles().setDefaultStyle("pp"); // NON-NLS
final BitmapFont normalFont = assetManager.loadFont(FONT); //NON-NLS final BitmapFont normalFont = assetManager.loadFont(FONT); // NON-NLS
setupInput(); setupInput();
setupGui(); setupGui();
@ -130,8 +134,6 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
} }
} }
private void blockInputs() { private void blockInputs() {
if (!inputBlocked) { if (!inputBlocked) {
System.out.println("Blockiere Eingaben..."); System.out.println("Blockiere Eingaben...");
@ -218,9 +220,9 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
public void startServer() { public void startServer() {
new Thread(() -> { new Thread(() -> {
try { try {
monopolyServer = new MonopolyServer(); // Erstelle Serverinstanz MonopolyServer.main(new String[0]); // Startet den MonopolyServer
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); errorDialog("Fehler: Server konnte nicht gestartet werden.");
} }
}).start(); }).start();
} }

View File

@ -18,7 +18,7 @@ import pp.monopoly.message.server.ServerMessage;
* Manages the network connection for the Monopoly application. * Manages the network connection for the Monopoly application.
* Handles connecting to and disconnecting from the server, and sending messages. * Handles connecting to and disconnecting from the server, and sending messages.
*/ */
class NetworkSupport implements MessageListener<Client>, ClientStateListener, ServerConnection { public class NetworkSupport implements MessageListener<Client>, ClientStateListener, ServerConnection {
private static final Logger LOGGER = System.getLogger(NetworkSupport.class.getName()); private static final Logger LOGGER = System.getLogger(NetworkSupport.class.getName());
private final MonopolyApp app; private final MonopolyApp app;
private Client client; private Client client;
@ -141,4 +141,40 @@ class NetworkSupport implements MessageListener<Client>, ClientStateListener, Se
client.send(message); 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.");
}
}
} }

View File

@ -16,13 +16,16 @@ import com.simsilica.lemur.style.ElementId;
import pp.monopoly.client.MonopolyApp; import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.StartMenu; import pp.monopoly.client.StartMenu;
/**
* CreateGameMenu class represents the menu for creating a new game.
*/
public class CreateGameMenu { public class CreateGameMenu {
private final MonopolyApp app; private final MonopolyApp app;
private final Container menuContainer; private final Container menuContainer;
private Geometry background; private Geometry background;
private TextField serverAddressField; private Label serverStatusLabel;
private TextField portField;
public CreateGameMenu(MonopolyApp app) { public CreateGameMenu(MonopolyApp app) {
this.app = app; this.app = app;
@ -46,12 +49,12 @@ public class CreateGameMenu {
inputContainer.setLocalTranslation(20, 0, 0); // Abstand vom Rand inputContainer.setLocalTranslation(20, 0, 0); // Abstand vom Rand
inputContainer.addChild(new Label("Server-Adresse:")); inputContainer.addChild(new Label("Server-Adresse:"));
serverAddressField = inputContainer.addChild(new TextField("localhost")); TextField playerNameField = inputContainer.addChild(new TextField("localhost"));
serverAddressField.setPreferredWidth(400); // Breite des Textfelds playerNameField.setPreferredWidth(400); // Breite des Textfelds
inputContainer.addChild(new Label("Port:")); inputContainer.addChild(new Label("Port:"));
portField = inputContainer.addChild(new TextField("42069")); TextField serverAddressField = inputContainer.addChild(new TextField("42069"));
portField.setPreferredWidth(400); // Breite des Textfelds serverAddressField.setPreferredWidth(400); // Breite des Textfelds
// Button-Container // Button-Container
Container buttonContainer = menuContainer.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y))); Container buttonContainer = menuContainer.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y)));
@ -66,15 +69,29 @@ public class CreateGameMenu {
// "Selber hosten"-Button // "Selber hosten"-Button
Button hostButton = buttonContainer.addChild(new Button("Selber hosten")); Button hostButton = buttonContainer.addChild(new Button("Selber hosten"));
hostButton.setPreferredSize(new Vector3f(120, 40, 0)); 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")); Button joinButton = buttonContainer.addChild(new Button("Beitreten"));
joinButton.setPreferredSize(new Vector3f(120, 40, 0)); 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 // Serverstatus-Label
Label serverStatusLabel = menuContainer.addChild(new Label("Serverstatus: Noch nicht gestartet")); serverStatusLabel = menuContainer.addChild(new Label("Serverstatus: Noch nicht gestartet"));
serverStatusLabel.setFontSize(24); serverStatusLabel.setFontSize(24);
// Zentrierung des Containers // Zentrierung des Containers
@ -119,38 +136,4 @@ public class CreateGameMenu {
app.getGuiNode().detachChild(background); // Entfernt das Hintergrundbild app.getGuiNode().detachChild(background); // Entfernt das Hintergrundbild
StartMenu.createStartMenu(app); 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);
//}
} }

View File

@ -3,20 +3,22 @@ package pp.monopoly.client.gui;
import java.util.Random; import java.util.Random;
import com.jme3.font.BitmapText; import com.jme3.font.BitmapText;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry; import com.jme3.scene.Geometry;
import com.simsilica.lemur.Axis; import com.simsilica.lemur.*;
import com.simsilica.lemur.Button; import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.component.SpringGridLayout; import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp; import pp.monopoly.client.MonopolyApp;
/** /**
* Toolbar Klasse, die am unteren Rand der Szene angezeigt wird. * Toolbar Klasse, die am unteren Rand der Szene angezeigt wird.
* Die Buttons bewegen den Würfel auf dem Spielfeld. * Die Buttons bewegen den Würfel auf dem Spielfeld.
*/ */
public class Toolbar { public class Toolbar extends Dialog {
private final MonopolyApp app; private final MonopolyApp app;
private final Container toolbarContainer; private final Container toolbarContainer;
@ -35,6 +37,7 @@ public class Toolbar {
* @param cube Der Würfel, der bewegt werden soll * @param cube Der Würfel, der bewegt werden soll
*/ */
public Toolbar(MonopolyApp app, Geometry cube) { public Toolbar(MonopolyApp app, Geometry cube) {
super(app.getDialogManager());
this.app = app; this.app = app;
this.cube = cube; this.cube = cube;
@ -44,13 +47,41 @@ public class Toolbar {
// Setze die Position am unteren Rand und die Breite // Setze die Position am unteren Rand und die Breite
toolbarContainer.setLocalTranslation( toolbarContainer.setLocalTranslation(
0, // Links bündig 0, // Links bündig
100, // Höhe über dem unteren Rand 200, // Höhe über dem unteren Rand
0 // Z-Ebene 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 // 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 // Füge die Toolbar zur GUI hinzu
app.getGuiNode().attachChild(toolbarContainer); app.getGuiNode().attachChild(toolbarContainer);
@ -64,9 +95,10 @@ public class Toolbar {
* Initialisiert die Buttons in der Toolbar. * Initialisiert die Buttons in der Toolbar.
*/ */
private void initializeButtons() { private void initializeButtons() {
addButton("Vorwärts", 1); // Bewegung nach vorne addTradeMenuButton(); // Bewegung nach vorne
addButton("Rückwärts", -1); // Bewegung nach hinten addEndTurnButton(); // Bewegung nach hinten
addDiceRollButton(); // Würfel-Button addDiceRollButton(); // Würfel-Button
} }
/** /**
@ -75,12 +107,13 @@ public class Toolbar {
* @param label Der Text des Buttons * @param label Der Text des Buttons
* @param step Schrittweite (+1 für vorwärts, -1 für rückwärts) * @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 button = new Button(label);
button.setPreferredSize(new Vector3f(150, 50, 0)); // Größe der Buttons button.setPreferredSize(new Vector3f(150, 50, 0)); // Größe der Buttons
button.addClickCommands(source -> moveCube(step)); button.addClickCommands(source -> moveCube(step));
toolbarContainer.addChild(button); toolbarContainer.addChild(button);
} }*/
/** /**
* Fügt den Würfel-Button hinzu, der die Figur entsprechend der gewürfelten Zahl bewegt. * 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); 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. * Simuliert einen Würfelwurf und bewegt die Figur entsprechend.
*/ */

View File

@ -1,7 +1,17 @@
package pp.monopoly.game.server; package pp.monopoly.game.server;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import pp.monopoly.MonopolyConfig; 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.GameStart; import pp.monopoly.message.server.GameStart;
import pp.monopoly.message.server.ServerMessage; import pp.monopoly.message.server.ServerMessage;
import pp.monopoly.message.server.TradeReply; import pp.monopoly.message.server.TradeReply;
@ -10,13 +20,6 @@ import pp.monopoly.message.server.ViewAssetsResponse;
import pp.monopoly.model.fields.BoardManager; import pp.monopoly.model.fields.BoardManager;
import pp.monopoly.model.fields.PropertyField; 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. * Controls the server-side game logic for Monopoly.
* Manages game states, player interactions, and message handling. * Manages game states, player interactions, and message handling.
@ -27,7 +30,7 @@ public class ServerGameLogic implements ClientInterpreter {
private final MonopolyConfig config; private final MonopolyConfig config;
private final PlayerHandler playerHandler = new PlayerHandler(this); private final PlayerHandler playerHandler = new PlayerHandler(this);
private final ServerSender serverSender; private final ServerSender serverSender;
private ServerState state = ServerState.CREATEGAME; private ServerState state = ServerState.LOBBY;
private static final int MAX_PLAYERS = 6; private static final int MAX_PLAYERS = 6;
private BoardManager boardManager = new BoardManager(); private BoardManager boardManager = new BoardManager();

View File

@ -7,21 +7,6 @@
package pp.monopoly.server; 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.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
@ -31,6 +16,22 @@ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.LogManager; 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 * Server implementing the visitor pattern as MessageReceiver for ClientMessages
*/ */
@ -119,8 +120,9 @@ public class MonopolyServer implements MessageListener<HostedConnection>, Connec
@Override @Override
public void connectionAdded(Server server, HostedConnection hostedConnection) { 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()); logic.addPlayer(hostedConnection.getId());
System.out.println("Spieler verbunden: ID = " + hostedConnection.getId());
} }
@Override @Override