mirror of
				https://athene2.informatik.unibw-muenchen.de/progproj/gruppen-ht24/Gruppe-02.git
				synced 2025-11-04 13:56:22 +01:00 
			
		
		
		
	Merge branch 'logic' of https://athene2.informatik.unibw-muenchen.de/progproj/gruppen-ht24/Gruppe-02 into logic
This commit is contained in:
		@@ -1,14 +1,9 @@
 | 
				
			|||||||
// Styling of Lemur components
 | 
					// Styling of Lemur components
 | 
				
			||||||
// For documentation, see
 | 
					// For documentation, see:
 | 
				
			||||||
// https://github.com/jMonkeyEngine-Contributions/Lemur/wiki/Styling
 | 
					// https://github.com/jMonkeyEngine-Contributions/Lemur/wiki/Styling
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.simsilica.lemur.Button
 | 
					import com.simsilica.lemur.*
 | 
				
			||||||
import com.simsilica.lemur.Button.ButtonAction
 | 
					 | 
				
			||||||
import com.simsilica.lemur.Command
 | 
					 | 
				
			||||||
import com.simsilica.lemur.HAlignment
 | 
					 | 
				
			||||||
import com.simsilica.lemur.Insets3f
 | 
					 | 
				
			||||||
import com.simsilica.lemur.component.QuadBackgroundComponent
 | 
					import com.simsilica.lemur.component.QuadBackgroundComponent
 | 
				
			||||||
import com.simsilica.lemur.component.TbtQuadBackgroundComponent
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def bgColor = color(1, 1, 1, 1)
 | 
					def bgColor = color(1, 1, 1, 1)
 | 
				
			||||||
def buttonEnabledColor = color(0.8, 0.9, 1, 1)
 | 
					def buttonEnabledColor = color(0.8, 0.9, 1, 1)
 | 
				
			||||||
@@ -16,8 +11,10 @@ def buttonDisabledColor = color(0.8, 0.9, 1, 0.2)
 | 
				
			|||||||
//def buttonBgColor = color(0, 0.75, 0.75, 1)
 | 
					//def buttonBgColor = color(0, 0.75, 0.75, 1)
 | 
				
			||||||
def sliderColor = color(0.6, 0.8, 0.8, 1)
 | 
					def sliderColor = color(0.6, 0.8, 0.8, 1)
 | 
				
			||||||
def sliderBgColor = color(0.5, 0.75, 0.75, 1)
 | 
					def sliderBgColor = color(0.5, 0.75, 0.75, 1)
 | 
				
			||||||
def gradientColor = color(0.5, 0.75, 0.85, 0.5)
 | 
					def gradientColor = color(1, 1, 1, 1)
 | 
				
			||||||
def tabbuttonEnabledColor = color(0.4, 0.45, 0.5, 1)
 | 
					def tabbuttonEnabledColor = color(0.4, 0.45, 0.5, 1)
 | 
				
			||||||
 | 
					def playButtonBorderColor = color(1, 0.6, 0, 1) // For "Spielen" button
 | 
				
			||||||
 | 
					def blackColor = color(0, 0, 0, 1) // Define black color for border
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def playButtonBorderColor = color(1, 0.6, 0, 1) // Orange border for "Spielen" button
 | 
					def playButtonBorderColor = color(1, 0.6, 0, 1) // Orange border for "Spielen" button
 | 
				
			||||||
def playButtonTextColor = color(0, 0, 0, 1) // Black text color for "Spielen" button
 | 
					def playButtonTextColor = color(0, 0, 0, 1) // Black text color for "Spielen" button
 | 
				
			||||||
@@ -27,39 +24,35 @@ def borderColor = color(0, 0, 0, 1) // Black border for "Spiel beenden" and "Ein
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def gradient = TbtQuadBackgroundComponent.create(
 | 
					def gradient = TbtQuadBackgroundComponent.create(
 | 
				
			||||||
        texture(name: "/com/simsilica/lemur/icons/bordered-gradient.png",
 | 
					        texture(name: "/com/simsilica/lemur/icons/bordered-gradient.png", generateMips: false),
 | 
				
			||||||
                generateMips: false),
 | 
					       1, 1, 1, 126, 126, 1f, false)
 | 
				
			||||||
        1, 1, 1, 126, 126,
 | 
					 | 
				
			||||||
        1f, false)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def doubleGradient = new QuadBackgroundComponent(gradientColor)
 | 
					def doubleGradient = new QuadBackgroundComponent(gradientColor)
 | 
				
			||||||
doubleGradient.texture = texture(name: "/com/simsilica/lemur/icons/double-gradient-128.png",
 | 
					doubleGradient.texture = texture(name: "/com/simsilica/lemur/icons/double-gradient-128.png", generateMips: false)
 | 
				
			||||||
                                 generateMips: false)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Hauptstil für die Schriftart
 | 
				
			||||||
selector("pp") {
 | 
					selector("pp") {
 | 
				
			||||||
    font = font("Interface/Fonts/Metropolis/Metropolis-Regular-32.fnt")
 | 
					    font = font("Interface/Fonts/Metropolis/Metropolis-Regular-32.fnt")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
selector("label", "pp") {
 | 
					// Titel für "Einstellungen"
 | 
				
			||||||
    insets = new Insets3f(2, 2, 2, 2)
 | 
					selector("settings-title", "pp") {
 | 
				
			||||||
    color = buttonEnabledColor
 | 
					    color = color(1, 1, 1, 1)
 | 
				
			||||||
}
 | 
					    fontSize = 48
 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("header", "pp") {
 | 
					 | 
				
			||||||
    font = font("Interface/Fonts/Metropolis/Metropolis-Bold-42.fnt")
 | 
					 | 
				
			||||||
    insets = new Insets3f(2, 2, 2, 2)
 | 
					 | 
				
			||||||
    color = color(1, 0.5, 0, 1)
 | 
					 | 
				
			||||||
    textHAlignment = HAlignment.Center
 | 
					    textHAlignment = HAlignment.Center
 | 
				
			||||||
 | 
					    insets = new Insets3f(5, 5, 5, 5)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Container Stil
 | 
				
			||||||
selector("container", "pp") {
 | 
					selector("container", "pp") {
 | 
				
			||||||
    background = gradient.clone()
 | 
					    background = gradient.clone()
 | 
				
			||||||
    background.setColor(bgColor)
 | 
					    background.setColor(bgColor)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Slider Stil
 | 
				
			||||||
selector("slider", "pp") {
 | 
					selector("slider", "pp") {
 | 
				
			||||||
    background = gradient.clone()
 | 
					    insets = new Insets3f(5, 10, 5, 10) // Abstand
 | 
				
			||||||
    background.setColor(bgColor)
 | 
					    background = new QuadBackgroundComponent(sliderBgColor)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
selector("play-button", "pp") {
 | 
					selector("play-button", "pp") {
 | 
				
			||||||
@@ -98,30 +91,6 @@ def enabledCommand = new Command<Button>() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def repeatCommand = new Command<Button>() {
 | 
					 | 
				
			||||||
    private long startTime
 | 
					 | 
				
			||||||
    private long lastClick
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void execute(Button source) {
 | 
					 | 
				
			||||||
        // Only do the repeating click while the mouse is
 | 
					 | 
				
			||||||
        // over the button (and pressed of course)
 | 
					 | 
				
			||||||
        if (source.isPressed() && source.isHighlightOn()) {
 | 
					 | 
				
			||||||
            long elapsedTime = System.currentTimeMillis() - startTime
 | 
					 | 
				
			||||||
            // After half a second pause, click 8 times a second
 | 
					 | 
				
			||||||
            if (elapsedTime > 500 && elapsedTime > lastClick + 125) {
 | 
					 | 
				
			||||||
                source.click()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                // Try to quantize the last click time to prevent drift
 | 
					 | 
				
			||||||
                lastClick = ((elapsedTime - 500) / 125) * 125 + 500
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
            startTime = System.currentTimeMillis()
 | 
					 | 
				
			||||||
            lastClick = 0
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def stdButtonCommands = [
 | 
					def stdButtonCommands = [
 | 
				
			||||||
        (ButtonAction.Down)    : [pressedCommand],
 | 
					        (ButtonAction.Down)    : [pressedCommand],
 | 
				
			||||||
        (ButtonAction.Up)      : [pressedCommand],
 | 
					        (ButtonAction.Up)      : [pressedCommand],
 | 
				
			||||||
@@ -129,98 +98,9 @@ def stdButtonCommands = [
 | 
				
			|||||||
        (ButtonAction.Disabled): [enabledCommand]
 | 
					        (ButtonAction.Disabled): [enabledCommand]
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def sliderButtonCommands = [
 | 
					 | 
				
			||||||
        (ButtonAction.Hover): [repeatCommand]
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("title", "pp") {
 | 
					 | 
				
			||||||
    color = color(0.8, 0.9, 1, 0.85f)
 | 
					 | 
				
			||||||
    highlightColor = color(1, 0.8, 1, 0.85f)
 | 
					 | 
				
			||||||
    shadowColor = color(0, 0, 0, 0.75f)
 | 
					 | 
				
			||||||
    shadowOffset = vec3(2, -2, -1)
 | 
					 | 
				
			||||||
    background = new QuadBackgroundComponent(color(0.5, 0.75, 0.85, 1))
 | 
					 | 
				
			||||||
    background.texture = texture(name: "/com/simsilica/lemur/icons/double-gradient-128.png",
 | 
					 | 
				
			||||||
                                 generateMips: false)
 | 
					 | 
				
			||||||
    insets = new Insets3f(2, 2, 2, 2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    buttonCommands = stdButtonCommands
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("button", "pp") {
 | 
					selector("button", "pp") {
 | 
				
			||||||
    background = gradient.clone()
 | 
					    background = gradient.clone()
 | 
				
			||||||
    color = buttonEnabledColor
 | 
					    color = buttonEnabledColor
 | 
				
			||||||
    background.setColor(buttonBgColor)
 | 
					 | 
				
			||||||
    insets = new Insets3f(2, 2, 2, 2)
 | 
					    insets = new Insets3f(2, 2, 2, 2)
 | 
				
			||||||
 | 
					 | 
				
			||||||
    buttonCommands = stdButtonCommands
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("slider", "pp") {
 | 
					 | 
				
			||||||
    insets = new Insets3f(1, 3, 1, 2)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("slider", "button", "pp") {
 | 
					 | 
				
			||||||
    background = doubleGradient.clone()
 | 
					 | 
				
			||||||
    //background.setColor(sliderBgColor)
 | 
					 | 
				
			||||||
    insets = new Insets3f(0, 0, 0, 0)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("slider.thumb.button", "pp") {
 | 
					 | 
				
			||||||
    text = "[]"
 | 
					 | 
				
			||||||
    color = sliderColor
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("slider.left.button", "pp") {
 | 
					 | 
				
			||||||
    text = "-"
 | 
					 | 
				
			||||||
    background = doubleGradient.clone()
 | 
					 | 
				
			||||||
    //background.setColor(sliderBgColor)
 | 
					 | 
				
			||||||
    background.setMargin(5, 0)
 | 
					 | 
				
			||||||
    color = sliderColor
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    buttonCommands = sliderButtonCommands
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("slider.right.button", "pp") {
 | 
					 | 
				
			||||||
    text = "+"
 | 
					 | 
				
			||||||
    background = doubleGradient.clone()
 | 
					 | 
				
			||||||
    //background.setColor(sliderBgColor)
 | 
					 | 
				
			||||||
    background.setMargin(4, 0)
 | 
					 | 
				
			||||||
    color = sliderColor
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    buttonCommands = sliderButtonCommands
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("slider.up.button", "pp") {
 | 
					 | 
				
			||||||
    buttonCommands = sliderButtonCommands
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("slider.down.button", "pp") {
 | 
					 | 
				
			||||||
    buttonCommands = sliderButtonCommands
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("checkbox", "pp") {
 | 
					 | 
				
			||||||
    color = buttonEnabledColor
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("rollup", "pp") {
 | 
					 | 
				
			||||||
    background = gradient.clone()
 | 
					 | 
				
			||||||
    background.setColor(bgColor)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("tabbedPanel", "pp") {
 | 
					 | 
				
			||||||
    activationColor = buttonEnabledColor
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("tabbedPanel.container", "pp") {
 | 
					 | 
				
			||||||
    background = null
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
selector("tab.button", "pp") {
 | 
					 | 
				
			||||||
    background = gradient.clone()
 | 
					 | 
				
			||||||
    background.setColor(bgColor)
 | 
					 | 
				
			||||||
    color = tabbuttonEnabledColor
 | 
					 | 
				
			||||||
    insets = new Insets3f(4, 2, 0, 2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    buttonCommands = stdButtonCommands
 | 
					    buttonCommands = stdButtonCommands
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,35 +1,28 @@
 | 
				
			|||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
// Programming project code
 | 
					 | 
				
			||||||
// UniBw M, 2022, 2023, 2024
 | 
					 | 
				
			||||||
// www.unibw.de/inf2
 | 
					 | 
				
			||||||
// (c) Mark Minas (mark.minas@unibw.de)
 | 
					 | 
				
			||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package pp.monopoly.client;
 | 
					package pp.monopoly.client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.jme3.app.Application;
 | 
					 | 
				
			||||||
import com.jme3.app.state.AbstractAppState;
 | 
					 | 
				
			||||||
import com.jme3.app.state.AppStateManager;
 | 
					 | 
				
			||||||
import com.jme3.asset.AssetLoadException;
 | 
					 | 
				
			||||||
import com.jme3.asset.AssetNotFoundException;
 | 
					 | 
				
			||||||
import com.jme3.audio.AudioData;
 | 
					 | 
				
			||||||
import com.jme3.audio.AudioNode;
 | 
					 | 
				
			||||||
import pp.monopoly.notification.GameEventListener;
 | 
					 | 
				
			||||||
import pp.monopoly.notification.SoundEvent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.lang.System.Logger;
 | 
					import java.lang.System.Logger;
 | 
				
			||||||
import java.lang.System.Logger.Level;
 | 
					import java.lang.System.Logger.Level;
 | 
				
			||||||
import java.util.prefs.Preferences;
 | 
					import java.util.prefs.Preferences;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.jme3.app.Application;
 | 
				
			||||||
 | 
					import com.jme3.app.state.AbstractAppState;
 | 
				
			||||||
 | 
					import com.jme3.app.state.AppStateManager;
 | 
				
			||||||
 | 
					import com.jme3.audio.AudioData;
 | 
				
			||||||
 | 
					import com.jme3.audio.AudioNode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import pp.monopoly.notification.GameEventListener;
 | 
				
			||||||
 | 
					import pp.monopoly.notification.SoundEvent;
 | 
				
			||||||
import static pp.util.PreferencesUtils.getPreferences;
 | 
					import static pp.util.PreferencesUtils.getPreferences;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * An application state that plays sounds.
 | 
					 * An application state that plays sounds based on game events.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class GameSound extends AbstractAppState implements GameEventListener {
 | 
					public class GameSound extends AbstractAppState implements GameEventListener {
 | 
				
			||||||
    private static final Logger LOGGER = System.getLogger(GameSound.class.getName());
 | 
					    private static final Logger LOGGER = System.getLogger(GameSound.class.getName());
 | 
				
			||||||
    private static final Preferences PREFERENCES = getPreferences(GameSound.class);
 | 
					    private static final Preferences PREFERENCES = getPreferences(GameSound.class);
 | 
				
			||||||
    private static final String ENABLED_PREF = "enabled"; //NON-NLS
 | 
					    private static final String ENABLED_PREF = "enabled";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Application app; // Feld zum Speichern der Application-Instanz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Checks if sound is enabled in the preferences.
 | 
					     * Checks if sound is enabled in the preferences.
 | 
				
			||||||
@@ -49,7 +42,6 @@ public class GameSound extends AbstractAppState implements GameEventListener {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Sets the enabled state of this AppState.
 | 
					     * Sets the enabled state of this AppState.
 | 
				
			||||||
     * Overrides {@link com.jme3.app.state.AbstractAppState#setEnabled(boolean)}
 | 
					 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param enabled {@code true} to enable the AppState, {@code false} to disable it.
 | 
					     * @param enabled {@code true} to enable the AppState, {@code false} to disable it.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@@ -57,46 +49,52 @@ public class GameSound extends AbstractAppState implements GameEventListener {
 | 
				
			|||||||
    public void setEnabled(boolean enabled) {
 | 
					    public void setEnabled(boolean enabled) {
 | 
				
			||||||
        if (isEnabled() == enabled) return;
 | 
					        if (isEnabled() == enabled) return;
 | 
				
			||||||
        super.setEnabled(enabled);
 | 
					        super.setEnabled(enabled);
 | 
				
			||||||
        LOGGER.log(Level.INFO, "Sound enabled: {0}", enabled); //NON-NLS
 | 
					        LOGGER.log(Level.INFO, "Sound enabled: {0}", enabled);
 | 
				
			||||||
        PREFERENCES.putBoolean(ENABLED_PREF, enabled);
 | 
					        PREFERENCES.putBoolean(ENABLED_PREF, enabled);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Initializes the sound effects for the game.
 | 
					     * Initializes the sound effects for the game and stores the application reference.
 | 
				
			||||||
     * Overrides {@link AbstractAppState#initialize(AppStateManager, Application)}
 | 
					 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param stateManager The state manager
 | 
					     * @param stateManager The state manager
 | 
				
			||||||
     * @param app          The application
 | 
					     * @param app          The application instance
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void initialize(AppStateManager stateManager, Application app) {
 | 
					    public void initialize(AppStateManager stateManager, Application app) {
 | 
				
			||||||
        super.initialize(stateManager, app);
 | 
					        super.initialize(stateManager, app);
 | 
				
			||||||
 | 
					        this.app = app; // Speichert die Application-Instanz
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Loads a sound from the specified file.
 | 
					     * Loads a sound from the specified file.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param app  The application
 | 
					 | 
				
			||||||
     * @param name The name of the sound file.
 | 
					     * @param name The name of the sound file.
 | 
				
			||||||
     * @return The loaded AudioNode.
 | 
					     * @return The loaded AudioNode.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private AudioNode loadSound(Application app, String name) {
 | 
					    private AudioNode loadSound(String name) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            final AudioNode sound = new AudioNode(app.getAssetManager(), name, AudioData.DataType.Buffer);
 | 
					            AudioNode sound = new AudioNode(app.getAssetManager(), name, AudioData.DataType.Buffer);
 | 
				
			||||||
            sound.setLooping(false);
 | 
					            sound.setLooping(false);
 | 
				
			||||||
            sound.setPositional(false);
 | 
					            sound.setPositional(false);
 | 
				
			||||||
            return sound;
 | 
					            return sound;
 | 
				
			||||||
        }
 | 
					        } catch (Exception ex) {
 | 
				
			||||||
        catch (AssetLoadException | AssetNotFoundException ex) {
 | 
					 | 
				
			||||||
            LOGGER.log(Level.ERROR, ex.getMessage(), ex);
 | 
					            LOGGER.log(Level.ERROR, ex.getMessage(), ex);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Handles sound-related game events to play specific sounds.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param event The sound event received.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void receivedEvent(SoundEvent event) {
 | 
					    public void receivedEvent(SoundEvent event) {
 | 
				
			||||||
        switch (event.sound()) {
 | 
					        if (isEnabled()) {
 | 
				
			||||||
 | 
					            AudioNode sound = loadSound(event.getSoundFileName());
 | 
				
			||||||
 | 
					            if (sound != null) {
 | 
				
			||||||
 | 
					                sound.play();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}//heloo
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,17 +7,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package pp.monopoly.client;
 | 
					package pp.monopoly.client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.simsilica.lemur.Button;
 | 
					 | 
				
			||||||
import com.simsilica.lemur.Checkbox;
 | 
					 | 
				
			||||||
import com.simsilica.lemur.Label;
 | 
					 | 
				
			||||||
import com.simsilica.lemur.style.ElementId;
 | 
					 | 
				
			||||||
import pp.dialog.Dialog;
 | 
					 | 
				
			||||||
import pp.dialog.StateCheckboxModel;
 | 
					 | 
				
			||||||
import pp.dialog.TextInputDialog;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.prefs.Preferences;
 | 
					import java.util.prefs.Preferences;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static pp.monopoly.Resources.lookup;
 | 
					import pp.dialog.Dialog;
 | 
				
			||||||
import static pp.util.PreferencesUtils.getPreferences;
 | 
					import static pp.util.PreferencesUtils.getPreferences;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,423 +1,197 @@
 | 
				
			|||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
// Programming project code
 | 
					 | 
				
			||||||
// UniBw M, 2022, 2023, 2024
 | 
					 | 
				
			||||||
// www.unibw.de/inf2
 | 
					 | 
				
			||||||
// (c) Mark Minas (mark.minas@unibw.de)
 | 
					 | 
				
			||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package pp.monopoly.client;
 | 
					package pp.monopoly.client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.jme3.app.DebugKeysAppState;
 | 
					import java.util.concurrent.ExecutorService;
 | 
				
			||||||
 | 
					import java.util.concurrent.Executors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.jme3.app.SimpleApplication;
 | 
					import com.jme3.app.SimpleApplication;
 | 
				
			||||||
import com.jme3.app.StatsAppState;
 | 
					 | 
				
			||||||
import com.jme3.font.BitmapFont;
 | 
					import com.jme3.font.BitmapFont;
 | 
				
			||||||
import com.jme3.font.BitmapText;
 | 
					import com.jme3.font.BitmapText;
 | 
				
			||||||
import com.jme3.input.KeyInput;
 | 
					import com.jme3.input.KeyInput;
 | 
				
			||||||
import com.jme3.input.MouseInput;
 | 
					 | 
				
			||||||
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.input.controls.MouseButtonTrigger;
 | 
					import com.jme3.material.Material;
 | 
				
			||||||
 | 
					import com.jme3.math.Vector3f;
 | 
				
			||||||
 | 
					import com.jme3.scene.Geometry;
 | 
				
			||||||
 | 
					import com.jme3.scene.shape.Box;
 | 
				
			||||||
import com.jme3.system.AppSettings;
 | 
					import com.jme3.system.AppSettings;
 | 
				
			||||||
 | 
					import com.jme3.texture.Texture;
 | 
				
			||||||
import com.simsilica.lemur.GuiGlobals;
 | 
					import com.simsilica.lemur.GuiGlobals;
 | 
				
			||||||
import com.simsilica.lemur.style.BaseStyles;
 | 
					import com.simsilica.lemur.style.BaseStyles;
 | 
				
			||||||
import pp.monopoly.game.client.MonopolyClient;
 | 
					
 | 
				
			||||||
import pp.monopoly.game.client.ClientGameLogic;
 | 
					 | 
				
			||||||
import pp.monopoly.game.client.ServerConnection;
 | 
					 | 
				
			||||||
import pp.monopoly.notification.ClientStateEvent;
 | 
					 | 
				
			||||||
import pp.monopoly.notification.GameEventListener;
 | 
					 | 
				
			||||||
import pp.monopoly.notification.InfoTextEvent;
 | 
					 | 
				
			||||||
import pp.dialog.DialogBuilder;
 | 
					import pp.dialog.DialogBuilder;
 | 
				
			||||||
import pp.dialog.DialogManager;
 | 
					import pp.dialog.DialogManager;
 | 
				
			||||||
import pp.graphics.Draw;
 | 
					import pp.graphics.Draw;
 | 
				
			||||||
 | 
					import pp.monopoly.client.gui.SettingsMenu;
 | 
				
			||||||
 | 
					import pp.monopoly.game.client.ClientGameLogic;
 | 
				
			||||||
 | 
					import pp.monopoly.game.client.MonopolyClient;
 | 
				
			||||||
 | 
					import pp.monopoly.game.client.ServerConnection;
 | 
				
			||||||
 | 
					import pp.monopoly.notification.GameEventListener;
 | 
				
			||||||
 | 
					import pp.monopoly.notification.InfoTextEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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.ExecutorService;
 | 
					 | 
				
			||||||
import java.util.concurrent.Executors;
 | 
					 | 
				
			||||||
import java.util.logging.LogManager;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static pp.monopoly.Resources.lookup;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * The main class for the Monopoly client application.
 | 
					 | 
				
			||||||
 * It manages the initialization, input setup, GUI setup, and game states for the client.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
public class MonopolyApp extends SimpleApplication implements MonopolyClient, GameEventListener {
 | 
					public class MonopolyApp extends SimpleApplication implements MonopolyClient, GameEventListener {
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Logger for logging messages within the application.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private static final Logger LOGGER = System.getLogger(MonopolyApp.class.getName());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Path to the styles script for GUI elements.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Path to the client configuration file, if one exists.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private static final File CONFIG_FILE = new File("client.properties");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Input mapping name for mouse clicks.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public static final String CLICK = "CLICK";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Input mapping name for the Escape key.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private static final String ESC = "ESC";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Manager for handling dialogs within the application.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private final DialogManager dialogManager = new DialogManager(this);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The server connection instance, used for communicating with the game server.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private final ServerConnection serverConnection;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Instance of the {@link Draw} class for rendering graphics.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private Draw draw;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Text display at the top of the GUI for showing information to the user.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private BitmapText topText;
 | 
					    private BitmapText topText;
 | 
				
			||||||
 | 
					    private final ServerConnection serverConnection;
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Executor service for handling asynchronous tasks within the application.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private ExecutorService executor;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Handler for managing the client's game logic.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private final ClientGameLogic logic;
 | 
					    private final ClientGameLogic logic;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Configuration settings for the Monopoly client application.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private final MonopolyAppConfig config;
 | 
					    private final MonopolyAppConfig config;
 | 
				
			||||||
 | 
					    private final ActionListener escapeListener = (name, isPressed, tpf) -> handleEscape(isPressed);
 | 
				
			||||||
 | 
					    private final DialogManager dialogManager = new DialogManager(this);
 | 
				
			||||||
 | 
					    private final ExecutorService executor = Executors.newCachedThreadPool();
 | 
				
			||||||
 | 
					    private SettingsMenu settingsMenu;
 | 
				
			||||||
 | 
					    private final Draw draw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    private boolean isSettingsMenuOpen = false;
 | 
				
			||||||
     * Listener for handling actions triggered by the Escape key.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private final ActionListener escapeListener = (name, isPressed, tpf) -> escape(isPressed);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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 Monopoly application.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param args Command-line arguments for launching the application.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public static void main(String[] args) {
 | 
					    public static void main(String[] args) {
 | 
				
			||||||
        new MonopolyApp().start();
 | 
					        new MonopolyApp().start();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    public MonopolyApp() {
 | 
				
			||||||
     * Constructs a new {@code MonopolyApp} instance.
 | 
					        this.draw = new Draw(assetManager);
 | 
				
			||||||
     * Initializes the configuration, server connection, and game logic listeners.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private MonopolyApp() {
 | 
					 | 
				
			||||||
        config = new MonopolyAppConfig();
 | 
					        config = new MonopolyAppConfig();
 | 
				
			||||||
        config.readFromIfExists(CONFIG_FILE);
 | 
					        serverConnection = new NetworkSupport(this);
 | 
				
			||||||
        serverConnection = makeServerConnection();
 | 
					 | 
				
			||||||
        logic = new ClientGameLogic(serverConnection);
 | 
					        logic = new ClientGameLogic(serverConnection);
 | 
				
			||||||
        logic.addListener(this);
 | 
					        logic.addListener(this);
 | 
				
			||||||
        setShowSettings(config.getShowSettings());
 | 
					        setShowSettings(config.getShowSettings());
 | 
				
			||||||
        setSettings(makeSettings());
 | 
					        setSettings(makeSettings());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Creates and configures application settings from the client configuration.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return A configured {@link AppSettings} object.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private AppSettings makeSettings() {
 | 
					 | 
				
			||||||
        final AppSettings settings = new AppSettings(true);
 | 
					 | 
				
			||||||
        settings.setTitle(lookup("monopoly.name"));
 | 
					 | 
				
			||||||
        settings.setResolution(config.getResolutionWidth(), config.getResolutionHeight());
 | 
					 | 
				
			||||||
        settings.setFullscreen(config.fullScreen());
 | 
					 | 
				
			||||||
        settings.setUseRetinaFrameBuffer(config.useRetinaFrameBuffer());
 | 
					 | 
				
			||||||
        settings.setGammaCorrection(config.useGammaCorrection());
 | 
					 | 
				
			||||||
        return settings;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Factory method for creating a server connection based on the current
 | 
					 | 
				
			||||||
     * client configuration.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return A {@link ServerConnection} instance, which could be a real or mock server.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private ServerConnection makeServerConnection() {
 | 
					 | 
				
			||||||
        return new NetworkSupport(this);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Returns the dialog manager responsible for managing in-game dialogs.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return The {@link DialogManager} instance.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public DialogManager getDialogManager() {
 | 
					 | 
				
			||||||
        return dialogManager;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Returns the game logic handler for the client.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return The {@link ClientGameLogic} instance.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public ClientGameLogic getGameLogic() {
 | 
					 | 
				
			||||||
        return logic;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Returns the current configuration settings for the Monopoly client.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return The {@link MonopolyClientConfig} instance.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public MonopolyAppConfig getConfig() {
 | 
					    public MonopolyAppConfig getConfig() {
 | 
				
			||||||
        return config;
 | 
					        return config;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Initializes the application.
 | 
					 | 
				
			||||||
     * Sets up input mappings, GUI, game states, and connects to the server.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void simpleInitApp() {
 | 
					    public ClientGameLogic getGameLogic() {
 | 
				
			||||||
        setPauseOnLostFocus(false);
 | 
					        return logic;
 | 
				
			||||||
        draw = new Draw(assetManager);
 | 
					 | 
				
			||||||
        setupInput();
 | 
					 | 
				
			||||||
        setupStates();
 | 
					 | 
				
			||||||
        setupGui();
 | 
					 | 
				
			||||||
        serverConnection.connect();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    private AppSettings makeSettings() {
 | 
				
			||||||
     * Sets up the graphical user interface (GUI) for the application.
 | 
					        final AppSettings settings = new AppSettings(true);
 | 
				
			||||||
     */
 | 
					        settings.setTitle("Monopoly Game");
 | 
				
			||||||
    private void setupGui() {
 | 
					        settings.setResolution(config.getResolutionWidth(), config.getResolutionHeight());
 | 
				
			||||||
 | 
					        settings.setFullscreen(config.fullScreen());
 | 
				
			||||||
 | 
					        return settings;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean isSettingsMenuOpen() {
 | 
				
			||||||
 | 
					        return isSettingsMenuOpen;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setSettingsMenuOpen(boolean isOpen) {
 | 
				
			||||||
 | 
					        this.isSettingsMenuOpen = isOpen;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void simpleInitApp() {
 | 
				
			||||||
        GuiGlobals.initialize(this); 
 | 
					        GuiGlobals.initialize(this); 
 | 
				
			||||||
        BaseStyles.loadStyleResources(STYLES_SCRIPT);
 | 
					        BaseStyles.loadGlassStyle();
 | 
				
			||||||
        GuiGlobals.getInstance().getStyles().setDefaultStyle("pp"); //NON-NLS
 | 
					        GuiGlobals.getInstance().getStyles().setDefaultStyle("glass");
 | 
				
			||||||
        final BitmapFont normalFont = assetManager.loadFont(FONT); //NON-NLS
 | 
					
 | 
				
			||||||
 | 
					        setupInput();
 | 
				
			||||||
 | 
					        setupGui();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Initialisiere das Startmenü
 | 
				
			||||||
 | 
					        StartMenu.createStartMenu(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void setupGui() {
 | 
				
			||||||
 | 
					        BitmapFont normalFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
 | 
				
			||||||
        topText = new BitmapText(normalFont);
 | 
					        topText = new BitmapText(normalFont);
 | 
				
			||||||
        final int height = context.getSettings().getHeight();
 | 
					        topText.setLocalTranslation(10, settings.getHeight() - 10, 0);
 | 
				
			||||||
        topText.setLocalTranslation(10f, height - 10f, 0f);
 | 
					 | 
				
			||||||
        topText.setColor(config.getTopColor());
 | 
					 | 
				
			||||||
        guiNode.attachChild(topText);
 | 
					        guiNode.attachChild(topText);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Configures input mappings and sets up listeners for user interactions.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private void setupInput() {
 | 
					    private void setupInput() {
 | 
				
			||||||
        inputManager.deleteMapping(INPUT_MAPPING_EXIT);
 | 
					        inputManager.deleteMapping(INPUT_MAPPING_EXIT);
 | 
				
			||||||
        inputManager.setCursorVisible(false);
 | 
					        inputManager.setCursorVisible(true);
 | 
				
			||||||
        inputManager.addMapping(ESC, new KeyTrigger(KeyInput.KEY_ESCAPE));
 | 
					        inputManager.addMapping("ESC", new KeyTrigger(KeyInput.KEY_ESCAPE));
 | 
				
			||||||
        inputManager.addMapping(CLICK, new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
 | 
					        inputManager.addListener(escapeListener, "ESC");
 | 
				
			||||||
        inputManager.addListener(escapeListener, ESC);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /**
 | 
					
 | 
				
			||||||
     * Initializes and attaches the necessary application states for the game.
 | 
					    private void handleEscape(boolean isPressed) {
 | 
				
			||||||
     */
 | 
					        if (isPressed) {
 | 
				
			||||||
    private void setupStates() {
 | 
					            if (isSettingsMenuOpen && settingsMenu != null) {
 | 
				
			||||||
        if (config.getShowStatistics()) {
 | 
					                settingsMenu.close();
 | 
				
			||||||
            final BitmapFont normalFont = assetManager.loadFont(FONT); //NON-NLS
 | 
					                setSettingsMenuOpen(false);
 | 
				
			||||||
            final StatsAppState stats = new StatsAppState(guiNode, normalFont);
 | 
					            } else {
 | 
				
			||||||
            stateManager.attach(stats);
 | 
					                settingsMenu = new SettingsMenu(this);
 | 
				
			||||||
 | 
					                settingsMenu.open();
 | 
				
			||||||
 | 
					                setSettingsMenuOpen(true);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        flyCam.setEnabled(false);
 | 
					 | 
				
			||||||
        stateManager.detach(stateManager.getState(StatsAppState.class));
 | 
					 | 
				
			||||||
        stateManager.detach(stateManager.getState(DebugKeysAppState.class));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        attachGameSound();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //TODO add states
 | 
					 | 
				
			||||||
        stateManager.attachAll();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					
 | 
				
			||||||
     * Attaches the game sound state and sets its initial enabled state.
 | 
					    void setInfoText(String text) {
 | 
				
			||||||
     */
 | 
					        topText.setText(text);
 | 
				
			||||||
    private void attachGameSound() {
 | 
					 | 
				
			||||||
        final GameSound gameSound = new GameSound();
 | 
					 | 
				
			||||||
        logic.addListener(gameSound);
 | 
					 | 
				
			||||||
        gameSound.setEnabled(GameSound.enabledInPreferences());
 | 
					 | 
				
			||||||
        stateManager.attach(gameSound);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Updates the application state every frame.
 | 
					 | 
				
			||||||
     * This method is called once per frame during the game loop.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param tpf Time per frame in seconds.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void simpleUpdate(float tpf) {
 | 
					    public void receivedEvent(InfoTextEvent event) {
 | 
				
			||||||
        super.simpleUpdate(tpf);
 | 
					        setInfoText(event.key());
 | 
				
			||||||
        dialogManager.update(tpf);
 | 
					 | 
				
			||||||
        logic.update(tpf);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    @Override
 | 
				
			||||||
     * Handles the Escape key action to either close the top dialog or show the main menu.
 | 
					    public void stop(boolean waitFor) {
 | 
				
			||||||
     *
 | 
					        if (executor != null) executor.shutdownNow();
 | 
				
			||||||
     * @param isPressed Indicates whether the Escape key is pressed.
 | 
					        serverConnection.disconnect();
 | 
				
			||||||
     */
 | 
					        super.stop(waitFor);
 | 
				
			||||||
    private void escape(boolean isPressed) {
 | 
					    }
 | 
				
			||||||
        if (!isPressed) return;
 | 
					
 | 
				
			||||||
        if (dialogManager.showsDialog())
 | 
					    public DialogManager getDialogManager() {
 | 
				
			||||||
            dialogManager.escape();
 | 
					        return dialogManager;
 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            new Menu(this).open();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Returns the {@link Draw} instance used for rendering graphical elements in the game.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return The {@link Draw} instance.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public Draw getDraw() {
 | 
					    public Draw getDraw() {
 | 
				
			||||||
        return draw;
 | 
					        return draw;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Handles a request to close the application.
 | 
					 | 
				
			||||||
     * If the request is initiated by pressing ESC, this parameter is true.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param esc If true, the request is due to the ESC key being pressed.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void requestClose(boolean esc) { /* do nothing */ }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Closes the application, displaying a confirmation dialog if the client is connected to a server.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public void closeApp() {
 | 
					 | 
				
			||||||
        if (serverConnection.isConnected())
 | 
					 | 
				
			||||||
            confirmDialog(lookup("confirm.leaving"), this::close);
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            close();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Closes the application, disconnecting from the server and stopping the application.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private void close() {
 | 
					 | 
				
			||||||
        serverConnection.disconnect();
 | 
					 | 
				
			||||||
        stop();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Updates the informational text displayed in the GUI.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param text The information text to display.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    void setInfoText(String text) {
 | 
					 | 
				
			||||||
        LOGGER.log(Level.DEBUG, "setInfoText {0}", text); //NON-NLS
 | 
					 | 
				
			||||||
        topText.setText(text);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Updates the informational text in the GUI based on the key received in an {@link InfoTextEvent}.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param event The {@link InfoTextEvent} containing the key for the text to display.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void receivedEvent(InfoTextEvent event) {
 | 
					 | 
				
			||||||
        LOGGER.log(Level.DEBUG, "received info text {0}", event.key()); //NON-NLS
 | 
					 | 
				
			||||||
        setInfoText(lookup(event.key()));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Handles client state events to update the game states accordingly.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param event The {@link ClientStateEvent} representing the state change.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void receivedEvent(ClientStateEvent event) {
 | 
					 | 
				
			||||||
        //TODO
 | 
					 | 
				
			||||||
        throw new UnsupportedOperationException("unimplemented method");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Returns the executor service used for handling multithreaded tasks.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return The {@link ExecutorService} instance.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public ExecutorService getExecutor() {
 | 
					    public ExecutorService getExecutor() {
 | 
				
			||||||
        if (executor == null)
 | 
					 | 
				
			||||||
            executor = Executors.newCachedThreadPool();
 | 
					 | 
				
			||||||
        return executor;
 | 
					        return executor;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    public void closeApp() {
 | 
				
			||||||
     * Stops the application, shutting down the executor service and halting execution.
 | 
					        stop();
 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param waitFor If true, waits for the application to stop before returning.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void stop(boolean waitFor) {
 | 
					 | 
				
			||||||
        if (executor != null) executor.shutdownNow();
 | 
					 | 
				
			||||||
        super.stop(waitFor);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    public void errorDialog(String errorMessage) {
 | 
				
			||||||
     * Displays a confirmation dialog with a specified question and action for the "Yes" button.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param question  The question to display in the dialog.
 | 
					 | 
				
			||||||
     * @param yesAction The action to perform if "Yes" is selected.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    void confirmDialog(String question, Runnable yesAction) {
 | 
					 | 
				
			||||||
        DialogBuilder.simple(dialogManager)
 | 
					        DialogBuilder.simple(dialogManager)
 | 
				
			||||||
                     .setTitle(lookup("dialog.question"))
 | 
					                .setTitle("Fehler")
 | 
				
			||||||
                     .setText(question)
 | 
					                .setText(errorMessage)
 | 
				
			||||||
                     .setOkButton(lookup("button.yes"), yesAction)
 | 
					                .setOkButton("OK")
 | 
				
			||||||
                     .setNoButton(lookup("button.no"))
 | 
					                .build()
 | 
				
			||||||
                     .build()
 | 
					                .open();
 | 
				
			||||||
                     .open();
 | 
					    }
 | 
				
			||||||
 | 
					    //altes Fenster beim Start von TestWorld schließen
 | 
				
			||||||
 | 
					    public void startTestWorld() {
 | 
				
			||||||
 | 
					     // Entferne die aktuelle GUI
 | 
				
			||||||
 | 
					     guiNode.detachAllChildren();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					     // Erstelle ein Quadrat mit Textur
 | 
				
			||||||
 | 
					     Box box = new Box(1, 0.01f, 1);  // Dünnes Quadrat
 | 
				
			||||||
 | 
					     Geometry geom = new Geometry("Box", box);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					     // Setze das Material mit Textur
 | 
				
			||||||
 | 
					     Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
 | 
				
			||||||
 | 
					     Texture texture = assetManager.loadTexture("Pictures/board.png");
 | 
				
			||||||
 | 
					     mat.setTexture("ColorMap", texture);
 | 
				
			||||||
 | 
					     geom.setMaterial(mat);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					     // Füge das Quadrat zur Szene hinzu
 | 
				
			||||||
 | 
					     rootNode.attachChild(geom);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					     // Setze die Kameraposition
 | 
				
			||||||
 | 
					     cam.setLocation(new Vector3f(0, 0, 3));
 | 
				
			||||||
 | 
					     cam.lookAt(geom.getLocalTranslation(), Vector3f.UNIT_Y);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public void returnToMenu() {
 | 
				
			||||||
 | 
					        // Entferne die Testszene
 | 
				
			||||||
 | 
					        rootNode.detachAllChildren();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        // Zeige das Startmenü erneut
 | 
				
			||||||
 | 
					        StartMenu.createStartMenu(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /**
 | 
					
 | 
				
			||||||
     * Displays an error dialog with the specified error message.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param errorMessage The error message to display in the dialog.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    void errorDialog(String errorMessage) {
 | 
					 | 
				
			||||||
        DialogBuilder.simple(dialogManager)
 | 
					 | 
				
			||||||
                     .setTitle(lookup("dialog.error"))
 | 
					 | 
				
			||||||
                     .setText(errorMessage)
 | 
					 | 
				
			||||||
                     .setOkButton(lookup("button.ok"))
 | 
					 | 
				
			||||||
                     .build()
 | 
					 | 
				
			||||||
                     .open();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,13 +1,7 @@
 | 
				
			|||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
// Programming project code
 | 
					 | 
				
			||||||
// UniBw M, 2022, 2023, 2024
 | 
					 | 
				
			||||||
// www.unibw.de/inf2
 | 
					 | 
				
			||||||
// (c) Mark Minas (mark.minas@unibw.de)
 | 
					 | 
				
			||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package pp.monopoly.client;
 | 
					package pp.monopoly.client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.jme3.math.ColorRGBA;
 | 
					import com.jme3.math.ColorRGBA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pp.monopoly.game.client.MonopolyClientConfig;
 | 
					import pp.monopoly.game.client.MonopolyClientConfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,19 +1,13 @@
 | 
				
			|||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
// Programming project code
 | 
					 | 
				
			||||||
// UniBw M, 2022, 2023, 2024
 | 
					 | 
				
			||||||
// www.unibw.de/inf2
 | 
					 | 
				
			||||||
// (c) Mark Minas (mark.minas@unibw.de)
 | 
					 | 
				
			||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package pp.monopoly.client;
 | 
					package pp.monopoly.client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.jme3.app.Application;
 | 
					import com.jme3.app.Application;
 | 
				
			||||||
import com.jme3.app.state.AbstractAppState;
 | 
					import com.jme3.app.state.AbstractAppState;
 | 
				
			||||||
import com.jme3.app.state.AppStateManager;
 | 
					import com.jme3.app.state.AppStateManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pp.monopoly.game.client.ClientGameLogic;
 | 
					import pp.monopoly.game.client.ClientGameLogic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Abstract class representing a state in the Battleship game.
 | 
					 * Abstract class representing a state in the Monopoly game.
 | 
				
			||||||
 * Extends the AbstractAppState from jMonkeyEngine to manage state behavior.
 | 
					 * Extends the AbstractAppState from jMonkeyEngine to manage state behavior.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public abstract class MonopolyAppState extends AbstractAppState {
 | 
					public abstract class MonopolyAppState extends AbstractAppState {
 | 
				
			||||||
@@ -21,8 +15,6 @@ public abstract class MonopolyAppState extends AbstractAppState {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Creates a new MonopolyAppState that is initially disabled.
 | 
					     * Creates a new MonopolyAppState that is initially disabled.
 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @see #setEnabled(boolean)
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected MonopolyAppState() {
 | 
					    protected MonopolyAppState() {
 | 
				
			||||||
        setEnabled(false);
 | 
					        setEnabled(false);
 | 
				
			||||||
@@ -38,7 +30,9 @@ public abstract class MonopolyAppState extends AbstractAppState {
 | 
				
			|||||||
    public void initialize(AppStateManager stateManager, Application application) {
 | 
					    public void initialize(AppStateManager stateManager, Application application) {
 | 
				
			||||||
        super.initialize(stateManager, application);
 | 
					        super.initialize(stateManager, application);
 | 
				
			||||||
        this.app = (MonopolyApp) application;
 | 
					        this.app = (MonopolyApp) application;
 | 
				
			||||||
        if (isEnabled()) enableState();
 | 
					        if (isEnabled()) {
 | 
				
			||||||
 | 
					            enableState();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -59,15 +53,6 @@ public abstract class MonopolyAppState extends AbstractAppState {
 | 
				
			|||||||
        return app.getGameLogic();
 | 
					        return app.getGameLogic();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Checks if any dialog is currently displayed.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return true if any dialog is currently shown, false otherwise
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public boolean showsDialog() {
 | 
					 | 
				
			||||||
        return app.getDialogManager().showsDialog();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Sets the enabled state of the MonopolyAppState.
 | 
					     * Sets the enabled state of the MonopolyAppState.
 | 
				
			||||||
     * If the new state is the same as the current state, the method returns.
 | 
					     * If the new state is the same as the current state, the method returns.
 | 
				
			||||||
@@ -79,24 +64,21 @@ public abstract class MonopolyAppState extends AbstractAppState {
 | 
				
			|||||||
        if (isEnabled() == enabled) return;
 | 
					        if (isEnabled() == enabled) return;
 | 
				
			||||||
        super.setEnabled(enabled);
 | 
					        super.setEnabled(enabled);
 | 
				
			||||||
        if (app != null) {
 | 
					        if (app != null) {
 | 
				
			||||||
            if (enabled)
 | 
					            if (enabled) {
 | 
				
			||||||
                enableState();
 | 
					                enableState();
 | 
				
			||||||
            else
 | 
					            } else {
 | 
				
			||||||
                disableState();
 | 
					                disableState();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * This method is called when the state is enabled.
 | 
					     * Called when the state is enabled. Override to define specific behavior.
 | 
				
			||||||
     * It is meant to be overridden by subclasses to perform
 | 
					 | 
				
			||||||
     * specific actions when the state is enabled.
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected abstract void enableState();
 | 
					    protected abstract void enableState();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * This method is called when the state is disabled.
 | 
					     * Called when the state is disabled. Override to define specific behavior.
 | 
				
			||||||
     * It is meant to be overridden by subclasses to perform
 | 
					 | 
				
			||||||
     * specific actions when the state is disabled.
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected abstract void disableState();
 | 
					    protected abstract void disableState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,35 +1,27 @@
 | 
				
			|||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
// Programming project code
 | 
					 | 
				
			||||||
// UniBw M, 2022, 2023, 2024
 | 
					 | 
				
			||||||
// www.unibw.de/inf2
 | 
					 | 
				
			||||||
// (c) Mark Minas (mark.minas@unibw.de)
 | 
					 | 
				
			||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package pp.monopoly.client;
 | 
					package pp.monopoly.client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.simsilica.lemur.Container;
 | 
					 | 
				
			||||||
import com.simsilica.lemur.Label;
 | 
					 | 
				
			||||||
import com.simsilica.lemur.TextField;
 | 
					 | 
				
			||||||
import com.simsilica.lemur.component.SpringGridLayout;
 | 
					 | 
				
			||||||
import pp.dialog.Dialog;
 | 
					 | 
				
			||||||
import pp.dialog.DialogBuilder;
 | 
					 | 
				
			||||||
import pp.dialog.SimpleDialog;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.lang.System.Logger;
 | 
					import java.lang.System.Logger;
 | 
				
			||||||
import java.lang.System.Logger.Level;
 | 
					import java.lang.System.Logger.Level;
 | 
				
			||||||
import java.util.concurrent.ExecutionException;
 | 
					import java.util.concurrent.ExecutionException;
 | 
				
			||||||
import java.util.concurrent.Future;
 | 
					import java.util.concurrent.Future;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static pp.monopoly.Resources.lookup;
 | 
					import com.simsilica.lemur.Button;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.Container;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.Label;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.TextField;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import pp.dialog.Dialog;
 | 
				
			||||||
 | 
					import pp.dialog.DialogBuilder;
 | 
				
			||||||
 | 
					import pp.dialog.SimpleDialog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Represents a dialog for setting up a network connection in the Battleship game.
 | 
					 * Represents a dialog for setting up a network connection in the Monopoly game.
 | 
				
			||||||
 * Allows users to specify the host and port for connecting to a game server.
 | 
					 * Allows users to specify the host and port for connecting to a game server.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class NetworkDialog extends SimpleDialog {
 | 
					class NetworkDialog extends SimpleDialog {
 | 
				
			||||||
    private static final Logger LOGGER = System.getLogger(NetworkDialog.class.getName());
 | 
					    private static final Logger LOGGER = System.getLogger(NetworkDialog.class.getName());
 | 
				
			||||||
    private static final String LOCALHOST = "localhost"; //NON-NLS
 | 
					    private static final String LOCALHOST = "localhost";
 | 
				
			||||||
    private static final String DEFAULT_PORT = "1234"; //NON-NLS
 | 
					    private static final String DEFAULT_PORT = "1234";
 | 
				
			||||||
    private final NetworkSupport network;
 | 
					    private final NetworkSupport network;
 | 
				
			||||||
    private final TextField host = new TextField(LOCALHOST);
 | 
					    private final TextField host = new TextField(LOCALHOST);
 | 
				
			||||||
    private final TextField port = new TextField(DEFAULT_PORT);
 | 
					    private final TextField port = new TextField(DEFAULT_PORT);
 | 
				
			||||||
@@ -46,56 +38,59 @@ class NetworkDialog extends SimpleDialog {
 | 
				
			|||||||
    NetworkDialog(NetworkSupport network) {
 | 
					    NetworkDialog(NetworkSupport network) {
 | 
				
			||||||
        super(network.getApp().getDialogManager());
 | 
					        super(network.getApp().getDialogManager());
 | 
				
			||||||
        this.network = network;
 | 
					        this.network = network;
 | 
				
			||||||
        host.setSingleLine(true);
 | 
					        initializeDialog();
 | 
				
			||||||
        host.setPreferredWidth(400f);
 | 
					 | 
				
			||||||
        port.setSingleLine(true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        final MonopolyApp app = network.getApp();
 | 
					 | 
				
			||||||
        final Container input = new Container(new SpringGridLayout());
 | 
					 | 
				
			||||||
        input.addChild(new Label(lookup("host.name") + ":  "));
 | 
					 | 
				
			||||||
        input.addChild(host, 1);
 | 
					 | 
				
			||||||
        input.addChild(new Label(lookup("port.number") + ":  "));
 | 
					 | 
				
			||||||
        input.addChild(port, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        DialogBuilder.simple(app.getDialogManager())
 | 
					 | 
				
			||||||
                     .setTitle(lookup("server.dialog"))
 | 
					 | 
				
			||||||
                     .setExtension(d -> d.addChild(input))
 | 
					 | 
				
			||||||
                     .setOkButton(lookup("button.connect"), d -> connect())
 | 
					 | 
				
			||||||
                     .setNoButton(lookup("button.cancel"), app::closeApp)
 | 
					 | 
				
			||||||
                     .setOkClose(false)
 | 
					 | 
				
			||||||
                     .setNoClose(false)
 | 
					 | 
				
			||||||
                     .build(this);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Handles the action for the connect button in the connection dialog.
 | 
					     * Initializes the dialog with input fields and connection buttons.
 | 
				
			||||||
     * Tries to parse the port number and initiate connection to the server.
 | 
					     */
 | 
				
			||||||
 | 
					    private void initializeDialog() {
 | 
				
			||||||
 | 
					        final MonopolyApp app = network.getApp();
 | 
				
			||||||
 | 
					        Container inputContainer = new Container();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Titel und Eingabefelder für Host und Port
 | 
				
			||||||
 | 
					        inputContainer.addChild(new Label("Server-Adresse"));
 | 
				
			||||||
 | 
					        inputContainer.addChild(host);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inputContainer.addChild(new Label("Port"));
 | 
				
			||||||
 | 
					        inputContainer.addChild(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Button connectButton = inputContainer.addChild(new Button("Verbinden"));
 | 
				
			||||||
 | 
					        connectButton.addClickCommands(source -> connect());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Button cancelButton = inputContainer.addChild(new Button("Abbrechen"));
 | 
				
			||||||
 | 
					        cancelButton.addClickCommands(source -> app.closeApp());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        app.getGuiNode().attachChild(inputContainer);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Initiates the connection attempt based on the entered host and port.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private void connect() {
 | 
					    private void connect() {
 | 
				
			||||||
        LOGGER.log(Level.INFO, "connect to host={0}, port={1}", host, port); //NON-NLS
 | 
					        LOGGER.log(Level.INFO, "Connecting to host={0}, port={1}", host, port);
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            hostname = host.getText().trim().isEmpty() ? LOCALHOST : host.getText();
 | 
					            hostname = host.getText().trim().isEmpty() ? LOCALHOST : host.getText();
 | 
				
			||||||
            portNumber = Integer.parseInt(port.getText());
 | 
					            portNumber = Integer.parseInt(port.getText());
 | 
				
			||||||
            openProgressDialog();
 | 
					            openProgressDialog();
 | 
				
			||||||
            connectionFuture = network.getApp().getExecutor().submit(this::initNetwork);
 | 
					            connectionFuture = network.getApp().getExecutor().submit(this::initNetwork);
 | 
				
			||||||
        }
 | 
					        } catch (NumberFormatException e) {
 | 
				
			||||||
        catch (NumberFormatException e) {
 | 
					            network.getApp().errorDialog("Port muss eine Zahl sein.");
 | 
				
			||||||
            network.getApp().errorDialog(lookup("port.must.be.integer"));
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Creates a dialog indicating that the connection is in progress.
 | 
					     * Opens a progress dialog while connecting.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private void openProgressDialog() {
 | 
					    private void openProgressDialog() {
 | 
				
			||||||
        progressDialog = DialogBuilder.simple(network.getApp().getDialogManager())
 | 
					        progressDialog = DialogBuilder.simple(network.getApp().getDialogManager())
 | 
				
			||||||
                                      .setText(lookup("label.connecting"))
 | 
					                                      .setText("Verbinde zum Server...")
 | 
				
			||||||
                                      .build();
 | 
					                                      .build();
 | 
				
			||||||
        progressDialog.open();
 | 
					        progressDialog.open();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Tries to initialize the network connection.
 | 
					     * Attempts to initialize the network connection.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @throws RuntimeException If an error occurs when creating the client.
 | 
					     * @throws RuntimeException If an error occurs when creating the client.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@@ -103,40 +98,37 @@ class NetworkDialog extends SimpleDialog {
 | 
				
			|||||||
        try {
 | 
					        try {
 | 
				
			||||||
            network.initNetwork(hostname, portNumber);
 | 
					            network.initNetwork(hostname, portNumber);
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        } catch (Exception e) {
 | 
				
			||||||
        catch (Exception e) {
 | 
					 | 
				
			||||||
            throw new RuntimeException(e);
 | 
					            throw new RuntimeException(e);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * This method is called by {@linkplain pp.dialog.DialogManager#update(float)} for periodically
 | 
					     * Updates the connection status and handles completion or failure.
 | 
				
			||||||
     * updating this dialog. T
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void update(float delta) {
 | 
					    public void update(float delta) {
 | 
				
			||||||
        if (connectionFuture != null && connectionFuture.isDone())
 | 
					        if (connectionFuture != null && connectionFuture.isDone()) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                connectionFuture.get();
 | 
					                connectionFuture.get();
 | 
				
			||||||
                success();
 | 
					                onSuccess();
 | 
				
			||||||
            }
 | 
					            } catch (ExecutionException e) {
 | 
				
			||||||
            catch (ExecutionException e) {
 | 
					                onFailure(e.getCause());
 | 
				
			||||||
                failure(e.getCause());
 | 
					            } catch (InterruptedException e) {
 | 
				
			||||||
            }
 | 
					                LOGGER.log(Level.WARNING, "Connection interrupted.", e);
 | 
				
			||||||
            catch (InterruptedException e) {
 | 
					 | 
				
			||||||
                LOGGER.log(Level.WARNING, "Interrupted!", e); //NON-NLS
 | 
					 | 
				
			||||||
                Thread.currentThread().interrupt();
 | 
					                Thread.currentThread().interrupt();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Handles a successful connection to the game server.
 | 
					     * Handles a successful connection to the game server.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private void success() {
 | 
					    private void onSuccess() {
 | 
				
			||||||
        connectionFuture = null;
 | 
					        connectionFuture = null;
 | 
				
			||||||
        progressDialog.close();
 | 
					        progressDialog.close();
 | 
				
			||||||
        this.close();
 | 
					        this.close();
 | 
				
			||||||
        network.getApp().setInfoText(lookup("wait.for.an.opponent"));
 | 
					        network.getApp().setInfoText("Warte auf einen Gegner...");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -144,10 +136,11 @@ class NetworkDialog extends SimpleDialog {
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param e The cause of the failure.
 | 
					     * @param e The cause of the failure.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private void failure(Throwable e) {
 | 
					    private void onFailure(Throwable e) {
 | 
				
			||||||
        connectionFuture = null;
 | 
					        connectionFuture = null;
 | 
				
			||||||
        progressDialog.close();
 | 
					        progressDialog.close();
 | 
				
			||||||
        network.getApp().errorDialog(lookup("server.connection.failed"));
 | 
					        network.getApp().errorDialog("Verbindung zum Server fehlgeschlagen.");
 | 
				
			||||||
        network.getApp().setInfoText(e.getLocalizedMessage());
 | 
					        network.getApp().setInfoText(e.getLocalizedMessage());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,29 +1,21 @@
 | 
				
			|||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
// Programming project code
 | 
					 | 
				
			||||||
// UniBw M, 2022, 2023, 2024
 | 
					 | 
				
			||||||
// www.unibw.de/inf2
 | 
					 | 
				
			||||||
// (c) Mark Minas (mark.minas@unibw.de)
 | 
					 | 
				
			||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package pp.monopoly.client;
 | 
					package pp.monopoly.client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.lang.System.Logger;
 | 
				
			||||||
 | 
					import java.lang.System.Logger.Level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.jme3.network.Client;
 | 
					import com.jme3.network.Client;
 | 
				
			||||||
import com.jme3.network.ClientStateListener;
 | 
					import com.jme3.network.ClientStateListener;
 | 
				
			||||||
import com.jme3.network.Message;
 | 
					import com.jme3.network.Message;
 | 
				
			||||||
import com.jme3.network.MessageListener;
 | 
					import com.jme3.network.MessageListener;
 | 
				
			||||||
import com.jme3.network.Network;
 | 
					import com.jme3.network.Network;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pp.monopoly.game.client.ServerConnection;
 | 
					import pp.monopoly.game.client.ServerConnection;
 | 
				
			||||||
import pp.monopoly.message.client.ClientMessage;
 | 
					import pp.monopoly.message.client.ClientMessage;
 | 
				
			||||||
import pp.monopoly.message.server.ServerMessage;
 | 
					import pp.monopoly.message.server.ServerMessage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					 | 
				
			||||||
import java.lang.System.Logger;
 | 
					 | 
				
			||||||
import java.lang.System.Logger.Level;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static pp.monopoly.Resources.lookup;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Manages the network connection for the Battleship 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 {
 | 
					class NetworkSupport implements MessageListener<Client>, ClientStateListener, ServerConnection {
 | 
				
			||||||
@@ -32,18 +24,18 @@ class NetworkSupport implements MessageListener<Client>, ClientStateListener, Se
 | 
				
			|||||||
    private Client client;
 | 
					    private Client client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Constructs a NetworkSupport instance for the given Battleship application.
 | 
					     * Constructs a NetworkSupport instance for the Monopoly application.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param app The Battleship application instance.
 | 
					     * @param app The Monopoly application instance.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public NetworkSupport(MonopolyApp app) {
 | 
					    public NetworkSupport(MonopolyApp app) {
 | 
				
			||||||
        this.app = app;
 | 
					        this.app = app;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Returns the Battleship application instance.
 | 
					     * Returns the Monopoly application instance.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return Battleship application instance
 | 
					     * @return Monopoly application instance
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    MonopolyApp getApp() {
 | 
					    MonopolyApp getApp() {
 | 
				
			||||||
        return app;
 | 
					        return app;
 | 
				
			||||||
@@ -65,8 +57,9 @@ class NetworkSupport implements MessageListener<Client>, ClientStateListener, Se
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void connect() {
 | 
					    public void connect() {
 | 
				
			||||||
        if (client == null)
 | 
					        if (client == null) {
 | 
				
			||||||
            new NetworkDialog(this).open();
 | 
					            new NetworkDialog(this).open();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -77,7 +70,7 @@ class NetworkSupport implements MessageListener<Client>, ClientStateListener, Se
 | 
				
			|||||||
        if (client == null) return;
 | 
					        if (client == null) return;
 | 
				
			||||||
        client.close();
 | 
					        client.close();
 | 
				
			||||||
        client = null;
 | 
					        client = null;
 | 
				
			||||||
        LOGGER.log(Level.INFO, "client closed"); //NON-NLS
 | 
					        LOGGER.log(Level.INFO, "Client connection closed.");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -88,8 +81,9 @@ class NetworkSupport implements MessageListener<Client>, ClientStateListener, Se
 | 
				
			|||||||
     * @throws IOException If an I/O error occurs when creating the client.
 | 
					     * @throws IOException If an I/O error occurs when creating the client.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    void initNetwork(String host, int port) throws IOException {
 | 
					    void initNetwork(String host, int port) throws IOException {
 | 
				
			||||||
        if (client != null)
 | 
					        if (client != null) {
 | 
				
			||||||
            throw new IllegalStateException("trying to join a game again");
 | 
					            throw new IllegalStateException("Already connected to the game server.");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        client = Network.connectToServer(host, port);
 | 
					        client = Network.connectToServer(host, port);
 | 
				
			||||||
        client.start();
 | 
					        client.start();
 | 
				
			||||||
        client.addMessageListener(this);
 | 
					        client.addMessageListener(this);
 | 
				
			||||||
@@ -104,9 +98,10 @@ class NetworkSupport implements MessageListener<Client>, ClientStateListener, Se
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void messageReceived(Client client, Message message) {
 | 
					    public void messageReceived(Client client, Message message) {
 | 
				
			||||||
        LOGGER.log(Level.INFO, "message received from server: {0}", message); //NON-NLS
 | 
					        LOGGER.log(Level.INFO, "Message received from server: {0}", message);
 | 
				
			||||||
        if (message instanceof ServerMessage serverMessage)
 | 
					        if (message instanceof ServerMessage serverMessage) {
 | 
				
			||||||
            app.enqueue(() -> serverMessage.accept(app.getGameLogic()));
 | 
					            app.enqueue(() -> serverMessage.accept(app.getGameLogic()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -116,7 +111,7 @@ class NetworkSupport implements MessageListener<Client>, ClientStateListener, Se
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void clientConnected(Client client) {
 | 
					    public void clientConnected(Client client) {
 | 
				
			||||||
        LOGGER.log(Level.INFO, "Client connected: {0}", client); //NON-NLS
 | 
					        LOGGER.log(Level.INFO, "Successfully connected to server: {0}", client);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -127,13 +122,9 @@ class NetworkSupport implements MessageListener<Client>, ClientStateListener, Se
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void clientDisconnected(Client client, DisconnectInfo disconnectInfo) {
 | 
					    public void clientDisconnected(Client client, DisconnectInfo disconnectInfo) {
 | 
				
			||||||
        LOGGER.log(Level.INFO, "Client {0} disconnected: {1}", client, disconnectInfo); //NON-NLS
 | 
					        LOGGER.log(Level.INFO, "Disconnected from server: {0}", disconnectInfo);
 | 
				
			||||||
        if (this.client != client)
 | 
					 | 
				
			||||||
            throw new IllegalArgumentException("parameter value must be client");
 | 
					 | 
				
			||||||
        LOGGER.log(Level.INFO, "client still connected: {0}", client.isConnected()); //NON-NLS
 | 
					 | 
				
			||||||
        this.client = null;
 | 
					        this.client = null;
 | 
				
			||||||
        disconnect();
 | 
					        app.enqueue(() -> app.setInfoText("Verbindung zum Server verloren."));
 | 
				
			||||||
        app.enqueue(() -> app.setInfoText(lookup("lost.connection.to.server")));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -143,10 +134,11 @@ class NetworkSupport implements MessageListener<Client>, ClientStateListener, Se
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void send(ClientMessage message) {
 | 
					    public void send(ClientMessage message) {
 | 
				
			||||||
        LOGGER.log(Level.INFO, "sending {0}", message); //NON-NLS
 | 
					        LOGGER.log(Level.INFO, "Sending message to server: {0}", message);
 | 
				
			||||||
        if (client == null)
 | 
					        if (client == null) {
 | 
				
			||||||
            app.errorDialog(lookup("lost.connection.to.server"));
 | 
					            app.errorDialog("Verbindung zum Server verloren.");
 | 
				
			||||||
        else
 | 
					        } else {
 | 
				
			||||||
            client.send(message);
 | 
					            client.send(message);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,117 +1,123 @@
 | 
				
			|||||||
package pp.monopoly.client;
 | 
					package pp.monopoly.client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.jme3.asset.TextureKey;
 | 
					 | 
				
			||||||
import com.jme3.material.Material;
 | 
					import com.jme3.material.Material;
 | 
				
			||||||
 | 
					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.jme3.scene.shape.Quad;
 | 
					import com.jme3.scene.shape.Quad;
 | 
				
			||||||
import com.jme3.texture.Texture;
 | 
					import com.jme3.texture.Texture;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.Axis;
 | 
				
			||||||
import com.simsilica.lemur.Button;
 | 
					import com.simsilica.lemur.Button;
 | 
				
			||||||
import com.simsilica.lemur.Insets3f;
 | 
					import com.simsilica.lemur.Container;
 | 
				
			||||||
import com.simsilica.lemur.Label;
 | 
					import com.simsilica.lemur.HAlignment;
 | 
				
			||||||
import com.simsilica.lemur.Panel;
 | 
					 | 
				
			||||||
import com.simsilica.lemur.style.ElementId;
 | 
					 | 
				
			||||||
import com.simsilica.lemur.component.QuadBackgroundComponent;
 | 
					import com.simsilica.lemur.component.QuadBackgroundComponent;
 | 
				
			||||||
import com.jme3.math.ColorRGBA;
 | 
					import com.simsilica.lemur.component.SpringGridLayout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pp.dialog.Dialog;
 | 
					import pp.dialog.Dialog;
 | 
				
			||||||
 | 
					import pp.monopoly.client.gui.CreateGameMenu;
 | 
				
			||||||
 | 
					import pp.monopoly.client.gui.SettingsMenu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Constructs the startup menu dialog for the Monopoly application.
 | 
				
			||||||
import pp.monopoly.client.gui.GameMenu;
 | 
					import pp.monopoly.client.gui.GameMenu;
 | 
				
			||||||
import pp.dialog.DialogManager;
 | 
					 */
 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.prefs.Preferences;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static pp.monopoly.Resources.lookup;
 | 
					 | 
				
			||||||
import static pp.util.PreferencesUtils.getPreferences;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class StartMenu extends Dialog {
 | 
					public class StartMenu extends Dialog {
 | 
				
			||||||
    private static final Preferences PREFERENCES = getPreferences(StartMenu.class);
 | 
					 | 
				
			||||||
    private final MonopolyApp app;
 | 
					    private final MonopolyApp app;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Buttons for the menu
 | 
					 | 
				
			||||||
    private final Button playButton = new Button(lookup("button.play"));
 | 
					 | 
				
			||||||
    private final Button quitButton = new Button(lookup("menu.quit"));
 | 
					 | 
				
			||||||
    private final Button settingsButton = new Button("Einstellungen", new ElementId("menu-button"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Constructs the StartMenu dialog for the Monopoly application.
 | 
					     * Constructs the Startup Menu dialog for the Monopoly application.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param app the MonopolyApp instance
 | 
					     * @param app the MonopolyApp instance
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public StartMenu(MonopolyApp app) {
 | 
					    public StartMenu(MonopolyApp app) {
 | 
				
			||||||
        super(app.getDialogManager());
 | 
					        super(app.getDialogManager());
 | 
				
			||||||
        this.app = app;
 | 
					        this.app = app;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Load and display the background image
 | 
					    /**
 | 
				
			||||||
        TextureKey backgroundKey = new TextureKey("unibw-bib", false);
 | 
					     * Creates and displays the Start Menu with buttons for starting the game,
 | 
				
			||||||
        Texture backgroundTexture = app.getAssetManager().loadTexture(backgroundKey);
 | 
					     * opening settings, and quitting the application.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static void createStartMenu(MonopolyApp app) {
 | 
				
			||||||
 | 
					        int screenWidth = app.getContext().getSettings().getWidth();
 | 
				
			||||||
 | 
					        int screenHeight = app.getContext().getSettings().getHeight();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Set up the background image
 | 
				
			||||||
 | 
					        Texture backgroundImage = app.getAssetManager().loadTexture("Pictures/unibw-Bib2.png");
 | 
				
			||||||
 | 
					        Quad quad = new Quad(screenWidth, screenHeight);
 | 
				
			||||||
 | 
					        Geometry background = new Geometry("Background", quad);
 | 
				
			||||||
        Material backgroundMaterial = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
 | 
					        Material backgroundMaterial = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
 | 
				
			||||||
        backgroundMaterial.setTexture("ColorMap", backgroundTexture);
 | 
					        backgroundMaterial.setTexture("ColorMap", backgroundImage);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Create a large Quad for the background
 | 
					 | 
				
			||||||
        Quad backgroundQuad = new Quad(16, 9); // Adjust size as necessary to fill the screen
 | 
					 | 
				
			||||||
        Geometry background = new Geometry("Background", backgroundQuad);
 | 
					 | 
				
			||||||
        background.setMaterial(backgroundMaterial);
 | 
					        background.setMaterial(backgroundMaterial);
 | 
				
			||||||
        background.setLocalTranslation(new Vector3f(-8, -4.5f, -1)); // Position it behind the UI components
 | 
					        background.setLocalTranslation(0, 0, -1); // Ensure it is behind other GUI elements
 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Attach the background as the first element
 | 
					 | 
				
			||||||
        app.getGuiNode().attachChild(background);
 | 
					        app.getGuiNode().attachChild(background);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Load and display the Monopoly logo
 | 
					        // Center container for title and play button
 | 
				
			||||||
        TextureKey monopolyLogoKey = new TextureKey("log-Monopoly", false);
 | 
					        Container centerMenu = new Container(new SpringGridLayout(Axis.Y, Axis.X));
 | 
				
			||||||
        Texture monopolyLogoTexture = app.getAssetManager().loadTexture(monopolyLogoKey);
 | 
					 | 
				
			||||||
        Material monopolyLogoMaterial = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
 | 
					 | 
				
			||||||
        monopolyLogoMaterial.setTexture("ColorMap", monopolyLogoTexture);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Quad monopolyQuad = new Quad(5, 1.5f); // Adjust dimensions as necessary
 | 
					        Button startButton = new Button("Spielen");
 | 
				
			||||||
        Geometry monopolyLogo = new Geometry("MonopolyLogo", monopolyQuad);
 | 
					        startButton.setPreferredSize(new Vector3f(190, 60, 0)); // Increase button size (width, height)
 | 
				
			||||||
        monopolyLogo.setMaterial(monopolyLogoMaterial);
 | 
					        startButton.setFontSize(40); // Set the font size for the button text
 | 
				
			||||||
        monopolyLogo.setLocalTranslation(new Vector3f(0, 5, 0)); // Position Monopoly logo at the top
 | 
					        startButton.setTextHAlignment(HAlignment.Center); // Center the text horizontally
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Panel monopolyLogoPanel = new Panel();
 | 
					        // Set a custom border and background color
 | 
				
			||||||
        addChild(monopolyLogoPanel);
 | 
					        ColorRGBA borderColor = ColorRGBA.Orange; // Example: White border
 | 
				
			||||||
 | 
					        ColorRGBA backgroundColor = ColorRGBA.LightGray; // Example: light gray background
 | 
				
			||||||
 | 
					        QuadBackgroundComponent backgroundColorSp = new QuadBackgroundComponent(backgroundColor);
 | 
				
			||||||
 | 
					        backgroundColorSp.setMargin(2, 2); // Optional: Adjust margin for the border
 | 
				
			||||||
 | 
					        backgroundColorSp.setColor(borderColor); // Set border color
 | 
				
			||||||
 | 
					        startButton.setBackground(backgroundColorSp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Load and display the university logo
 | 
					        startButton.addClickCommands(source -> startGame(app));
 | 
				
			||||||
        TextureKey universityLogoKey = new TextureKey("unibw-logo.png", false);
 | 
					        centerMenu.addChild(startButton);
 | 
				
			||||||
        Texture universityLogoTexture = app.getAssetManager().loadTexture(universityLogoKey);
 | 
					 | 
				
			||||||
        Material universityLogoMaterial = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
 | 
					 | 
				
			||||||
        universityLogoMaterial.setTexture("ColorMap", universityLogoTexture);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Quad universityQuad = new Quad(4, 1); // Adjust dimensions to fit below Monopoly logo
 | 
					        // Position the center container in the middle of the screen
 | 
				
			||||||
        Geometry universityLogo = new Geometry("UniversityLogo", universityQuad);
 | 
					        centerMenu.setLocalTranslation(new Vector3f(screenWidth / 2f - centerMenu.getPreferredSize().x / 2f,
 | 
				
			||||||
        universityLogo.setMaterial(universityLogoMaterial);
 | 
					                                                    screenHeight / 2f - 280 + centerMenu.getPreferredSize().y / 2f,
 | 
				
			||||||
        universityLogo.setLocalTranslation(new Vector3f(0, 3, 0)); // Position below the Monopoly logo
 | 
					                                                    0));
 | 
				
			||||||
 | 
					        app.getGuiNode().attachChild(centerMenu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Panel universityLogoPanel = new Panel();
 | 
					        // Lower-left container for "Spiel beenden" button
 | 
				
			||||||
        addChild(universityLogoPanel);
 | 
					        Container lowerLeftMenu = new Container();
 | 
				
			||||||
 | 
					        lowerLeftMenu.setLocalTranslation(new Vector3f(100, 90, 0));
 | 
				
			||||||
 | 
					        Button quitButton = new Button("Spiel beenden");
 | 
				
			||||||
 | 
					        quitButton.setPreferredSize(new Vector3f(130, 40, 0)); // Increase button size slightly (width, height)
 | 
				
			||||||
 | 
					        quitButton.setFontSize(20);
 | 
				
			||||||
 | 
					        quitButton.addClickCommands(source -> quitGame());
 | 
				
			||||||
 | 
					        lowerLeftMenu.addChild(quitButton);
 | 
				
			||||||
 | 
					        app.getGuiNode().attachChild(lowerLeftMenu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Lower-right container for "Einstellungen" button
 | 
				
			||||||
 | 
					        Container lowerRightMenu = new Container();
 | 
				
			||||||
        // Button actions
 | 
					        lowerRightMenu.setLocalTranslation(new Vector3f(screenWidth - 200, 90, 0));
 | 
				
			||||||
        playButton.addClickCommands(source -> startGame());
 | 
					        Button settingsButton = new Button("Einstellungen");
 | 
				
			||||||
        quitButton.addClickCommands(source -> app.closeApp());
 | 
					        settingsButton.setPreferredSize(new Vector3f(130, 40, 0)); // Increase button size slightly (width, height)
 | 
				
			||||||
        settingsButton.addClickCommands(source -> openSettings());
 | 
					        settingsButton.setFontSize(20); // Increase the font size for the text
 | 
				
			||||||
 | 
					        settingsButton.addClickCommands(source -> openSettings(app));
 | 
				
			||||||
        addChild(monopolyLogoPanel);
 | 
					        lowerRightMenu.addChild(settingsButton);
 | 
				
			||||||
        addChild(universityLogoPanel);
 | 
					        app.getGuiNode().attachChild(lowerRightMenu);
 | 
				
			||||||
        addChild(playButton);
 | 
					 | 
				
			||||||
        addChild(quitButton);
 | 
					 | 
				
			||||||
        addChild(settingsButton);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void startGame() {
 | 
					    /**
 | 
				
			||||||
        System.out.println("Starting game...");
 | 
					     * Starts the game by transitioning to the CreateGameMenu.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static void startGame(MonopolyApp app) {
 | 
				
			||||||
 | 
					        app.getGuiNode().detachAllChildren();
 | 
				
			||||||
 | 
					        new CreateGameMenu(app);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void openSettings() {
 | 
					    /**
 | 
				
			||||||
        app.getDialogManager().close(this);
 | 
					     * Opens the settings menu.
 | 
				
			||||||
        app.getDialogManager().open(new GameMenu(app));
 | 
					     */
 | 
				
			||||||
 | 
					    private static void openSettings(MonopolyApp app) {
 | 
				
			||||||
 | 
					        app.getGuiNode().detachAllChildren();
 | 
				
			||||||
 | 
					        new SettingsMenu(app);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    /**
 | 
				
			||||||
    public void update() {
 | 
					     * Quits the game application.
 | 
				
			||||||
    }
 | 
					     */
 | 
				
			||||||
 | 
					    private static void quitGame() {
 | 
				
			||||||
    @Override
 | 
					        System.exit(0);
 | 
				
			||||||
    public void escape() {
 | 
					 | 
				
			||||||
        close();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,16 +1,10 @@
 | 
				
			|||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
// Programming project code
 | 
					 | 
				
			||||||
// UniBw M, 2022, 2023, 2024
 | 
					 | 
				
			||||||
// www.unibw.de/inf2
 | 
					 | 
				
			||||||
// (c) Mark Minas (mark.minas@unibw.de)
 | 
					 | 
				
			||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package pp.monopoly.client.gui;
 | 
					package pp.monopoly.client.gui;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.jme3.scene.Node;
 | 
					import com.jme3.scene.Node;
 | 
				
			||||||
import com.jme3.scene.Spatial;
 | 
					import com.jme3.scene.Spatial;
 | 
				
			||||||
import pp.monopoly.model.Item;
 | 
					
 | 
				
			||||||
import pp.monopoly.model.Board;
 | 
					import pp.monopoly.model.Board;
 | 
				
			||||||
 | 
					import pp.monopoly.model.Item;
 | 
				
			||||||
import pp.monopoly.model.Visitor;
 | 
					import pp.monopoly.model.Visitor;
 | 
				
			||||||
import pp.monopoly.notification.GameEventListener;
 | 
					import pp.monopoly.notification.GameEventListener;
 | 
				
			||||||
import pp.monopoly.notification.ItemAddedEvent;
 | 
					import pp.monopoly.notification.ItemAddedEvent;
 | 
				
			||||||
@@ -21,30 +15,23 @@ import pp.view.ModelViewSynchronizer;
 | 
				
			|||||||
 * Abstract base class for synchronizing the visual representation of a {@link Board} with its model state.
 | 
					 * Abstract base class for synchronizing the visual representation of a {@link Board} with its model state.
 | 
				
			||||||
 * This class handles the addition and removal of items from the map, ensuring that changes in the model
 | 
					 * This class handles the addition and removal of items from the map, ensuring that changes in the model
 | 
				
			||||||
 * are accurately reflected in the view.
 | 
					 * are accurately reflected in the view.
 | 
				
			||||||
 * <p>
 | 
					 | 
				
			||||||
 * Subclasses are responsible for providing the specific implementation of how each item in the map
 | 
					 | 
				
			||||||
 * is represented visually by implementing the {@link Visitor} interface.
 | 
					 | 
				
			||||||
 * </p>
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
abstract class BoardSynchronizer extends ModelViewSynchronizer<Item> implements Visitor<Spatial>, GameEventListener {
 | 
					abstract class BoardSynchronizer extends ModelViewSynchronizer<Item> implements Visitor<Spatial>, GameEventListener {
 | 
				
			||||||
    // The map that this synchronizer is responsible for
 | 
					 | 
				
			||||||
    private final Board board;
 | 
					    private final Board board;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Constructs a new BoardSynchronizer.
 | 
					     * Constructs a new BoardSynchronizer.
 | 
				
			||||||
     * Initializes the synchronizer with the provided map and the root node for attaching view representations.
 | 
					 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param map  the map to be synchronized
 | 
					     * @param board the game board to synchronize
 | 
				
			||||||
     * @param root the root node to which the view representations of the map items are attached
 | 
					     * @param root  the root node to which the view representations of the board items are attached
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected BoardSynchronizer(Board map, Node root) {
 | 
					    protected BoardSynchronizer(Board board, Node root) {
 | 
				
			||||||
        super(root);
 | 
					        super(root);
 | 
				
			||||||
        this.board = map;
 | 
					        this.board = board;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Translates a model item into its corresponding visual representation.
 | 
					     * Translates a model item into its corresponding visual representation.
 | 
				
			||||||
     * The specific visual representation is determined by the concrete implementation of the {@link Visitor} interface.
 | 
					 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param item the item from the model to be translated
 | 
					     * @param item the item from the model to be translated
 | 
				
			||||||
     * @return the visual representation of the item as a {@link Spatial}
 | 
					     * @return the visual representation of the item as a {@link Spatial}
 | 
				
			||||||
@@ -55,35 +42,33 @@ abstract class BoardSynchronizer extends ModelViewSynchronizer<Item> implements
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Adds the existing items from the map to the view.
 | 
					     * Adds the existing items from the board to the view during initialization.
 | 
				
			||||||
     * This method should be called during initialization to ensure that all current items in the map
 | 
					 | 
				
			||||||
     * are visually represented.
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected void addExisting() {
 | 
					    protected void addExisting() {
 | 
				
			||||||
        board.getItems().forEach(this::add);
 | 
					        board.getItems().forEach(this::add);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Handles the event when an item is removed from the map.
 | 
					     * Handles the event when an item is removed from the board.
 | 
				
			||||||
     * Removes the visual representation of the item from the view if it belongs to the synchronized map.
 | 
					 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param event the event indicating that an item has been removed from the map
 | 
					     * @param event the event indicating that an item has been removed from the board
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void receivedEvent(ItemRemovedEvent event) {
 | 
					    public void receivedEvent(ItemRemovedEvent event) {
 | 
				
			||||||
        if (board == event.map())
 | 
					        if (board == event.getBoard()) {
 | 
				
			||||||
            delete(event.item());
 | 
					            delete(event.getItem());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Handles the event when an item is added to the map.
 | 
					     * Handles the event when an item is added to the board.
 | 
				
			||||||
     * Adds the visual representation of the new item to the view if it belongs to the synchronized map.
 | 
					 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param event the event indicating that an item has been added to the map
 | 
					     * @param event the event indicating that an item has been added to the board
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void receivedEvent(ItemAddedEvent event) {
 | 
					    public void receivedEvent(ItemAddedEvent event) {
 | 
				
			||||||
        if (board == event.map())
 | 
					        if (board == event.getBoard()) {
 | 
				
			||||||
            add(event.item());
 | 
					            add(event.getItem());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,129 @@
 | 
				
			|||||||
 | 
					package pp.monopoly.client.gui;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.jme3.material.Material;
 | 
				
			||||||
 | 
					import com.jme3.math.Vector3f;
 | 
				
			||||||
 | 
					import com.jme3.scene.Geometry;
 | 
				
			||||||
 | 
					import com.jme3.scene.shape.Quad;
 | 
				
			||||||
 | 
					import com.jme3.texture.Texture;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.Axis;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.Button;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.Container;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.Label;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.TextField;
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public CreateGameMenu(MonopolyApp app) {
 | 
				
			||||||
 | 
					        this.app = app;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Hintergrundbild laden und hinzufügen
 | 
				
			||||||
 | 
					        addBackgroundImage();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Hauptcontainer für das Menü
 | 
				
			||||||
 | 
					        menuContainer = new Container(new SpringGridLayout(Axis.Y, Axis.X));
 | 
				
			||||||
 | 
					        menuContainer.setPreferredSize(new Vector3f(600, 400, 0)); // Feste Größe des Containers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Titel
 | 
				
			||||||
 | 
					        Label title = menuContainer.addChild(new Label("Neues Spiel"));
 | 
				
			||||||
 | 
					        title.setFontSize(48);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Eingabefelder-Container
 | 
				
			||||||
 | 
					        Container inputContainer = menuContainer.addChild(new Container(new SpringGridLayout(Axis.Y, Axis.X)));
 | 
				
			||||||
 | 
					        inputContainer.setPreferredSize(new Vector3f(200, 150, 0)); // Eingabefelder nicht ganz so breit
 | 
				
			||||||
 | 
					        inputContainer.setLocalTranslation(20, 0, 0); // Abstand vom Rand
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inputContainer.addChild(new Label("Server-Adresse:"));
 | 
				
			||||||
 | 
					        TextField playerNameField = inputContainer.addChild(new TextField("localhost"));
 | 
				
			||||||
 | 
					        playerNameField.setPreferredWidth(400); // Breite des Textfelds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inputContainer.addChild(new Label("Port:"));
 | 
				
			||||||
 | 
					        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)));
 | 
				
			||||||
 | 
					        buttonContainer.setPreferredSize(new Vector3f(400, 50, 0));
 | 
				
			||||||
 | 
					        buttonContainer.setLocalTranslation(20, 0, 0); // Abstand vom Rand
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // "Abbrechen"-Button
 | 
				
			||||||
 | 
					        Button cancelButton = buttonContainer.addChild(new Button("Abbrechen"));
 | 
				
			||||||
 | 
					        cancelButton.setPreferredSize(new Vector3f(120, 40, 0));
 | 
				
			||||||
 | 
					        cancelButton.addClickCommands(source -> goBackToStartMenu());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // "Spiel hosten"-Button
 | 
				
			||||||
 | 
					        Button hostButton = buttonContainer.addChild(new Button("Spiel hosten"));
 | 
				
			||||||
 | 
					        hostButton.setPreferredSize(new Vector3f(120, 40, 0));
 | 
				
			||||||
 | 
					        hostButton.addClickCommands(source -> {
 | 
				
			||||||
 | 
					        closeCreateGameMenu(); // Schließt das Menü
 | 
				
			||||||
 | 
					        app.startTestWorld(); // Startet die Testwelt in der Hauptanwendung
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // "Beitreten"-Button
 | 
				
			||||||
 | 
					        Button joinButton = buttonContainer.addChild(new Button("Beitreten"));
 | 
				
			||||||
 | 
					        joinButton.setPreferredSize(new Vector3f(120, 40, 0));
 | 
				
			||||||
 | 
					        // joinButton.addClickCommands(source -> joinGame()); // Placeholder for joining logic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Zentrierung des Containers
 | 
				
			||||||
 | 
					        menuContainer.setLocalTranslation(
 | 
				
			||||||
 | 
					            (app.getCamera().getWidth() - menuContainer.getPreferredSize().x) / 2,
 | 
				
			||||||
 | 
					            (app.getCamera().getHeight() + menuContainer.getPreferredSize().y) / 2,
 | 
				
			||||||
 | 
					            1  // Höhere Z-Ebene für den Vordergrund
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        app.getGuiNode().attachChild(menuContainer);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Lädt das Hintergrundbild und fügt es als geometrische Ebene hinzu.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void addBackgroundImage() {
 | 
				
			||||||
 | 
					        Texture backgroundImage = app.getAssetManager().loadTexture("Pictures/unibw-Bib2.png");
 | 
				
			||||||
 | 
					        Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
 | 
				
			||||||
 | 
					        background = new Geometry("Background", quad);
 | 
				
			||||||
 | 
					        Material backgroundMaterial = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
 | 
				
			||||||
 | 
					        backgroundMaterial.setTexture("ColorMap", backgroundImage);
 | 
				
			||||||
 | 
					        background.setMaterial(backgroundMaterial);
 | 
				
			||||||
 | 
					        background.setLocalTranslation(0, 0, -1); // Hintergrundebene
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        app.getGuiNode().attachChild(background);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Geht zum Startmenü zurück, wenn "Abbrechen" angeklickt wird.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void goBackToStartMenu() {
 | 
				
			||||||
 | 
					        app.getGuiNode().detachChild(menuContainer);
 | 
				
			||||||
 | 
					        app.getGuiNode().detachChild(background); // Entfernt das Hintergrundbild
 | 
				
			||||||
 | 
					        StartMenu.createStartMenu(app);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * Link zwischen createGame und TestWorld
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private void startTestWorld() {
 | 
				
			||||||
 | 
					        // Entfernt das Menü
 | 
				
			||||||
 | 
					        app.getGuiNode().detachChild(menuContainer);
 | 
				
			||||||
 | 
					        app.getGuiNode().detachChild(background);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Startet die Testszene
 | 
				
			||||||
 | 
					        TestWorld.startTestWorld();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void closeCreateGameMenu() {
 | 
				
			||||||
 | 
					        app.getGuiNode().detachChild(menuContainer); // Entfernt den Menü-Container
 | 
				
			||||||
 | 
					        app.getGuiNode().detachChild(background); // Entfernt das Hintergrundbild
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -5,6 +5,7 @@ import com.jme3.math.ColorRGBA;
 | 
				
			|||||||
import com.simsilica.lemur.Button;
 | 
					import com.simsilica.lemur.Button;
 | 
				
			||||||
import com.simsilica.lemur.Label;
 | 
					import com.simsilica.lemur.Label;
 | 
				
			||||||
import com.simsilica.lemur.style.ElementId;
 | 
					import com.simsilica.lemur.style.ElementId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pp.dialog.Dialog;
 | 
					import pp.dialog.Dialog;
 | 
				
			||||||
import pp.monopoly.client.MonopolyApp;
 | 
					import pp.monopoly.client.MonopolyApp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,55 +1,38 @@
 | 
				
			|||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
// Programming project code
 | 
					 | 
				
			||||||
// UniBw M, 2022, 2023, 2024
 | 
					 | 
				
			||||||
// www.unibw.de/inf2
 | 
					 | 
				
			||||||
// (c) Mark Minas (mark.minas@unibw.de)
 | 
					 | 
				
			||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package pp.monopoly.client.gui;
 | 
					package pp.monopoly.client.gui;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.jme3.material.Material;
 | 
					import com.jme3.material.Material;
 | 
				
			||||||
import com.jme3.material.RenderState.BlendMode;
 | 
					import com.jme3.material.RenderState.BlendMode;
 | 
				
			||||||
import com.jme3.math.ColorRGBA;
 | 
					import com.jme3.math.ColorRGBA;
 | 
				
			||||||
import com.jme3.math.Vector2f;
 | 
					 | 
				
			||||||
import com.jme3.math.Vector3f;
 | 
					 | 
				
			||||||
import com.jme3.scene.Geometry;
 | 
					import com.jme3.scene.Geometry;
 | 
				
			||||||
import com.jme3.scene.Node;
 | 
					import com.jme3.scene.Node;
 | 
				
			||||||
import com.jme3.scene.Spatial.CullHint;
 | 
					import com.jme3.scene.Spatial.CullHint;
 | 
				
			||||||
import com.jme3.scene.shape.Quad;
 | 
					import com.jme3.scene.shape.Quad;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pp.monopoly.client.MonopolyApp;
 | 
					import pp.monopoly.client.MonopolyApp;
 | 
				
			||||||
import pp.monopoly.model.IntPoint;
 | 
					 | 
				
			||||||
import pp.monopoly.model.Board;
 | 
					import pp.monopoly.model.Board;
 | 
				
			||||||
import pp.util.FloatPoint;
 | 
					 | 
				
			||||||
import pp.util.Position;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Represents the visual view of a {@link Board}, used to display the map structure such as the player's map, harbor,
 | 
					 * Represents the visual view of a {@link Board}, used to display the map structure and elements.
 | 
				
			||||||
 * and opponent's map. This class handles the graphical representation of the map, including background setup, grid lines,
 | 
					 * This class handles the graphical representation of the board, including background setup and grid lines.
 | 
				
			||||||
 * and interaction between the model and the view.
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class MapView {
 | 
					class MapView {
 | 
				
			||||||
    private static final float FIELD_SIZE = 40f;
 | 
					    private static final float FIELD_SIZE = 40f;
 | 
				
			||||||
    private static final float GRID_LINE_WIDTH = 2f;
 | 
					 | 
				
			||||||
    private static final float BACKGROUND_DEPTH = -4f;
 | 
					    private static final float BACKGROUND_DEPTH = -4f;
 | 
				
			||||||
    private static final float GRID_DEPTH = -1f;
 | 
					 | 
				
			||||||
    private static final ColorRGBA BACKGROUND_COLOR = new ColorRGBA(0, 0.05f, 0.05f, 0.5f);
 | 
					    private static final ColorRGBA BACKGROUND_COLOR = new ColorRGBA(0, 0.05f, 0.05f, 0.5f);
 | 
				
			||||||
    private static final ColorRGBA GRID_COLOR = ColorRGBA.Green;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Reference to the main application and the ship map being visualized
 | 
					 | 
				
			||||||
    private final MonopolyApp app;
 | 
					    private final MonopolyApp app;
 | 
				
			||||||
    private final Node mapNode = new Node("map"); // NON-NLS
 | 
					    private final Node mapNode = new Node("map");
 | 
				
			||||||
    private final Board map;
 | 
					    private final Board board;
 | 
				
			||||||
    private final MapViewSynchronizer synchronizer;
 | 
					    private final MapViewSynchronizer synchronizer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Constructs a new MapView for a given {@link Board} and {@link MonopolyApp}.
 | 
					     * Constructs a new MapView for a given {@link Board} and {@link MonopolyApp}.
 | 
				
			||||||
     * Initializes the view by setting up the background and registering a synchronizer to listen to changes in the map.
 | 
					 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param map the ship map to visualize
 | 
					     * @param board the board to visualize
 | 
				
			||||||
     * @param app the main application instance
 | 
					     * @param app   the main application instance
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    MapView(Board map, MonopolyApp app) {
 | 
					    MapView(Board board, MonopolyApp app) {
 | 
				
			||||||
        this.map = map;
 | 
					        this.board = board;
 | 
				
			||||||
        this.app = app;
 | 
					        this.app = app;
 | 
				
			||||||
        this.synchronizer = new MapViewSynchronizer(this);
 | 
					        this.synchronizer = new MapViewSynchronizer(this);
 | 
				
			||||||
        setupBackground();
 | 
					        setupBackground();
 | 
				
			||||||
@@ -57,65 +40,26 @@ class MapView {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Unregisters the {@link MapViewSynchronizer} from the listener list of the ClientGameLogic,
 | 
					     * Unregisters the {@link MapViewSynchronizer} from listening to board changes.
 | 
				
			||||||
     * stopping the view from receiving updates when the underlying {@link Board} changes.
 | 
					 | 
				
			||||||
     * After calling this method, this MapView instance should no longer be used.
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    void unregister() {
 | 
					    void unregister() {
 | 
				
			||||||
        app.getGameLogic().removeListener(synchronizer);
 | 
					        app.getGameLogic().removeListener(synchronizer);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Gets the {@link Board} associated with this view.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return the ship map
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public Board getMap() {
 | 
					 | 
				
			||||||
        return map;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Gets the {@link MonopolyApp} instance associated with this view.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return the main application instance
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public MonopolyApp getApp() {
 | 
					 | 
				
			||||||
        return app;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Sets up the background of the map view using a quad geometry.
 | 
					     * Sets up the background of the map view using a quad geometry.
 | 
				
			||||||
     * The background is configured with a semi-transparent color and placed at a specific depth.
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private void setupBackground() {
 | 
					    private void setupBackground() {
 | 
				
			||||||
        final Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md"); // NON-NLS
 | 
					        Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
 | 
				
			||||||
        mat.setColor("Color", BACKGROUND_COLOR); // NON-NLS
 | 
					        mat.setColor("Color", BACKGROUND_COLOR);
 | 
				
			||||||
        mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
 | 
					        mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
 | 
				
			||||||
        final Position corner = modelToView(map.getWidth(), map.getHeight());
 | 
					        Geometry background = new Geometry("MapBackground", new Quad(board.getWidth() * FIELD_SIZE, board.getHeight() * FIELD_SIZE));
 | 
				
			||||||
        final Geometry background = new Geometry("MapBackground", new Quad(corner.getX(), corner.getY()));
 | 
					 | 
				
			||||||
        background.setMaterial(mat);
 | 
					        background.setMaterial(mat);
 | 
				
			||||||
        background.setLocalTranslation(0f, 0f, BACKGROUND_DEPTH);
 | 
					        background.setLocalTranslation(0f, 0f, BACKGROUND_DEPTH);
 | 
				
			||||||
        background.setCullHint(CullHint.Never);
 | 
					        background.setCullHint(CullHint.Never);
 | 
				
			||||||
        mapNode.attachChild(background);
 | 
					        mapNode.attachChild(background);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Adds grid lines to the map view to visually separate the fields within the map.
 | 
					 | 
				
			||||||
     * The grid lines are drawn based on the dimensions of the ship map.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public void addGrid() {
 | 
					 | 
				
			||||||
        for (int x = 0; x <= map.getWidth(); x++) {
 | 
					 | 
				
			||||||
            final Position f = modelToView(x, 0);
 | 
					 | 
				
			||||||
            final Position t = modelToView(x, map.getHeight());
 | 
					 | 
				
			||||||
            mapNode.attachChild(gridLine(f, t));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        for (int y = 0; y <= map.getHeight(); y++) {
 | 
					 | 
				
			||||||
            final Position f = modelToView(0, y);
 | 
					 | 
				
			||||||
            final Position t = modelToView(map.getWidth(), y);
 | 
					 | 
				
			||||||
            mapNode.attachChild(gridLine(f, t));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Gets the root node containing all visual elements in this map view.
 | 
					     * Gets the root node containing all visual elements in this map view.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@@ -125,67 +69,7 @@ class MapView {
 | 
				
			|||||||
        return mapNode;
 | 
					        return mapNode;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    public Board getBoard() {
 | 
				
			||||||
     * Gets the total width of the map in view coordinates.
 | 
					        return board;
 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return the width of the map in view coordinates
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public float getWidth() {
 | 
					 | 
				
			||||||
        return FIELD_SIZE * map.getWidth();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Gets the total height of the map in view coordinates.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return the height of the map in view coordinates
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public float getHeight() {
 | 
					 | 
				
			||||||
        return FIELD_SIZE * map.getHeight();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Converts coordinates from view coordinates to model coordinates.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param x the x-coordinate in view space
 | 
					 | 
				
			||||||
     * @param y the y-coordinate in view space
 | 
					 | 
				
			||||||
     * @return the corresponding model coordinates as an {@link IntPoint}
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public IntPoint viewToModel(float x, float y) {
 | 
					 | 
				
			||||||
        return new IntPoint((int) Math.floor(x / FIELD_SIZE), (int) Math.floor(y / FIELD_SIZE));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Converts coordinates from model coordinates to view coordinates.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param x the x-coordinate in model space
 | 
					 | 
				
			||||||
     * @param y the y-coordinate in model space
 | 
					 | 
				
			||||||
     * @return the corresponding view coordinates as a {@link Position}
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public Position modelToView(float x, float y) {
 | 
					 | 
				
			||||||
        return new FloatPoint(x * FIELD_SIZE, y * FIELD_SIZE);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Converts the mouse position to model coordinates.
 | 
					 | 
				
			||||||
     * This method takes into account the map's transformation in the 3D scene.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param pos the 2D vector representing the mouse position in the view
 | 
					 | 
				
			||||||
     * @return the corresponding model coordinates as an {@link IntPoint}
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public IntPoint mouseToModel(Vector2f pos) {
 | 
					 | 
				
			||||||
        final Vector3f world = new Vector3f(pos.getX(), pos.getY(), 0f);
 | 
					 | 
				
			||||||
        final Vector3f view = mapNode.getWorldTransform().transformInverseVector(world, null);
 | 
					 | 
				
			||||||
        return viewToModel(view.getX(), view.getY());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Creates a visual representation of a grid line between two positions.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param p1 the start position of the grid line
 | 
					 | 
				
			||||||
     * @param p2 the end position of the grid line
 | 
					 | 
				
			||||||
     * @return a {@link Geometry} representing the grid line
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private Geometry gridLine(Position p1, Position p2) {
 | 
					 | 
				
			||||||
        return app.getDraw().makeFatLine(p1, p2, GRID_DEPTH, GRID_COLOR, GRID_LINE_WIDTH);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,63 +1,36 @@
 | 
				
			|||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
// Programming project code
 | 
					 | 
				
			||||||
// UniBw M, 2022, 2023, 2024
 | 
					 | 
				
			||||||
// www.unibw.de/inf2
 | 
					 | 
				
			||||||
// (c) Mark Minas (mark.minas@unibw.de)
 | 
					 | 
				
			||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package pp.monopoly.client.gui;
 | 
					package pp.monopoly.client.gui;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.jme3.math.ColorRGBA;
 | 
					 | 
				
			||||||
import com.jme3.scene.Geometry;
 | 
					 | 
				
			||||||
import com.jme3.scene.Node;
 | 
					 | 
				
			||||||
import com.jme3.scene.Spatial;
 | 
					 | 
				
			||||||
import pp.util.Position;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Synchronizes the visual representation of the ship map with the game model.
 | 
					 * Synchronizes the visual representation of the board with the game model.
 | 
				
			||||||
 * It handles the rendering of ships and shots on the map view, updating the view
 | 
					 * Handles updates for items on the board.
 | 
				
			||||||
 * whenever changes occur in the model.
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class MapViewSynchronizer extends BoardSynchronizer {
 | 
					class MapViewSynchronizer extends BoardSynchronizer {
 | 
				
			||||||
    // Constants for rendering properties
 | 
					 | 
				
			||||||
    private static final float SHIP_LINE_WIDTH = 6f;
 | 
					 | 
				
			||||||
    private static final float SHOT_DEPTH = -2f;
 | 
					 | 
				
			||||||
    private static final float SHIP_DEPTH = 0f;
 | 
					 | 
				
			||||||
    private static final float INDENT = 4f;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Colors used for different visual elements
 | 
					 | 
				
			||||||
    private static final ColorRGBA HIT_COLOR = ColorRGBA.Red;
 | 
					 | 
				
			||||||
    private static final ColorRGBA MISS_COLOR = ColorRGBA.Blue;
 | 
					 | 
				
			||||||
    private static final ColorRGBA SHIP_BORDER_COLOR = ColorRGBA.White;
 | 
					 | 
				
			||||||
    private static final ColorRGBA PREVIEW_COLOR = ColorRGBA.Gray;
 | 
					 | 
				
			||||||
    private static final ColorRGBA ERROR_COLOR = ColorRGBA.Red;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // The MapView associated with this synchronizer
 | 
					 | 
				
			||||||
    private final MapView view;
 | 
					    private final MapView view;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Constructs a new MapViewSynchronizer for the given MapView.
 | 
					     * Constructs a new MapViewSynchronizer for the given MapView.
 | 
				
			||||||
     * Initializes the synchronizer and adds existing elements from the model to the view.
 | 
					 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param view the MapView to synchronize with the game model
 | 
					     * @param view the MapView to synchronize with the game model
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public MapViewSynchronizer(MapView view) {
 | 
					    public MapViewSynchronizer(MapView view) {
 | 
				
			||||||
        super(view.getMap(), view.getNode());
 | 
					        super(view.getBoard(), view.getNode());
 | 
				
			||||||
        this.view = view;
 | 
					        this.view = view;
 | 
				
			||||||
        addExisting();
 | 
					        addExisting();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Creates a line geometry representing part of the ship's border.
 | 
					     * Enables the state by performing initial setup, such as adding any items to the view.
 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param x1    the starting x-coordinate of the line
 | 
					 | 
				
			||||||
     * @param y1    the starting y-coordinate of the line
 | 
					 | 
				
			||||||
     * @param x2    the ending x-coordinate of the line
 | 
					 | 
				
			||||||
     * @param y2    the ending y-coordinate of the line
 | 
					 | 
				
			||||||
     * @param color the color of the line
 | 
					 | 
				
			||||||
     * @return a Geometry representing the line
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private Geometry shipLine(float x1, float y1, float x2, float y2, ColorRGBA color) {
 | 
					    
 | 
				
			||||||
        return view.getApp().getDraw().makeFatLine(x1, y1, x2, y2, SHIP_DEPTH, color, SHIP_LINE_WIDTH);
 | 
					    protected void enableState() {
 | 
				
			||||||
 | 
					        // Platz für zusätzliche Initialisierungen
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Disables the state by clearing the view.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    protected void disableState() {
 | 
				
			||||||
 | 
					        view.getNode().detachAllChildren(); // Entfernt alle visuellen Elemente vom Knoten
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,95 @@
 | 
				
			|||||||
 | 
					package pp.monopoly.client.gui;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.jme3.material.Material;
 | 
				
			||||||
 | 
					import com.jme3.material.RenderState.BlendMode;
 | 
				
			||||||
 | 
					import com.jme3.math.ColorRGBA;
 | 
				
			||||||
 | 
					import com.jme3.scene.Geometry;
 | 
				
			||||||
 | 
					import com.jme3.scene.shape.Quad;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.Button;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.Checkbox;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.Container;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.Label;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.Slider;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.component.QuadBackgroundComponent;
 | 
				
			||||||
 | 
					import com.simsilica.lemur.style.ElementId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import pp.dialog.Dialog;
 | 
				
			||||||
 | 
					import pp.monopoly.client.MonopolyApp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * SettingsMenu ist ein Overlay-Menü, das durch ESC aufgerufen werden kann.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class SettingsMenu extends Dialog {
 | 
				
			||||||
 | 
					    private final MonopolyApp app;
 | 
				
			||||||
 | 
					    private final Geometry overlayBackground;
 | 
				
			||||||
 | 
					    private final Container settingsContainer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public SettingsMenu(MonopolyApp app) {
 | 
				
			||||||
 | 
					        super(app.getDialogManager());
 | 
				
			||||||
 | 
					        this.app = app;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Halbtransparentes Overlay hinzufügen
 | 
				
			||||||
 | 
					        overlayBackground = createOverlayBackground();
 | 
				
			||||||
 | 
					        app.getGuiNode().attachChild(overlayBackground);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Hauptcontainer für das Menü
 | 
				
			||||||
 | 
					        settingsContainer = new Container();
 | 
				
			||||||
 | 
					        settingsContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.1f, 0.1f, 0.1f, 0.9f)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Titel
 | 
				
			||||||
 | 
					        Label settingsTitle = settingsContainer.addChild(new Label("Einstellungen", new ElementId("settings-title")));
 | 
				
			||||||
 | 
					        settingsTitle.setFontSize(48);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Effekt-Sound: Slider und Checkbox
 | 
				
			||||||
 | 
					        Container effectSoundContainer = settingsContainer.addChild(new Container());
 | 
				
			||||||
 | 
					        effectSoundContainer.addChild(new Label("Effekt Sound", new ElementId("label")));
 | 
				
			||||||
 | 
					        effectSoundContainer.addChild(new Slider());
 | 
				
			||||||
 | 
					        effectSoundContainer.addChild(new Checkbox("Aktivieren")).setChecked(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Hintergrundmusik: Slider und Checkbox
 | 
				
			||||||
 | 
					        Container backgroundMusicContainer = settingsContainer.addChild(new Container());
 | 
				
			||||||
 | 
					        backgroundMusicContainer.addChild(new Label("Hintergrund Musik", new ElementId("label")));
 | 
				
			||||||
 | 
					        backgroundMusicContainer.addChild(new Slider());
 | 
				
			||||||
 | 
					        backgroundMusicContainer.addChild(new Checkbox("Aktivieren")).setChecked(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Beenden-Button
 | 
				
			||||||
 | 
					        Button quitButton = settingsContainer.addChild(new Button("Beenden", new ElementId("menu-button")));
 | 
				
			||||||
 | 
					        quitButton.setFontSize(32);
 | 
				
			||||||
 | 
					        quitButton.addClickCommands(source -> app.stop());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Zentriere das Menü
 | 
				
			||||||
 | 
					        settingsContainer.setLocalTranslation(
 | 
				
			||||||
 | 
					            (app.getCamera().getWidth() - settingsContainer.getPreferredSize().x) / 2,
 | 
				
			||||||
 | 
					            (app.getCamera().getHeight() + settingsContainer.getPreferredSize().y) / 2,
 | 
				
			||||||
 | 
					            1
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        app.getGuiNode().attachChild(settingsContainer);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Erstellt einen halbtransparenten Hintergrund für das Menü.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return Geometrie des Overlays
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private Geometry createOverlayBackground() {
 | 
				
			||||||
 | 
					        Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
 | 
				
			||||||
 | 
					        Geometry overlay = new Geometry("Overlay", quad);
 | 
				
			||||||
 | 
					        Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
 | 
				
			||||||
 | 
					        material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Halbtransparent
 | 
				
			||||||
 | 
					        material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
 | 
				
			||||||
 | 
					        overlay.setMaterial(material);
 | 
				
			||||||
 | 
					        overlay.setLocalTranslation(0, 0, 0);
 | 
				
			||||||
 | 
					        return overlay;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Schließt das Menü und entfernt die GUI-Elemente.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void close() {
 | 
				
			||||||
 | 
					        app.getGuiNode().detachChild(settingsContainer);
 | 
				
			||||||
 | 
					        app.getGuiNode().detachChild(overlayBackground);
 | 
				
			||||||
 | 
					        app.setSettingsMenuOpen(false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					package pp.monopoly.client.gui;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.jme3.app.SimpleApplication;
 | 
				
			||||||
 | 
					import com.jme3.material.Material;
 | 
				
			||||||
 | 
					import com.jme3.math.Vector3f;
 | 
				
			||||||
 | 
					import com.jme3.scene.Geometry;
 | 
				
			||||||
 | 
					import com.jme3.scene.shape.Box;
 | 
				
			||||||
 | 
					import com.jme3.texture.Texture;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * TestWorld zeigt eine einfache Szene mit einem texturierten Quadrat.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class TestWorld extends SimpleApplication {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void simpleInitApp() {
 | 
				
			||||||
 | 
					        // Erstelle ein Quadrat
 | 
				
			||||||
 | 
					        Box box = new Box(1, 0.01f, 1);  // Dünnes Quadrat für die Textur
 | 
				
			||||||
 | 
					        Geometry geom = new Geometry("Box", box);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Setze das Material mit Textur
 | 
				
			||||||
 | 
					        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
 | 
				
			||||||
 | 
					        Texture texture = assetManager.loadTexture("Pictures/board.png"); // Ersetze durch den Pfad zum gewünschten Bild
 | 
				
			||||||
 | 
					        mat.setTexture("ColorMap", texture);
 | 
				
			||||||
 | 
					        geom.setMaterial(mat);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Füge das Quadrat zur Szene hinzu
 | 
				
			||||||
 | 
					        rootNode.attachChild(geom);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Setze die Kameraposition, um das Quadrat zu fokussieren
 | 
				
			||||||
 | 
					        cam.setLocation(new Vector3f(0, 0, 3));  // Kamera auf der Z-Achse, nah am Quadrat
 | 
				
			||||||
 | 
					        cam.lookAt(geom.getLocalTranslation(), Vector3f.UNIT_Y);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void startTestWorld() {
 | 
				
			||||||
 | 
					        TestWorld testWorldApp = new TestWorld();
 | 
				
			||||||
 | 
					        testWorldApp.start();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					package pp.monopoly.client.gui;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.jme3.app.SimpleApplication;
 | 
				
			||||||
 | 
					import com.jme3.material.Material;
 | 
				
			||||||
 | 
					import com.jme3.math.Vector3f;
 | 
				
			||||||
 | 
					import com.jme3.scene.Geometry;
 | 
				
			||||||
 | 
					import com.jme3.scene.shape.Box;
 | 
				
			||||||
 | 
					import com.jme3.texture.Texture;
 | 
				
			||||||
 | 
					import com.jme3.system.JmeCanvasContext;
 | 
				
			||||||
 | 
					import com.jme3.system.AppSettings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.swing.*;
 | 
				
			||||||
 | 
					import java.awt.*;
 | 
				
			||||||
 | 
					import java.awt.event.ActionEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class TestWorldWithMenu extends SimpleApplication {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void createAndShowGUI() {
 | 
				
			||||||
 | 
					        // Create JFrame
 | 
				
			||||||
 | 
					        JFrame frame = new JFrame("Test World with Menu");
 | 
				
			||||||
 | 
					        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 | 
				
			||||||
 | 
					        frame.setLayout(new BorderLayout());
 | 
				
			||||||
 | 
					        frame.setSize(800, 600);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Create Menu Bar
 | 
				
			||||||
 | 
					        JMenuBar menuBar = new JMenuBar();
 | 
				
			||||||
 | 
					        JMenu fileMenu = new JMenu("File");
 | 
				
			||||||
 | 
					        JMenuItem exitItem = new JMenuItem(new AbstractAction("Exit") {
 | 
				
			||||||
 | 
					            @Override
 | 
				
			||||||
 | 
					            public void actionPerformed(ActionEvent e) {
 | 
				
			||||||
 | 
					                System.exit(0);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        fileMenu.add(exitItem);
 | 
				
			||||||
 | 
					        menuBar.add(fileMenu);
 | 
				
			||||||
 | 
					        frame.setJMenuBar(menuBar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Create Canvas for jMonkey
 | 
				
			||||||
 | 
					        AppSettings settings = new AppSettings(true);
 | 
				
			||||||
 | 
					        settings.setWidth(800);
 | 
				
			||||||
 | 
					        settings.setHeight(600);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TestWorldWithMenu app = new TestWorldWithMenu();
 | 
				
			||||||
 | 
					        app.setSettings(settings);
 | 
				
			||||||
 | 
					        app.createCanvas(); // Create a canvas for embedding
 | 
				
			||||||
 | 
					        JmeCanvasContext ctx = (JmeCanvasContext) app.getContext();
 | 
				
			||||||
 | 
					        ctx.setSystemListener(app);
 | 
				
			||||||
 | 
					        Canvas canvas = ctx.getCanvas();
 | 
				
			||||||
 | 
					        canvas.setSize(800, 600);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Add the canvas to JFrame
 | 
				
			||||||
 | 
					        frame.add(canvas, BorderLayout.CENTER);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Show the frame
 | 
				
			||||||
 | 
					        frame.setVisible(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Start the jMonkeyEngine application
 | 
				
			||||||
 | 
					        app.startCanvas();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void simpleInitApp() {
 | 
				
			||||||
 | 
					        // Erstelle ein Quadrat
 | 
				
			||||||
 | 
					        Box box = new Box(1, 0.01f, 1);  // Dünnes Quadrat für die Textur
 | 
				
			||||||
 | 
					        Geometry geom = new Geometry("Box", box);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Setze das Material mit Textur
 | 
				
			||||||
 | 
					        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
 | 
				
			||||||
 | 
					        Texture texture = assetManager.loadTexture("Pictures/board.png"); // Replace with the path to your image
 | 
				
			||||||
 | 
					        mat.setTexture("ColorMap", texture);
 | 
				
			||||||
 | 
					        geom.setMaterial(mat);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Füge das Quadrat zur Szene hinzu
 | 
				
			||||||
 | 
					        rootNode.attachChild(geom);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Setze die Kameraposition, um das Quadrat zu fokussieren
 | 
				
			||||||
 | 
					        cam.setLocation(new Vector3f(0, 0, 3));  // Kamera auf der Z-Achse, nah am Quadrat
 | 
				
			||||||
 | 
					        cam.lookAt(geom.getLocalTranslation(), Vector3f.UNIT_Y);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								Projekte/monopoly/client/src/main/resources/Pictures/board.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Projekte/monopoly/client/src/main/resources/Pictures/board.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 857 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 750 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 7.1 MiB  | 
							
								
								
									
										
											BIN
										
									
								
								Projekte/monopoly/client/src/main/resources/icons/test.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Projekte/monopoly/client/src/main/resources/icons/test.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 4.2 KiB  | 
@@ -7,6 +7,13 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package pp.monopoly.game.client;
 | 
					package pp.monopoly.game.client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.File;
 | 
				
			||||||
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.lang.System.Logger;
 | 
				
			||||||
 | 
					import java.lang.System.Logger.Level;
 | 
				
			||||||
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pp.monopoly.message.client.ClientMessage;
 | 
					import pp.monopoly.message.client.ClientMessage;
 | 
				
			||||||
import pp.monopoly.message.server.BuyPropertyResponse;
 | 
					import pp.monopoly.message.server.BuyPropertyResponse;
 | 
				
			||||||
import pp.monopoly.message.server.DiceResult;
 | 
					import pp.monopoly.message.server.DiceResult;
 | 
				
			||||||
@@ -20,8 +27,8 @@ import pp.monopoly.message.server.TimeOutWarning;
 | 
				
			|||||||
import pp.monopoly.message.server.TradeReply;
 | 
					import pp.monopoly.message.server.TradeReply;
 | 
				
			||||||
import pp.monopoly.message.server.TradeRequest;
 | 
					import pp.monopoly.message.server.TradeRequest;
 | 
				
			||||||
import pp.monopoly.message.server.ViewAssetsResponse;
 | 
					import pp.monopoly.message.server.ViewAssetsResponse;
 | 
				
			||||||
import pp.monopoly.model.IntPoint;
 | 
					 | 
				
			||||||
import pp.monopoly.model.Board;
 | 
					import pp.monopoly.model.Board;
 | 
				
			||||||
 | 
					import pp.monopoly.model.IntPoint;
 | 
				
			||||||
import pp.monopoly.notification.ClientStateEvent;
 | 
					import pp.monopoly.notification.ClientStateEvent;
 | 
				
			||||||
import pp.monopoly.notification.GameEvent;
 | 
					import pp.monopoly.notification.GameEvent;
 | 
				
			||||||
import pp.monopoly.notification.GameEventBroker;
 | 
					import pp.monopoly.notification.GameEventBroker;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,13 +7,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package pp.monopoly.game.client;
 | 
					package pp.monopoly.game.client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pp.monopoly.MonopolyConfig;
 | 
					 | 
				
			||||||
import pp.monopoly.model.IntPoint;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.io.File;
 | 
					import java.io.File;
 | 
				
			||||||
import java.util.ArrayList;
 | 
					
 | 
				
			||||||
import java.util.Iterator;
 | 
					import pp.monopoly.MonopolyConfig;
 | 
				
			||||||
import java.util.List;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Class providing access to the Monopoly client configuration.
 | 
					 * Class providing access to the Monopoly client configuration.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,10 @@ import pp.monopoly.model.fields.PropertyField;
 | 
				
			|||||||
import java.lang.System.Logger;
 | 
					import java.lang.System.Logger;
 | 
				
			||||||
import java.lang.System.Logger.Level;
 | 
					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.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,15 +7,16 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package pp.monopoly.model;
 | 
					package pp.monopoly.model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pp.monopoly.notification.GameEvent;
 | 
					 | 
				
			||||||
import pp.monopoly.notification.GameEventBroker;
 | 
					 | 
				
			||||||
import pp.monopoly.notification.ItemAddedEvent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
import java.util.Collections;
 | 
					import java.util.Collections;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.stream.Stream;
 | 
					import java.util.stream.Stream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import pp.monopoly.notification.GameEvent;
 | 
				
			||||||
 | 
					import pp.monopoly.notification.GameEventBroker;
 | 
				
			||||||
 | 
					import pp.monopoly.notification.ItemAddedEvent;
 | 
				
			||||||
 | 
					import pp.monopoly.notification.ItemRemovedEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Represents a rectangular map that holds figures and registers houses, hotels
 | 
					 * Represents a rectangular map that holds figures and registers houses, hotels
 | 
				
			||||||
 * It also supports event notification for game state changes such as item addition or removal.
 | 
					 * It also supports event notification for game state changes such as item addition or removal.
 | 
				
			||||||
@@ -65,7 +66,7 @@ public class Board {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    private void addItem(Item item) {
 | 
					    private void addItem(Item item) {
 | 
				
			||||||
        items.add(item);
 | 
					        items.add(item);
 | 
				
			||||||
        notifyListeners(new ItemAddedEvent(item, this));
 | 
					        notifyListeners((GameEvent) new ItemAddedEvent(item, null));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -75,7 +76,7 @@ public class Board {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public void remove(Item item) {
 | 
					    public void remove(Item item) {
 | 
				
			||||||
        items.remove(item);
 | 
					        items.remove(item);
 | 
				
			||||||
        notifyListeners(new ItemAddedEvent(item, this));
 | 
					        notifyListeners((GameEvent) new ItemRemovedEvent(item, null)); // Falls es ein entsprechendes ItemRemovedEvent gibt
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,10 +7,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package pp.monopoly.model;
 | 
					package pp.monopoly.model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.jme3.network.serializing.Serializable;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.Objects;
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.jme3.network.serializing.Serializable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Represents a point in the two-dimensional plane with integer coordinates.
 | 
					 * Represents a point in the two-dimensional plane with integer coordinates.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,29 +1,41 @@
 | 
				
			|||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
// Programming project code
 | 
					 | 
				
			||||||
// UniBw M, 2022, 2023, 2024
 | 
					 | 
				
			||||||
// www.unibw.de/inf2
 | 
					 | 
				
			||||||
// (c) Mark Minas (mark.minas@unibw.de)
 | 
					 | 
				
			||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package pp.monopoly.notification;
 | 
					package pp.monopoly.notification;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pp.monopoly.model.Item;
 | 
					 | 
				
			||||||
import pp.monopoly.model.Board;
 | 
					import pp.monopoly.model.Board;
 | 
				
			||||||
 | 
					import pp.monopoly.model.Item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Event when an item is added to a map.
 | 
					 * Event that is triggered when an item is added to a board.
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param item the added item
 | 
					 | 
				
			||||||
 * @param map  the map that got the additional item
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public record ItemAddedEvent(Item item, Board map) implements GameEvent {
 | 
					public class ItemAddedEvent {
 | 
				
			||||||
 | 
					    private final Item item;
 | 
				
			||||||
 | 
					    private final Board board;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Notifies the game event listener of this event.
 | 
					     * Constructs a new ItemAddedEvent.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param listener the game event listener
 | 
					     * @param item  the item that was added
 | 
				
			||||||
 | 
					     * @param board the board to which the item was added
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @Override
 | 
					    public ItemAddedEvent(Item item, Board board) {
 | 
				
			||||||
    public void notifyListener(GameEventListener listener) {
 | 
					        this.item = item;
 | 
				
			||||||
        listener.receivedEvent(this);
 | 
					        this.board = board;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets the item that was added.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return the added item
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public Item getItem() {
 | 
				
			||||||
 | 
					        return item;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets the board to which the item was added.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return the board
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public Board getBoard() {
 | 
				
			||||||
 | 
					        return board;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,22 +7,30 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package pp.monopoly.notification;
 | 
					package pp.monopoly.notification;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pp.monopoly.model.Item;
 | 
					 | 
				
			||||||
import pp.monopoly.model.Board;
 | 
					import pp.monopoly.model.Board;
 | 
				
			||||||
 | 
					import pp.monopoly.model.Item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Event when an item gets removed.
 | 
					 * Event when an item gets removed.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param item the destroyed item
 | 
					 * @param item the destroyed item
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public record ItemRemovedEvent(Item item, Board map) implements GameEvent {
 | 
					public class ItemRemovedEvent {
 | 
				
			||||||
    /**
 | 
					    private final Item item;
 | 
				
			||||||
     * Notifies the game event listener of this event.
 | 
					    private final Board board;
 | 
				
			||||||
     *
 | 
					
 | 
				
			||||||
     * @param listener the game event listener
 | 
					    public ItemRemovedEvent(Item item, Board board) {
 | 
				
			||||||
     */
 | 
					        this.item = item;
 | 
				
			||||||
    @Override
 | 
					        this.board = board;
 | 
				
			||||||
    public void notifyListener(GameEventListener listener) {
 | 
					    }
 | 
				
			||||||
        listener.receivedEvent(this);
 | 
					
 | 
				
			||||||
 | 
					    public Item getItem() {
 | 
				
			||||||
 | 
					        return item;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Board getBoard() {
 | 
				
			||||||
 | 
					        return board;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,26 +1,25 @@
 | 
				
			|||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
// Programming project code
 | 
					 | 
				
			||||||
// UniBw M, 2022, 2023, 2024
 | 
					 | 
				
			||||||
// www.unibw.de/inf2
 | 
					 | 
				
			||||||
// (c) Mark Minas (mark.minas@unibw.de)
 | 
					 | 
				
			||||||
////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package pp.monopoly.notification;
 | 
					package pp.monopoly.notification;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Event when an item is added to a map.
 | 
					 * Event when a sound needs to be played.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param sound the sound to be played
 | 
					 * @param soundFileName the sound file to be played
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public record SoundEvent(Sound sound) implements GameEvent {
 | 
					public class SoundEvent implements GameEvent {
 | 
				
			||||||
 | 
					    private final String soundFileName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public SoundEvent(Sound sound) {
 | 
				
			||||||
 | 
					        this.soundFileName = sound.getFileName(); // Angenommen, Sound hat eine Methode getFileName()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String getSoundFileName() {
 | 
				
			||||||
 | 
					        return soundFileName;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Notifies the game event listener of this event.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param listener the game event listener
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void notifyListener(GameEventListener listener) {
 | 
					    public void notifyListener(GameEventListener listener) {
 | 
				
			||||||
        listener.receivedEvent(this);
 | 
					        listener.receivedEvent(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,3 +40,4 @@ dialog.question=Question
 | 
				
			|||||||
port.must.be.integer=Port must be an integer number
 | 
					port.must.be.integer=Port must be an integer number
 | 
				
			||||||
map.doesnt.fit=The map doesn't fit to this game
 | 
					map.doesnt.fit=The map doesn't fit to this game
 | 
				
			||||||
client.server-start=Start server
 | 
					client.server-start=Start server
 | 
				
			||||||
 | 
					menu.settings=Open Settings
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user