Compare commits
	
		
			114 Commits
		
	
	
		
			logic
			...
			acc797f2ff
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | acc797f2ff | ||
|  | 853c32a5b8 | ||
|  | 72bef7143a | ||
|  | b1ed571950 | ||
|  | 1a75d6d6a8 | ||
|  | c990e7b562 | ||
|  | c87406f60e | ||
|  | 21914a1294 | ||
|  | a344145732 | ||
|  | a27ac31086 | ||
|  | 9a7f75b76b | ||
|  | 3e487c00d5 | ||
|  | 4820b8cf46 | ||
|  | caa4cb5262 | ||
|  | 1b2a7d73b5 | ||
|  | 55778dbcea | ||
|  | 422faec281 | ||
|  | dcf10e0819 | ||
|  | 6b78733a5d | ||
|  | c124a99901 | ||
|  | d7df4002da | ||
|  | 8b0ef97a82 | ||
|  | 75d3bef5c8 | ||
|  | c2d5611ab9 | ||
|  | fb28f3fefc | ||
|  | 6a34dab00c | ||
|  | c7bd7d18b7 | ||
|  | 437114704a | ||
|  | 9b4cac4e56 | ||
|  | e780513b35 | ||
|  | d582c59a7d | ||
|  | 7d2c85f617 | ||
|  | 4a882bc4ac | ||
|  | 3c4eac1fcd | ||
|  | 75d5a15bdb | ||
|  | 17f121f7d1 | ||
|  | a66c570b51 | ||
|  | e1e7f2eaf6 | ||
|  | 46d2dce372 | ||
|  | c39f1f6d4c | ||
|  | 738b04f2d9 | ||
|  | ecba1c3135 | ||
|  | 748226f4ed | ||
|  | f658f53ba9 | ||
|  | 4a8304ee4f | ||
|  | 7fe9604338 | ||
|  | 7f09a6dae8 | ||
|  | 270129bc97 | ||
|  | 62ec6f6bef | ||
|  | b24c14900c | ||
|  | 44c55ce3a6 | ||
|  | 895bea048c | ||
|  | 885ab5bdc9 | ||
|  | c6355b2c09 | ||
|  | ada6bf3f24 | ||
|  | db471ac679 | ||
|  | 84059c4085 | ||
|  | 09b363f943 | ||
|  | fd347c7780 | ||
|  | b38a34efa5 | ||
|  | 10e24cf30e | ||
|  | 3369057afb | ||
|  | 7ada56e215 | ||
|  | 373b9e6d53 | ||
|  | 3de31de9f7 | ||
|  | 7252259ab3 | ||
|  | f33c673a05 | ||
|  | 65a7958b66 | ||
|  | 91e4df7478 | ||
|  | 399606d9a0 | ||
|  | 559afcaffd | ||
|  | 15f5f91ddb | ||
|  | 067a8063a5 | ||
|  | 35e367ba24 | ||
|  | fe68d991fc | ||
|  | 88dc633e8e | ||
|  | 0b9cbb0f5f | ||
|  | c3a33b4402 | ||
|  | e12f00aad6 | ||
|  | 47bac0185f | ||
|  | dafe1dab2a | ||
|  | 8ba4ea2819 | ||
|  | f6f708fd5b | ||
|  | 1203077aed | ||
|  | ddbf79c928 | ||
|  | aa47dd579f | ||
|  | cdce478d77 | ||
|  | f11f4a59f1 | ||
|  | d631e8df1e | ||
|  | af80d40700 | ||
|  | 3a6f8a945a | ||
|  | bb9727d54a | ||
|  | 7da8b3e545 | ||
|  | b6968df451 | ||
|  | aa986fb948 | ||
|  | 6e63de6e99 | ||
|  | 962ecd08fa | ||
|  | 580a26b3ea | ||
|  | 0cda6b5fa0 | ||
|  | cc8c3795b8 | ||
|  | 3c21165efb | ||
|  | 818fdf4670 | ||
|  | b7d679b492 | ||
|  | a42093df23 | ||
|  | 6157db51da | ||
|  | 843052989b | ||
|  | 8e01fa3192 | ||
|  | e2126a7ea7 | ||
|  | 0b46d14650 | ||
|  | 9e28deedf7 | ||
|  | 9c0172b413 | ||
|  | 2933d022aa | ||
|  | bdefb7193e | ||
|  | 69b68a6975 | 
| @@ -1,18 +0,0 @@ | ||||
| <component name="ProjectRunConfigurationManager"> | ||||
|     <configuration default="false" name="MonopolyApp (Mac)" type="Application" factoryName="Application" | ||||
|                    singleton="false"> | ||||
|         <option name="MAIN_CLASS_NAME" value="pp.monopoly.client.MonopolyApp"/> | ||||
|         <module name="Projekte.monopoly.client.main"/> | ||||
|         <option name="VM_PARAMETERS" value="-XstartOnFirstThread"/> | ||||
|         <option name="WORKING_DIRECTORY" value="$MODULE_WORKING_DIR$"/> | ||||
|         <extension name="coverage"> | ||||
|             <pattern> | ||||
|                 <option name="PATTERN" value="pp.monopoly.client.*"/> | ||||
|                 <option name="ENABLED" value="true"/> | ||||
|             </pattern> | ||||
|         </extension> | ||||
|         <method v="2"> | ||||
|             <option name="Make" enabled="true"/> | ||||
|         </method> | ||||
|     </configuration> | ||||
| </component> | ||||
| @@ -1,6 +1,5 @@ | ||||
| // Styling of Lemur components | ||||
| // For documentation, see: | ||||
| // For documentation, see: | ||||
| // https://github.com/jMonkeyEngine-Contributions/Lemur/wiki/Styling | ||||
|  | ||||
| import com.jme3.math.ColorRGBA | ||||
| @@ -12,6 +11,7 @@ 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.TbtQuadBackgroundComponent | ||||
|  | ||||
| def bgColor = color(1, 1, 1, 1) | ||||
| def buttonEnabledColor = color(0, 0, 0, 1) | ||||
| @@ -19,7 +19,7 @@ def buttonDisabledColor = color(0.8, 0.9, 1, 0.2) | ||||
| def buttonBgColor = color(1, 1, 1, 1) | ||||
| def sliderColor = color(0.6, 0.8, 0.8, 1) | ||||
| def sliderBgColor = color(0.5, 0.75, 0.75, 1) | ||||
| def gradientColor = color(1, 1, 1, 1) | ||||
| def gradientColor = color(0.5, 0.75, 0.85, 0.5) | ||||
| def tabbuttonEnabledColor = color(0.4, 0.45, 0.5, 1) | ||||
| def solidWhiteBackground = new QuadBackgroundComponent(new ColorRGBA(1, 1, 1, 1)) | ||||
| def greyBackground = new QuadBackgroundComponent(new ColorRGBA(0.1f, 0.1f, 0.1f, 1.0f)); | ||||
| @@ -30,8 +30,10 @@ def lightGrey = color(0.6, 0.6, 0.6, 1.0) | ||||
|  | ||||
|  | ||||
| def gradient = TbtQuadBackgroundComponent.create( | ||||
|         texture(name: "/com/simsilica/lemur/icons/bordered-gradient.png", generateMips: false), | ||||
|        1, 1, 1, 126, 126, 1f, false) | ||||
|         texture(name: "/com/simsilica/lemur/icons/bordered-gradient.png", | ||||
|                 generateMips: false), | ||||
|         1, 1, 1, 126, 126, | ||||
|         1f, false) | ||||
|  | ||||
| def doubleGradient = new QuadBackgroundComponent(gradientColor) | ||||
| doubleGradient.texture = texture(name: "/com/simsilica/lemur/icons/double-gradient-128.png", | ||||
| @@ -77,7 +79,6 @@ selector("header", "pp") { | ||||
|     textVAlignment = VAlignment.Center | ||||
| } | ||||
|  | ||||
| // Container Stil | ||||
| selector("container", "pp") { | ||||
|     background = solidWhiteBackground.clone() | ||||
|     background.setColor(bgColor) | ||||
| @@ -90,8 +91,8 @@ selector("toolbar") { | ||||
|  | ||||
| } | ||||
| selector("slider", "pp") { | ||||
|     insets = new Insets3f(5, 10, 5, 10) // Abstand | ||||
|     background = new QuadBackgroundComponent(sliderBgColor) | ||||
|     background = gradient.clone() | ||||
|     background.setColor(bgColor) | ||||
| } | ||||
|  | ||||
| def pressedCommand = new Command<Button>() { | ||||
| @@ -112,6 +113,30 @@ 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 = [ | ||||
|         (ButtonAction.Down)    : [pressedCommand], | ||||
|         (ButtonAction.Up)      : [pressedCommand], | ||||
|   | ||||
| @@ -1,8 +1,11 @@ | ||||
| package pp.monopoly.client; | ||||
| //////////////////////////////////////// | ||||
| // Programming project code | ||||
| // UniBw M, 2022, 2023, 2024 | ||||
| // www.unibw.de/inf2 | ||||
| // (c) Mark Minas (mark.minas@unibw.de) | ||||
| //////////////////////////////////////// | ||||
|  | ||||
| import java.lang.System.Logger; | ||||
| import java.lang.System.Logger.Level; | ||||
| import java.util.prefs.Preferences; | ||||
| package pp.monopoly.client; | ||||
|  | ||||
| import java.lang.System.Logger; | ||||
| import java.lang.System.Logger.Level; | ||||
| @@ -11,16 +14,17 @@ 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.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 static pp.util.PreferencesUtils.getPreferences; | ||||
|  | ||||
| /** | ||||
|  * An application state that plays sounds based on game events. | ||||
|  * An application state that plays sounds. | ||||
|  */ | ||||
| public class GameSound extends AbstractAppState implements GameEventListener { | ||||
|     private static final Logger LOGGER = System.getLogger(GameSound.class.getName()); | ||||
| @@ -67,6 +71,7 @@ public class GameSound extends AbstractAppState implements GameEventListener { | ||||
|  | ||||
|     /** | ||||
|      * 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. | ||||
|      */ | ||||
| @@ -74,15 +79,16 @@ public class GameSound extends AbstractAppState implements GameEventListener { | ||||
|     public void setEnabled(boolean enabled) { | ||||
|         if (isEnabled() == enabled) return; | ||||
|         super.setEnabled(enabled); | ||||
|         LOGGER.log(Level.INFO, "Sound enabled: {0}", enabled); | ||||
|         LOGGER.log(Level.INFO, "Sound enabled: {0}", enabled); //NON-NLS | ||||
|         PREFERENCES.putBoolean(ENABLED_PREF, enabled); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Initializes the sound effects for the game and stores the application reference. | ||||
|      * Initializes the sound effects for the game. | ||||
|      * Overrides {@link AbstractAppState#initialize(AppStateManager, Application)} | ||||
|      * | ||||
|      * @param stateManager The state manager | ||||
|      * @param app          The application instance | ||||
|      * @param app          The application | ||||
|      */ | ||||
|     @Override | ||||
|     public void initialize(AppStateManager stateManager, Application app) { | ||||
| @@ -103,16 +109,18 @@ public class GameSound extends AbstractAppState implements GameEventListener { | ||||
|     /** | ||||
|      * Loads a sound from the specified file. | ||||
|      * | ||||
|      * @param app  The application | ||||
|      * @param name The name of the sound file. | ||||
|      * @return The loaded AudioNode. | ||||
|      */ | ||||
|     private AudioNode loadSound(String name) { | ||||
|     private AudioNode loadSound(Application app, String name) { | ||||
|         try { | ||||
|             AudioNode sound = new AudioNode(app.getAssetManager(), name, AudioData.DataType.Buffer); | ||||
|             final AudioNode sound = new AudioNode(app.getAssetManager(), name, AudioData.DataType.Buffer); | ||||
|             sound.setLooping(false); | ||||
|             sound.setPositional(false); | ||||
|             return sound; | ||||
|         } catch (Exception ex) { | ||||
|         } | ||||
|         catch (AssetLoadException | AssetNotFoundException ex) { | ||||
|             LOGGER.log(Level.ERROR, ex.getMessage(), ex); | ||||
|         } | ||||
|         return null; | ||||
| @@ -231,4 +239,4 @@ public class GameSound extends AbstractAppState implements GameEventListener { | ||||
|             case BUTTON -> button(); | ||||
|         } | ||||
|     } | ||||
| }//heloo | ||||
| } | ||||
|   | ||||
| @@ -18,26 +18,16 @@ import com.jme3.input.controls.ActionListener; | ||||
| import com.jme3.input.controls.KeyTrigger; | ||||
| import com.jme3.input.controls.MouseButtonTrigger; | ||||
| import com.jme3.system.AppSettings; | ||||
| import com.jme3.texture.Texture; | ||||
| import com.simsilica.lemur.GuiGlobals; | ||||
| import com.simsilica.lemur.Label; | ||||
| import com.simsilica.lemur.style.BaseStyles; | ||||
| import pp.monopoly.game.client.MonopolyClient; | ||||
| import pp.monopoly.client.gui.SettingsMenu; | ||||
| import pp.monopoly.client.gui.StartMenu; | ||||
| import pp.monopoly.client.gui.TestWorld; | ||||
| import pp.monopoly.client.gui.popups.BuildingPropertyCard; | ||||
| import pp.monopoly.client.gui.popups.BuyCard; | ||||
| import pp.monopoly.client.gui.popups.EventCard; | ||||
| import pp.monopoly.client.gui.popups.FoodFieldCard; | ||||
| import pp.monopoly.client.gui.popups.GateFieldCard; | ||||
| 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.monopoly.notification.Sound; | ||||
| import pp.dialog.Dialog; | ||||
| import pp.dialog.DialogBuilder; | ||||
| import pp.dialog.DialogManager; | ||||
| import pp.graphics.Draw; | ||||
| @@ -129,17 +119,6 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga | ||||
|      */ | ||||
|     private final ActionListener escapeListener = (name, isPressed, tpf) -> escape(isPressed); | ||||
|  | ||||
|     //TODO temp for testing | ||||
|     private EventCard eventCard; | ||||
|     private BuildingPropertyCard buildingProperty; | ||||
|     private FoodFieldCard foodField; | ||||
|     private GateFieldCard gateField; | ||||
|     private BuyCard buyCard; | ||||
|     private boolean isBuyCardPopupOpen = false; | ||||
|     private final ActionListener BListener = (name, isPressed, tpf) -> handleB(isPressed); | ||||
|     private final ActionListener TListener = (name, isPressed, tpf) -> handleT(isPressed); | ||||
|     private TestWorld testWorld; | ||||
|  | ||||
|     static { | ||||
|         // Configure logging | ||||
|         LogManager manager = LogManager.getLogManager(); | ||||
| @@ -249,7 +228,6 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga | ||||
|     private void setupGui() { | ||||
|         GuiGlobals.initialize(this); | ||||
|         BaseStyles.loadStyleResources(STYLES_SCRIPT); | ||||
|         BaseStyles.loadGlassStyle(); | ||||
|         GuiGlobals.getInstance().getStyles().setDefaultStyle("pp"); //NON-NLS | ||||
|         final BitmapFont normalFont = assetManager.loadFont(FONT); //NON-NLS | ||||
|         topText = new BitmapText(normalFont); | ||||
| @@ -268,44 +246,8 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga | ||||
|         inputManager.addMapping(ESC, new KeyTrigger(KeyInput.KEY_ESCAPE)); | ||||
|         inputManager.addMapping(CLICK, new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); | ||||
|         inputManager.addListener(escapeListener, ESC); | ||||
|  | ||||
|         //TODO tmp for testing | ||||
|         inputManager.addMapping("B", new KeyTrigger(KeyInput.KEY_B)); | ||||
|         inputManager.addListener(BListener, "B"); | ||||
|         inputManager.addMapping("T", new KeyTrigger(KeyInput.KEY_T)); | ||||
|         inputManager.addListener(TListener, "T"); | ||||
|     } | ||||
|  | ||||
|     //logik zum wechselnden erscheinen und verschwinden beim drücken von B //TODO süäter entfernen | ||||
|     private void handleB(boolean isPressed) { | ||||
|         if (isPressed) { | ||||
|             Dialog tmp = new BuyCard(this); | ||||
|             if (eventCard != null && isBuyCardPopupOpen) { | ||||
|                 // Schließe das SettingsMenu | ||||
|                 System.out.println("Schließe BuyCardPopup..."); | ||||
|                 eventCard.close(); | ||||
|                 eventCard = null; | ||||
|                 tmp.open(); | ||||
|             } else { | ||||
|                 // Öffne das SettingsMenu | ||||
|                 System.out.println("Öffne BuyCardPopup..."); | ||||
|                 eventCard = new EventCard(this); | ||||
|                 eventCard.open(); | ||||
|                 dialogManager.close(tmp); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     //logik zum wechselnden erscheinen und verschwinden beim drücken von B //TODO süäter entfernen | ||||
|     private void handleT(boolean isPressed) { | ||||
|         if (isPressed) { | ||||
|             testWorld = new TestWorld(this); | ||||
|             testWorld.initializeScene(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * Initializes and attaches the necessary application states for the game. | ||||
|      */ | ||||
| @@ -353,11 +295,6 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga | ||||
|         super.simpleUpdate(tpf); | ||||
|         dialogManager.update(tpf); | ||||
|         logic.update(tpf); | ||||
|  | ||||
|         //TODO testing replace later | ||||
|         if (testWorld != null) { | ||||
|             testWorld.update(tpf); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -478,11 +415,8 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga | ||||
|         DialogBuilder.simple(dialogManager) | ||||
|                      .setTitle(lookup("dialog.question")) | ||||
|                      .setText(question) | ||||
|                      .setOkButton(lookup("button.yes"), d -> { | ||||
|                         getGameLogic().playSound(Sound.BUTTON); // Play sound | ||||
|                         yesAction.run(); // Execute the original yesAction | ||||
|                     }) | ||||
|                      .setNoButton(lookup("button.no"),  d -> getGameLogic().playSound(Sound.BUTTON)) | ||||
|                      .setOkButton(lookup("button.yes"), yesAction) | ||||
|                      .setNoButton(lookup("button.no")) | ||||
|                      .build() | ||||
|                      .open(); | ||||
|     } | ||||
| @@ -496,7 +430,7 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga | ||||
|         DialogBuilder.simple(dialogManager) | ||||
|                      .setTitle(lookup("dialog.error")) | ||||
|                      .setText(errorMessage) | ||||
|                      .setOkButton(lookup("button.ok"), d -> getGameLogic().playSound(Sound.BUTTON)) | ||||
|                      .setOkButton(lookup("button.ok")) | ||||
|                      .build() | ||||
|                      .open(); | ||||
|     } | ||||
|   | ||||
| @@ -3,10 +3,8 @@ package pp.monopoly.client.gui; | ||||
| import com.jme3.scene.Node; | ||||
| import com.jme3.scene.Spatial; | ||||
|  | ||||
|  | ||||
| import pp.monopoly.model.Board; | ||||
| import pp.monopoly.model.Item; | ||||
| import pp.monopoly.model.Item; | ||||
| import pp.monopoly.model.Visitor; | ||||
| import pp.monopoly.notification.GameEventListener; | ||||
| import pp.monopoly.notification.ItemAddedEvent; | ||||
| @@ -26,14 +24,10 @@ abstract class BoardSynchronizer extends ModelViewSynchronizer<Item> implements | ||||
|      * | ||||
|      * @param board the game board to synchronize | ||||
|      * @param root  the root node to which the view representations of the board items are attached | ||||
|      * @param board the game board to synchronize | ||||
|      * @param root  the root node to which the view representations of the board items are attached | ||||
|      */ | ||||
|     protected BoardSynchronizer(Board board, Node root) { | ||||
|     protected BoardSynchronizer(Board board, Node root) { | ||||
|         super(root); | ||||
|         this.board = board; | ||||
|         this.board = board; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -48,7 +42,6 @@ abstract class BoardSynchronizer extends ModelViewSynchronizer<Item> implements | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Adds the existing items from the board to the view during initialization. | ||||
|      * Adds the existing items from the board to the view during initialization. | ||||
|      */ | ||||
|     protected void addExisting() { | ||||
| @@ -56,36 +49,26 @@ abstract class BoardSynchronizer extends ModelViewSynchronizer<Item> implements | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handles the event when an item is removed from the board. | ||||
|      * Handles the event when an item is removed from the board. | ||||
|      * | ||||
|      * @param event the event indicating that an item has been removed from the board | ||||
|      * @param event the event indicating that an item has been removed from the board | ||||
|      */ | ||||
|     @Override | ||||
|     public void receivedEvent(ItemRemovedEvent event) { | ||||
|         if (board == event.getBoard()) { | ||||
|             delete(event.getItem()); | ||||
|         } | ||||
|         if (board == event.getBoard()) { | ||||
|             delete(event.getItem()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handles the event when an item is added to the board. | ||||
|      * Handles the event when an item is added to the board. | ||||
|      * | ||||
|      * @param event the event indicating that an item has been added to the board | ||||
|      * @param event the event indicating that an item has been added to the board | ||||
|      */ | ||||
|     @Override | ||||
|     public void receivedEvent(ItemAddedEvent event) { | ||||
|         if (board == event.getBoard()) { | ||||
|             add(event.getItem()); | ||||
|         } | ||||
|         if (board == event.getBoard()) { | ||||
|             add(event.getItem()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,64 +0,0 @@ | ||||
| package pp.monopoly.client.gui; | ||||
|  | ||||
| import com.jme3.material.Material; | ||||
| import com.jme3.math.ColorRGBA; | ||||
| import com.jme3.math.Vector3f; | ||||
| import com.jme3.scene.Geometry; | ||||
| import com.jme3.scene.shape.Quad; | ||||
| import com.jme3.texture.Texture; | ||||
| import com.simsilica.lemur.Axis; | ||||
| import com.simsilica.lemur.Container; | ||||
| import com.simsilica.lemur.Label; | ||||
| import com.simsilica.lemur.TextField; | ||||
| import com.simsilica.lemur.component.QuadBackgroundComponent; | ||||
| import com.simsilica.lemur.component.SpringGridLayout; | ||||
| import com.simsilica.lemur.style.ElementId; | ||||
| import pp.dialog.Dialog; | ||||
| import pp.monopoly.client.MonopolyApp; | ||||
|  | ||||
| public class ChoosePartner extends Dialog { | ||||
|  | ||||
|     private final MonopolyApp app; | ||||
|     private final Container menuContainer; | ||||
|     private Geometry background; | ||||
|  | ||||
|  | ||||
|     public ChoosePartner(MonopolyApp app) { | ||||
|         super(app.getDialogManager()); | ||||
|         this.app = app; | ||||
|  | ||||
|         // Hintergrundbild laden und hinzufügen | ||||
|         addBackgroundImage(); | ||||
|  | ||||
|         QuadBackgroundComponent translucentWhiteBackground = | ||||
|                 new QuadBackgroundComponent(new ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f)); | ||||
|  | ||||
|         menuContainer = new Container(new SpringGridLayout(Axis.Y, Axis.X)); | ||||
|         menuContainer.setPreferredSize(new Vector3f(1000, 600, 0)); // Fixed size of the container | ||||
|         menuContainer.setBackground(translucentWhiteBackground); | ||||
|  | ||||
|         // Create a smaller horizontal container for the label, input field, and spacers | ||||
|         Container horizontalContainer = menuContainer.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y))); | ||||
|         horizontalContainer.setPreferredSize(new Vector3f(600, 40, 0)); // Adjust container size | ||||
|         horizontalContainer.setBackground(null); | ||||
|  | ||||
|         Label title = horizontalContainer.addChild(new Label("Wähle deinen Handelspartner:", new ElementId("label-Bold"))); | ||||
|         title.setFontSize(40); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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); | ||||
|     } | ||||
| } | ||||
| @@ -25,7 +25,6 @@ import com.simsilica.lemur.component.SpringGridLayout; | ||||
|  | ||||
| import static pp.monopoly.Resources.lookup; | ||||
|  | ||||
| import com.simsilica.lemur.style.ElementId; | ||||
| import pp.monopoly.client.MonopolyApp; | ||||
| import pp.monopoly.client.NetworkSupport; | ||||
| import pp.monopoly.notification.Sound; | ||||
| @@ -66,7 +65,7 @@ public class CreateGameMenu extends Dialog { | ||||
|  | ||||
|         final MonopolyApp app = network.getApp(); | ||||
|  | ||||
|                 int screenWidth = app.getContext().getSettings().getWidth(); | ||||
|         int screenWidth = app.getContext().getSettings().getWidth(); | ||||
|         int screenHeight = app.getContext().getSettings().getHeight(); | ||||
|  | ||||
|         // Set up the background image | ||||
| @@ -79,7 +78,7 @@ public class CreateGameMenu extends Dialog { | ||||
|         background.setLocalTranslation(0, 0, -1); // Ensure it is behind other GUI elements | ||||
|         app.getGuiNode().attachChild(background); | ||||
|  | ||||
|         addChild(new Label("Spiel erstellen", new ElementId("header"))); //NON-NLS | ||||
|  | ||||
|         final Container input = new Container(new SpringGridLayout()); | ||||
|         input.addChild(new Label(lookup("host.name") + ":  ")); | ||||
|         input.addChild(host, 1); | ||||
| @@ -89,27 +88,27 @@ public class CreateGameMenu extends Dialog { | ||||
|         addChild(input); | ||||
|         // "Abbrechen"-Button | ||||
|         cancelButton.setPreferredSize(new Vector3f(120, 40, 0)); | ||||
|         cancelButton.addClickCommands(s -> ifTopDialog(() -> { | ||||
|             app.getGameLogic().playSound(Sound.BUTTON); | ||||
|             this.close(); | ||||
|             new StartMenu(network.getApp()).open(); | ||||
|         })); | ||||
|         cancelButton.addClickCommands(source -> close()); | ||||
|         addChild(cancelButton); | ||||
|         cancelButton.addClickCommands(s -> ifTopDialog(() -> { | ||||
|             this.close(); | ||||
|             new StartMenu(app); | ||||
|             app.getGameLogic().playSound(Sound.BUTTON); | ||||
|         })); | ||||
|  | ||||
|         // "Selber hosten"-Button | ||||
|         serverButton.addClickCommands(s -> ifTopDialog( () -> { | ||||
|             network.getApp().getGameLogic().playSound(Sound.BUTTON); | ||||
|         addChild(serverButton).addClickCommands(s -> ifTopDialog(() -> { | ||||
|             startServerInThread(); | ||||
|         }   )); | ||||
|         addChild(serverButton); | ||||
|             app.getGameLogic().playSound(Sound.BUTTON); | ||||
|         })); | ||||
|  | ||||
|         // "Beitreten"-Button | ||||
|         joinButton.setPreferredSize(new Vector3f(120, 40, 0)); | ||||
|         joinButton.addClickCommands(s -> ifTopDialog( () -> { | ||||
|             app.getGameLogic().playSound(Sound.BUTTON); | ||||
|             connect(); | ||||
|         })); | ||||
|         addChild(joinButton); | ||||
|         joinButton.addClickCommands(s -> ifTopDialog(() -> { | ||||
|             connect(); | ||||
|             app.getGameLogic().playSound(Sound.BUTTON); | ||||
|         })); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -156,7 +155,7 @@ public class CreateGameMenu extends Dialog { | ||||
|  | ||||
|     @Override | ||||
|     public void escape() { | ||||
|         new SettingsMenu(network.getApp()).open(); | ||||
|         close(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -219,6 +218,7 @@ public class CreateGameMenu extends Dialog { | ||||
|         try { | ||||
|             Thread.sleep(2000); | ||||
|         } catch (InterruptedException e) { | ||||
|             // TODO Auto-generated catch block | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|         connect(); | ||||
|   | ||||
| @@ -131,11 +131,11 @@ public class LobbyMenu extends Dialog { | ||||
|         buttonContainer.setBackground(null); | ||||
|         // Lower-left container for "Abbrechen" button | ||||
|         lowerLeftMenu = new Container(); | ||||
|         Button cancelButton = new Button("Beenden"); | ||||
|         Button cancelButton = new Button("Abbrechen"); | ||||
|         cancelButton.setPreferredSize(new Vector3f(200, 60, 0)); // Set size to match the appearance in the image | ||||
|         cancelButton.setFontSize(18); // Adjust font size | ||||
|         cancelButton.addClickCommands(s -> ifTopDialog(() -> { | ||||
|             app.closeApp(); | ||||
|             this.close(); | ||||
|             app.getGameLogic().playSound(Sound.BUTTON); | ||||
|         })); | ||||
|         lowerLeftMenu.addChild(cancelButton); | ||||
| @@ -217,7 +217,7 @@ public class LobbyMenu extends Dialog { | ||||
|  | ||||
|     @Override | ||||
|     public void escape() { | ||||
|         new SettingsMenu(app).open(); | ||||
|         super.close(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package pp.monopoly.client.gui; | ||||
|  | ||||
| import com.simsilica.lemur.Slider; | ||||
| import pp.monopoly.client.GameMusic; | ||||
| import pp.monopoly.client.GameSound; | ||||
|  | ||||
| public class SoundSlider extends Slider { | ||||
|   | ||||
| @@ -6,17 +6,12 @@ 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.Axis; | ||||
| import com.simsilica.lemur.Button; | ||||
| import com.simsilica.lemur.Container; | ||||
| import com.simsilica.lemur.HAlignment; | ||||
| import com.simsilica.lemur.Container; | ||||
| import com.simsilica.lemur.HAlignment; | ||||
| import com.simsilica.lemur.component.QuadBackgroundComponent; | ||||
| import com.simsilica.lemur.component.SpringGridLayout; | ||||
|  | ||||
| import com.simsilica.lemur.component.SpringGridLayout; | ||||
|  | ||||
| import pp.dialog.Dialog; | ||||
| import pp.monopoly.client.MonopolyApp; | ||||
| import pp.monopoly.notification.Sound; | ||||
| @@ -25,12 +20,12 @@ import pp.monopoly.notification.Sound; | ||||
|  * Constructs the startup menu dialog for the Monopoly application. | ||||
| import pp.monopoly.client.gui.GameMenu; | ||||
|  */ | ||||
|  */ | ||||
| public class StartMenu extends Dialog { | ||||
|     private final MonopolyApp app; | ||||
|     private Container logoContainer; | ||||
|     private Container unibwLogoContainer; | ||||
|  | ||||
|     /** | ||||
|      * Constructs the Startup Menu dialog for the Monopoly application. | ||||
|      * Constructs the Startup Menu dialog for the Monopoly application. | ||||
|      * | ||||
|      * @param app the MonopolyApp instance | ||||
| @@ -48,10 +43,8 @@ public class StartMenu extends Dialog { | ||||
|         Geometry background = new Geometry("Background", quad); | ||||
|         Material backgroundMaterial = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md"); | ||||
|         backgroundMaterial.setTexture("ColorMap", backgroundImage); | ||||
|         backgroundMaterial.setTexture("ColorMap", backgroundImage); | ||||
|         background.setMaterial(backgroundMaterial); | ||||
|         background.setLocalTranslation(0, 0, -1); // Ensure it is behind other GUI elements | ||||
|         background.setLocalTranslation(0, 0, -1); // Ensure it is behind other GUI elements | ||||
|         app.getGuiNode().attachChild(background); | ||||
|  | ||||
|         // Center container for title and play button | ||||
|   | ||||
| @@ -21,6 +21,7 @@ public class TestWorld { | ||||
|  | ||||
|     private final MonopolyApp app; | ||||
|     private CameraController cameraController; // Steuert die Kamera | ||||
|     private Geometry cube; // Spielfigur | ||||
|  | ||||
|     /** | ||||
|      * Konstruktor für TestWorld. | ||||
| @@ -40,6 +41,7 @@ public class TestWorld { | ||||
|  | ||||
|         setSkyColor(); // Setze den Himmel auf hellblau | ||||
|         createBoard(); // Erstelle das Spielfeld | ||||
|         createCube();  // Füge den Würfel hinzu | ||||
|  | ||||
|         // Erstelle den CameraController | ||||
|         cameraController = new CameraController( | ||||
| @@ -51,7 +53,7 @@ public class TestWorld { | ||||
|         ); | ||||
|  | ||||
|         // Füge die Toolbar hinzu | ||||
|         new Toolbar(app).open(); | ||||
|         new Toolbar(app, cube); | ||||
|          | ||||
|         cameraController.setPosition(0); | ||||
|     } | ||||
| @@ -91,4 +93,22 @@ public class TestWorld { | ||||
|  | ||||
|         app.getRootNode().attachChild(geom); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Erstellt den Würfel (Spielfigur) in der Szene. | ||||
|      */ | ||||
|     private void createCube() { | ||||
|         Box box = new Box(0.05f, 0.05f, 0.05f); // Kleinere Größe für Spielfigur | ||||
|         cube = new Geometry("Cube", box); | ||||
|  | ||||
|         // Setze das Material für den Würfel | ||||
|         Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md"); | ||||
|         mat.setColor("Color", ColorRGBA.Blue); // Blau gefärbter Würfel | ||||
|         cube.setMaterial(mat); | ||||
|  | ||||
|         // Setze den Startpunkt des Würfels | ||||
|         cube.setLocalTranslation(0.8999999f, 0.1f, -0.9f); | ||||
|  | ||||
|         app.getRootNode().attachChild(cube); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,80 +0,0 @@ | ||||
| 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); | ||||
|     } | ||||
| } | ||||
| @@ -5,15 +5,13 @@ import java.util.Random; | ||||
|  | ||||
| import com.jme3.font.BitmapText; | ||||
| import com.jme3.math.ColorRGBA; | ||||
| import com.jme3.math.Vector2f; | ||||
| import com.jme3.math.Vector3f; | ||||
| import com.jme3.scene.Geometry; | ||||
| import com.simsilica.lemur.*; | ||||
| import com.simsilica.lemur.component.IconComponent; | ||||
| import com.simsilica.lemur.component.QuadBackgroundComponent; | ||||
| import com.simsilica.lemur.component.SpringGridLayout; | ||||
|  | ||||
| import com.simsilica.lemur.style.ElementId; | ||||
|  | ||||
| import pp.dialog.Dialog; | ||||
| import pp.monopoly.client.MonopolyApp; | ||||
| import pp.monopoly.notification.Sound; | ||||
| @@ -26,6 +24,7 @@ public class Toolbar extends Dialog { | ||||
|  | ||||
|     private final MonopolyApp app; | ||||
|     private final Container toolbarContainer; | ||||
|     private final Geometry cube; // Referenz auf den Würfel | ||||
|     private final BitmapText positionText; // Anzeige für die aktuelle Position | ||||
|     private final float boardLimit = 0.95f; // Grenzen des Bretts | ||||
|     private final float stepSize = 0.18f; // Schrittgröße pro Bewegung | ||||
| @@ -37,10 +36,12 @@ public class Toolbar extends Dialog { | ||||
|      * Konstruktor für die Toolbar. | ||||
|      * | ||||
|      * @param app  Die Hauptanwendung (MonopolyApp) | ||||
|      * @param cube Der Würfel, der bewegt werden soll | ||||
|      */ | ||||
|     public Toolbar(MonopolyApp app) { | ||||
|     public Toolbar(MonopolyApp app, Geometry cube) { | ||||
|         super(app.getDialogManager()); | ||||
|         this.app = app; | ||||
|         this.cube = cube; | ||||
|  | ||||
|         // Erstelle die Toolbar | ||||
|         toolbarContainer = new Container(new SpringGridLayout(Axis.X, Axis.Y), "toolbar"); | ||||
| @@ -83,61 +84,11 @@ public class Toolbar extends Dialog { | ||||
|  | ||||
|         // Menü-Container: Ein Container für Würfel | ||||
|         Container diceContainer = toolbarContainer.addChild(new Container()); | ||||
|         diceContainer.setLayout(new SpringGridLayout(Axis.X, Axis.Y)); | ||||
|  | ||||
|         // Create a horizontal container to align leftContainer and rightContainer side by side | ||||
|         Container horizontalContainer = new Container(new SpringGridLayout(Axis.X, Axis.Y)); | ||||
|         horizontalContainer.setPreferredSize(new Vector3f(200, 150, 0)); // Adjust size as needed | ||||
|  | ||||
|         // Create the first container (leftContainer) | ||||
|         Container leftContainer = new Container(); | ||||
|         leftContainer.setPreferredSize(new Vector3f(100, 150, 0)); // Adjust size as needed | ||||
|  | ||||
|         Label imageLabel = new Label(""); | ||||
|         IconComponent icon = new IconComponent("Pictures/dice/one.png"); // Icon mit Textur erstellen | ||||
|         icon.setIconSize(new Vector2f(100,100)); // Skalierung des Bildes | ||||
|         imageLabel.setIcon(icon); | ||||
|  | ||||
|         Label imageLabel2 = new Label(""); | ||||
|         IconComponent icon2 = new IconComponent("Pictures/dice/two.png"); // Icon mit Textur erstellen | ||||
|         icon2.setIconSize(new Vector2f(100,100)); // Skalierung des Bildes | ||||
|         imageLabel2.setIcon(icon2); | ||||
|  | ||||
|         // Create the second container (rightContainer) | ||||
|         Container rightContainer = new Container(); | ||||
|         rightContainer.setPreferredSize(new Vector3f(100, 150, 0)); // Adjust size as needed | ||||
|         leftContainer.setBackground(null); | ||||
|         rightContainer.setBackground(null); | ||||
|         diceContainer.setPreferredSize(new Vector3f(400, 150, 0)); | ||||
|         diceContainer.addChild(new Label("Wo Würfel?", new ElementId("label"))); | ||||
|         diceContainer.addChild(addDiceRollButton()); | ||||
|         diceContainer.setBackground(null); | ||||
|         horizontalContainer.setBackground(null); | ||||
|  | ||||
|         imageLabel.setTextVAlignment(VAlignment.Center); | ||||
|         imageLabel.setTextHAlignment(HAlignment.Center); | ||||
|         imageLabel2.setTextVAlignment(VAlignment.Center); | ||||
|         imageLabel2.setTextHAlignment(HAlignment.Center); | ||||
|  | ||||
|         leftContainer.addChild(imageLabel); | ||||
|         rightContainer.addChild(imageLabel2); | ||||
|  | ||||
|  | ||||
|  | ||||
|         // Add leftContainer and rightContainer to the horizontal container | ||||
|         horizontalContainer.addChild(leftContainer); | ||||
|         horizontalContainer.addChild(rightContainer); | ||||
|  | ||||
|         // Add the horizontalContainer to the diceContainer (top section) | ||||
|         diceContainer.addChild(horizontalContainer); | ||||
|  | ||||
|         // Add the Würfeln button directly below the horizontalContainer | ||||
|         Button diceButton = new Button("Würfeln"); | ||||
|         diceButton.setPreferredSize(new Vector3f(200, 50, 0)); // Full width for Würfeln button | ||||
|         diceButton.addClickCommands(s -> ifTopDialog(() -> { | ||||
|             rollDice(); | ||||
|             app.getGameLogic().playSound(Sound.BUTTON); | ||||
|         })); | ||||
|         diceContainer.addChild(diceButton); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|         // Menü-Container: Ein Nested-Container für Handeln, Grundstücke und Zug beenden | ||||
| @@ -196,15 +147,12 @@ public class Toolbar extends Dialog { | ||||
|     private void addTradeMenuButton() { | ||||
|         Button diceButton = new Button("Handeln"); | ||||
|         diceButton.setPreferredSize(new Vector3f(150, 50, 0)); // Größe des Buttons | ||||
|         diceButton.addClickCommands(s  -> { | ||||
|         diceButton.addClickCommands(s -> ifTopDialog(() -> { | ||||
|             rollDice(); | ||||
|             app.getGameLogic().playSound(Sound.BUTTON); | ||||
|             this.close(); | ||||
|             System.out.println("test"); | ||||
|             new ChoosePartner(app).open(); | ||||
|         }); | ||||
|         })); | ||||
|         toolbarContainer.addChild(diceButton); | ||||
|     }// TODO Funktion der Buttons Überarbeiten und prüfen | ||||
|     } | ||||
|  | ||||
|     private void addEndTurnButton() { | ||||
|         Button diceButton = new Button("Grundstücke"); | ||||
| @@ -232,6 +180,20 @@ public class Toolbar extends Dialog { | ||||
|     private void rollDice() { | ||||
|         int diceRoll = random.nextInt(6) + 1; // Zahl zwischen 1 und 6 | ||||
|         System.out.println("Gewürfelt: " + diceRoll); | ||||
|         moveCube(diceRoll); // Bewege die Figur um die gewürfelte Zahl | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Bewegt den Würfel basierend auf der aktuellen Position auf dem Brett. | ||||
|      * | ||||
|      * @param step Schrittweite (+1 für vorwärts, -1 für rückwärts oder andere Werte) | ||||
|      */ | ||||
|     private void moveCube(int step) { | ||||
|         currentPosition = (currentPosition + step + 4 * positionsPerSide) % (4 * positionsPerSide); | ||||
|         Vector3f newPosition = calculatePosition(currentPosition); | ||||
|         cube.setLocalTranslation(newPosition); | ||||
|         updatePositionDisplay(); // Aktualisiere die Positionsanzeige | ||||
|         System.out.println("Würfelposition: " + newPosition + " (Feld-ID: " + currentPosition + ")"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -278,15 +240,11 @@ public class Toolbar extends Dialog { | ||||
|         positionText.setText("Feld-ID: " + currentPosition); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void close() { | ||||
|     /** | ||||
|      * Entfernt die Toolbar. | ||||
|      */ | ||||
|     public void remove() { | ||||
|         app.getGuiNode().detachChild(toolbarContainer); | ||||
|         app.getGuiNode().detachChild(positionText); | ||||
|         super.close(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void escape() { | ||||
|         new SettingsMenu(app).open(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -12,7 +12,6 @@ import com.simsilica.lemur.style.ElementId; | ||||
|  | ||||
| import pp.dialog.Dialog; | ||||
| import pp.monopoly.client.MonopolyApp; | ||||
| import pp.monopoly.client.gui.SettingsMenu; | ||||
| import pp.monopoly.model.fields.BuildingProperty; | ||||
|  | ||||
| /** | ||||
| @@ -24,7 +23,7 @@ public class BuildingPropertyCard extends Dialog { | ||||
|     private final Geometry overlayBackground; | ||||
|     private final Container buildingPropertyContainer; | ||||
|     private final Container backgroundContainer; | ||||
|     private int index = 37; | ||||
|     private int index = 39; | ||||
|  | ||||
|     public BuildingPropertyCard(MonopolyApp app) { | ||||
|         super(app.getDialogManager()); | ||||
| @@ -118,18 +117,17 @@ public class BuildingPropertyCard extends Dialog { | ||||
|      */ | ||||
|     @Override | ||||
|     public void close() { | ||||
|         System.out.println("Schließe SettingsMenu..."); // Debugging-Ausgabe | ||||
|         app.getGuiNode().detachChild(buildingPropertyContainer);  // Entferne das Menü | ||||
|         app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand | ||||
|         app.getGuiNode().detachChild(overlayBackground);  // Entferne das Overlay | ||||
|         super.close(); | ||||
|         // app.setSettingsMenuOpen(false);                  // Menü als geschlossen markieren | ||||
|         // app.unblockInputs();                             // Eingaben wieder aktivieren | ||||
|         System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe | ||||
|     } | ||||
|      | ||||
|     public void setIndex(int index) { | ||||
|         this.index = index; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void escape() { | ||||
|         new SettingsMenu(app).open(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,18 +3,14 @@ package pp.monopoly.client.gui.popups; | ||||
| import com.jme3.material.Material; | ||||
| import com.jme3.material.RenderState.BlendMode; | ||||
| import com.jme3.math.ColorRGBA; | ||||
| import com.jme3.math.Vector3f; | ||||
| import com.jme3.scene.Geometry; | ||||
| import com.jme3.scene.shape.Quad; | ||||
| import com.simsilica.lemur.Button; | ||||
| import com.simsilica.lemur.Container; | ||||
| import com.simsilica.lemur.Label; | ||||
| import com.simsilica.lemur.*; | ||||
| import com.simsilica.lemur.component.QuadBackgroundComponent; | ||||
| import com.simsilica.lemur.style.ElementId; | ||||
| import pp.dialog.Dialog; | ||||
| import pp.monopoly.client.MonopolyApp; | ||||
| import pp.monopoly.client.gui.SettingsMenu; | ||||
| import pp.monopoly.model.fields.BoardManager; | ||||
| import pp.monopoly.model.fields.BuildingProperty; | ||||
|  | ||||
| /** | ||||
|  * SettingsMenu ist ein Overlay-Menü, das durch ESC aufgerufen werden kann. | ||||
| @@ -22,18 +18,13 @@ import pp.monopoly.model.fields.BuildingProperty; | ||||
| public class BuyCard extends Dialog { | ||||
|     private final MonopolyApp app; | ||||
|     private final Geometry overlayBackground; | ||||
|     private final Container buyCardContainer; | ||||
|     private final Container settingsContainer; | ||||
|     private final Container backgroundContainer; | ||||
|  | ||||
|     private int index = 37; | ||||
|  | ||||
|     public BuyCard(MonopolyApp app) { | ||||
|         super(app.getDialogManager()); | ||||
|         this.app = app; | ||||
|  | ||||
|         //Generate the corresponfing field | ||||
|         BuildingProperty field = (BuildingProperty) new BoardManager().getFieldAtIndex(index); | ||||
|  | ||||
|         // Halbtransparentes Overlay hinzufügen | ||||
|         overlayBackground = createOverlayBackground(); | ||||
|         app.getGuiNode().attachChild(overlayBackground); | ||||
| @@ -43,55 +34,52 @@ public class BuyCard extends Dialog { | ||||
|         backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background | ||||
|         app.getGuiNode().attachChild(backgroundContainer); | ||||
|  | ||||
|         // Hauptcontainer für die Gebäudekarte | ||||
|         buyCardContainer = new Container(); | ||||
|         buyCardContainer.setBackground(new QuadBackgroundComponent(field.getColor().getColor())); | ||||
|         // Hauptcontainer für das Menü | ||||
|         settingsContainer = new Container(); | ||||
|         settingsContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.1f, 0.1f, 0.1f, 0.9f))); | ||||
|  | ||||
|  | ||||
|         Label settingsTitle = buyCardContainer.addChild(new Label( field.getName(), new ElementId("settings-title"))); | ||||
|  | ||||
|         // Titel | ||||
|         Label settingsTitle = settingsContainer.addChild(new Label("Gebäude 30", new ElementId("settings-title"))); //TODO Dynamische Gebäudezahl einfügen | ||||
|         settingsTitle.setFontSize(48); | ||||
|  | ||||
|         // Text, der auf der Karte steht | ||||
|         // Die Preise werden dynamisch dem BoardManager entnommen | ||||
|         Container propertyValuesContainer = buyCardContainer.addChild(new Container()); | ||||
|         propertyValuesContainer.addChild(new Label("„Grundstückswert: " + field.getPrice() + " EUR", new ElementId("label-Text"))); | ||||
|         propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile | ||||
|         propertyValuesContainer.addChild(new Label("„Miete allein: " + field.getAllRent().get(0)+ " EUR", new ElementId("label-Text"))); | ||||
|         propertyValuesContainer.addChild(new Label("„-mit 1 Haus: " + field.getAllRent().get(1) + " EUR", new ElementId("label-Text"))); | ||||
|         propertyValuesContainer.addChild(new Label("„-mit 2 Häuser: " + field.getAllRent().get(2) + " EUR", new ElementId("label-Text"))); | ||||
|         propertyValuesContainer.addChild(new Label("„-mit 3 Häuser: " + field.getAllRent().get(3) + " EUR", new ElementId("label-Text"))); | ||||
|         propertyValuesContainer.addChild(new Label("„-mit 4 Häuser: " + field.getAllRent().get(4) + " EUR", new ElementId("label-Text"))); | ||||
|         propertyValuesContainer.addChild(new Label("„-mit 1 Hotel: " + field.getAllRent().get(5) + " EUR", new ElementId("label-Text"))); | ||||
|         propertyValuesContainer.addChild(new Label("„-1 Haus kostet: " + field.getHousePrice()+ " EUR", new ElementId("label-Text"))); | ||||
|         propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile | ||||
|         propertyValuesContainer.addChild(new Label("„Hypothek: " + field.getHypo() + " EUR", new ElementId("label-Text"))); | ||||
|         int i = 0; | ||||
|         int a = 10; | ||||
|         int b = -45; | ||||
|  | ||||
|         // Effekt-Sound: Slider und Checkbox | ||||
|         Container propertyValuesContainer = settingsContainer.addChild(new Container()); | ||||
|         propertyValuesContainer.addChild(new Label("„Preis:" + i, new ElementId("label-Text")));//TODO Variable hier einsetzen | ||||
|         propertyValuesContainer.addChild(new Label("„Miete:" + a, new ElementId("label-Text")));//TODO Variable hier einsetzen | ||||
|         propertyValuesContainer.addChild(new Label("„Hypothek:" + b, new ElementId("label-Text")));//TODO Variable hier einsetzen | ||||
|         propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f))); | ||||
|  | ||||
|         // Beenden-Button | ||||
|         Button quitButton = buyCardContainer.addChild(new Button("Beenden", new ElementId("button"))); | ||||
|         Button quitButton = settingsContainer.addChild(new Button("Beenden", new ElementId("button"))); | ||||
|         quitButton.setFontSize(32); | ||||
|         // Kaufen-Button | ||||
|         Button buyButton = buyCardContainer.addChild(new Button("Kaufen", new ElementId("button"))); | ||||
|         Button buyButton = settingsContainer.addChild(new Button("Kaufen", new ElementId("button"))); | ||||
|         buyButton.setFontSize(32); | ||||
|  | ||||
|         float padding = 10; // Padding around the settingsContainer for the background | ||||
|         backgroundContainer.setPreferredSize(buyCardContainer.getPreferredSize().addLocal(padding, padding, 0)); | ||||
|         backgroundContainer.setPreferredSize(settingsContainer.getPreferredSize().addLocal(padding, padding, 0)); | ||||
|  | ||||
|  | ||||
|         // Zentriere das Menü | ||||
|         buyCardContainer.setLocalTranslation( | ||||
|             (app.getCamera().getWidth() - buyCardContainer.getPreferredSize().x) / 2, | ||||
|             (app.getCamera().getHeight() + buyCardContainer.getPreferredSize().y) / 2, | ||||
|         settingsContainer.setLocalTranslation( | ||||
|             (app.getCamera().getWidth() - settingsContainer.getPreferredSize().x) / 2, | ||||
|             (app.getCamera().getHeight() + settingsContainer.getPreferredSize().y) / 2, | ||||
|             8 | ||||
|         ); | ||||
|  | ||||
|         backgroundContainer.setLocalTranslation( | ||||
|                 (app.getCamera().getWidth() - buyCardContainer.getPreferredSize().x - padding) / 2, | ||||
|                 (app.getCamera().getHeight() + buyCardContainer.getPreferredSize().y+ padding) / 2, | ||||
|                 (app.getCamera().getWidth() - settingsContainer.getPreferredSize().x - padding) / 2, | ||||
|                 (app.getCamera().getHeight() + settingsContainer.getPreferredSize().y+ padding) / 2, | ||||
|                 7 | ||||
|         ); | ||||
|  | ||||
|         app.getGuiNode().attachChild(buyCardContainer); | ||||
|         app.getGuiNode().attachChild(settingsContainer); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -115,14 +103,14 @@ public class BuyCard extends Dialog { | ||||
|      */ | ||||
|     @Override | ||||
|     public void close() { | ||||
|         app.getGuiNode().detachChild(buyCardContainer);  // Entferne das Menü | ||||
|         System.out.println("Schließe SettingsMenu..."); // Debugging-Ausgabe | ||||
|         app.getGuiNode().detachChild(settingsContainer);  // Entferne das Menü | ||||
|         app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand | ||||
|         app.getGuiNode().detachChild(overlayBackground);  // Entferne das Overlay | ||||
|         super.close(); | ||||
|         // app.setSettingsMenuOpen(false);                  // Menü als geschlossen markieren | ||||
|         // app.unblockInputs();                             // Eingaben wieder aktivieren | ||||
|         System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void escape() { | ||||
|         new SettingsMenu(app).open(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,124 +0,0 @@ | ||||
| package pp.monopoly.client.gui.popups; | ||||
|  | ||||
| import com.jme3.material.Material; | ||||
| import com.jme3.material.RenderState.BlendMode; | ||||
| import com.jme3.math.ColorRGBA; | ||||
| import com.jme3.math.Vector3f; | ||||
| import com.jme3.scene.Geometry; | ||||
| import com.jme3.scene.shape.Quad; | ||||
| import com.simsilica.lemur.Button; | ||||
| import com.simsilica.lemur.Container; | ||||
| import com.simsilica.lemur.Label; | ||||
| import com.simsilica.lemur.component.QuadBackgroundComponent; | ||||
| import com.simsilica.lemur.style.ElementId; | ||||
| import pp.dialog.Dialog; | ||||
| import pp.monopoly.client.MonopolyApp; | ||||
| import pp.monopoly.client.gui.SettingsMenu; | ||||
| import pp.monopoly.model.card.Card; // TODO für den Import der Queue notwendig | ||||
| import pp.monopoly.model.card.DeckHelper; | ||||
| /** | ||||
|  * SettingsMenu ist ein Overlay-Menü, das durch ESC aufgerufen werden kann. | ||||
|  */ | ||||
| public class EventCard extends Dialog { | ||||
|     private final MonopolyApp app; | ||||
|     private final Geometry overlayBackground; | ||||
|     private final Container eventCardContainer; | ||||
|     private final Container backgroundContainer; | ||||
|  | ||||
|  | ||||
|     public EventCard(MonopolyApp app) { | ||||
|         super(app.getDialogManager()); | ||||
|         this.app = app; | ||||
|  | ||||
|         //Generate the corresponfing field | ||||
|         Card card = new DeckHelper().drawCard(); // TODO nimmt die Karten gerade unabhängig aus dem DeckHelper | ||||
|  | ||||
|         // Halbtransparentes Overlay hinzufügen | ||||
|         overlayBackground = createOverlayBackground(); | ||||
|         app.getGuiNode().attachChild(overlayBackground); | ||||
|  | ||||
|         // Create the background container | ||||
|         backgroundContainer = new Container(); | ||||
|         backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background | ||||
|         app.getGuiNode().attachChild(backgroundContainer); | ||||
|  | ||||
|         // Hauptcontainer für die Gebäudekarte | ||||
|         eventCardContainer = new Container(); | ||||
|         eventCardContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); | ||||
|         eventCardContainer.setPreferredSize(new Vector3f(550,400,10)); | ||||
|  | ||||
|         // Titel | ||||
|         // Die Namen werden dynamisch dem BoardManager entnommen | ||||
|         Label gateFieldTitle = eventCardContainer.addChild(new Label("Ereigniskarte", new ElementId("settings-title"))); | ||||
|         gateFieldTitle.setFontSize(48); | ||||
|         gateFieldTitle.setColor(ColorRGBA.Black); | ||||
|  | ||||
|         // Text, der auf der Karte steht | ||||
|         // Die Preise werden dynamisch dem BoardManager entnommen | ||||
|         Container propertyValuesContainer = eventCardContainer.addChild(new Container()); | ||||
|         propertyValuesContainer.addChild(new Label(card.getDescription(), new ElementId("label-Text"))); | ||||
|         propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f))); | ||||
|         propertyValuesContainer.setPreferredSize(new Vector3f(300,200,10)); | ||||
|  | ||||
|         // Beenden-Button | ||||
|         Button quitButton = eventCardContainer.addChild(new Button("Jawohl", new ElementId("button"))); | ||||
|         quitButton.setFontSize(32); | ||||
|         quitButton.addClickCommands(source -> close()); | ||||
|  | ||||
|  | ||||
|         // TODO Kaufen-Button wird nicht mehr benötigt, prüfen ob weg kann | ||||
|         //Button buyButton = buyCardContainer.addChild(new Button("Kaufen", new ElementId("button"))); | ||||
|         //buyButton.setFontSize(32); | ||||
|  | ||||
|         float padding = 10; // Padding around the settingsContainer for the background | ||||
|         backgroundContainer.setPreferredSize(eventCardContainer.getPreferredSize().addLocal(padding, padding, 0)); | ||||
|  | ||||
|  | ||||
|         // Zentriere das Menü | ||||
|         eventCardContainer.setLocalTranslation( | ||||
|             (app.getCamera().getWidth() - eventCardContainer.getPreferredSize().x) / 2, | ||||
|             (app.getCamera().getHeight() + eventCardContainer.getPreferredSize().y) / 2, | ||||
|             8 | ||||
|         ); | ||||
|  | ||||
|         backgroundContainer.setLocalTranslation( | ||||
|                 (app.getCamera().getWidth() - eventCardContainer.getPreferredSize().x - padding) / 2, | ||||
|                 (app.getCamera().getHeight() + eventCardContainer.getPreferredSize().y+ padding) / 2, | ||||
|                 7 | ||||
|         ); | ||||
|  | ||||
|         app.getGuiNode().attachChild(eventCardContainer); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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(eventCardContainer);  // Entferne das Menü | ||||
|         app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand | ||||
|         app.getGuiNode().detachChild(overlayBackground);  // Entferne das Overlay | ||||
|         super.close(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void escape() { | ||||
|         new SettingsMenu(app).open(); | ||||
|     } | ||||
| } | ||||
| @@ -5,6 +5,7 @@ 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.Container; | ||||
| import com.simsilica.lemur.Label; | ||||
| import com.simsilica.lemur.component.QuadBackgroundComponent; | ||||
| @@ -12,7 +13,6 @@ import com.simsilica.lemur.style.ElementId; | ||||
|  | ||||
| import pp.dialog.Dialog; | ||||
| import pp.monopoly.client.MonopolyApp; | ||||
| import pp.monopoly.client.gui.SettingsMenu; | ||||
| import pp.monopoly.model.fields.FoodField; | ||||
|  | ||||
| /** | ||||
| @@ -121,19 +121,17 @@ public class FoodFieldCard extends Dialog { | ||||
|      */ | ||||
|     @Override | ||||
|     public void close() { | ||||
|         System.out.println("Schließe SettingsMenu..."); // Debugging-Ausgabe | ||||
|         app.getGuiNode().detachChild(foodFieldContainer);  // Entferne das Menü | ||||
|         app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand | ||||
|         app.getGuiNode().detachChild(overlayBackground);  // Entferne das Overlay | ||||
|         super.close(); | ||||
|         // app.setSettingsMenuOpen(false);                  // Menü als geschlossen markieren | ||||
|         // app.unblockInputs();                             // Eingaben wieder aktivieren | ||||
|         System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe | ||||
|     } | ||||
|  | ||||
|     public void setIndex(int index) { | ||||
|         this.index = index; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void escape() { | ||||
|         new SettingsMenu(app).open(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -11,7 +11,6 @@ import com.simsilica.lemur.component.QuadBackgroundComponent; | ||||
| import com.simsilica.lemur.style.ElementId; | ||||
| import pp.dialog.Dialog; | ||||
| import pp.monopoly.client.MonopolyApp; | ||||
| import pp.monopoly.client.gui.SettingsMenu; | ||||
| import pp.monopoly.model.fields.GateField; | ||||
|  | ||||
| /** | ||||
| @@ -46,9 +45,9 @@ public class GateFieldCard extends Dialog { | ||||
|  | ||||
|         // Titel | ||||
|         // Die Namen werden dynamisch dem BoardManager entnommen | ||||
|         Label gateFieldTitle = gateFieldContainer.addChild(new Label(field.getName(), new ElementId("settings-title"))); | ||||
|         gateFieldTitle.setFontSize(48); | ||||
|         gateFieldTitle.setColor(ColorRGBA.Black); | ||||
|         Label settingsTitle = gateFieldContainer.addChild(new Label(field.getName(), new ElementId("settings-title"))); | ||||
|         settingsTitle.setFontSize(48); | ||||
|         settingsTitle.setColor(ColorRGBA.Black); | ||||
|  | ||||
|         // Text, der auf der Karte steht | ||||
|         // Die Preise werden dynamisch dem BoardManager entnommen | ||||
| @@ -115,18 +114,16 @@ public class GateFieldCard extends Dialog { | ||||
|      */ | ||||
|     @Override | ||||
|     public void close() { | ||||
|         System.out.println("Schließe SettingsMenu..."); // Debugging-Ausgabe | ||||
|         app.getGuiNode().detachChild(gateFieldContainer);  // Entferne das Menü | ||||
|         app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand | ||||
|         app.getGuiNode().detachChild(overlayBackground);  // Entferne das Overlay | ||||
|         super.close(); | ||||
|         // app.setSettingsMenuOpen(false);                  // Menü als geschlossen markieren | ||||
|         // app.unblockInputs();                             // Eingaben wieder aktivieren | ||||
|         System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe | ||||
|     } | ||||
|  | ||||
|     public void setIndex(int index) { | ||||
|         this.index = index; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void escape() { | ||||
|         new SettingsMenu(app).open(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| Before Width: | Height: | Size: 260 KiB | 
| Before Width: | Height: | Size: 105 KiB | 
| Before Width: | Height: | Size: 207 KiB | 
| Before Width: | Height: | Size: 169 KiB | 
| Before Width: | Height: | Size: 228 KiB | 
| Before Width: | Height: | Size: 183 KiB | 
| Before Width: | Height: | Size: 171 KiB | 
| @@ -7,9 +7,4 @@ description = 'Monopoly common model' | ||||
| dependencies { | ||||
|     api project(":common") | ||||
|     api libs.jme3.networking | ||||
|     testImplementation libs.mockito.core | ||||
|  | ||||
|     testImplementation project(":monopoly:client") | ||||
|     testImplementation project(":monopoly:model") | ||||
|     testImplementation project(":monopoly:server") | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import java.lang.System.Logger.Level; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| import pp.monopoly.game.server.Player; | ||||
| import pp.monopoly.game.server.PlayerHandler; | ||||
| import pp.monopoly.message.client.ClientMessage; | ||||
| import pp.monopoly.message.server.BuyPropertyResponse; | ||||
| import pp.monopoly.message.server.DiceResult; | ||||
| @@ -52,7 +52,7 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker { | ||||
|     /** The current state of the client game logic. */ | ||||
|     private ClientState state = new LobbyState(this); | ||||
|  | ||||
|     private List<Player> players; | ||||
|     private PlayerHandler playerHandler; | ||||
|  | ||||
|     private BoardManager boardManager = new BoardManager(); | ||||
|  | ||||
| @@ -94,8 +94,8 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker { | ||||
|         state.entry(); | ||||
|     } | ||||
|  | ||||
|     public List<Player> getPlayers() { | ||||
|         return players; | ||||
|     public PlayerHandler getPlayerHandler() { | ||||
|         return playerHandler; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -226,7 +226,7 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker { | ||||
|     @Override | ||||
|     public void received(EventDrawCard msg) { | ||||
|         setInfoText("Event card drawn: " + msg.getCardDescription()); | ||||
|         // Kartenlogik | ||||
|         //event card logic | ||||
|         playSound(Sound.EVENT_CARD); | ||||
|     } | ||||
|  | ||||
| @@ -255,7 +255,7 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker { | ||||
|      */ | ||||
|     @Override | ||||
|     public void received(GameStart msg) { | ||||
|         players = msg.getPlayers(); | ||||
|         playerHandler = msg.getPlayerHandler(); | ||||
|         setInfoText("The game has started! Good luck!"); | ||||
|         setState(new WaitForTurnState(this)); | ||||
|     } | ||||
|   | ||||
| @@ -10,8 +10,6 @@ package pp.monopoly.game.server; | ||||
| import java.util.List; | ||||
| import java.util.Random; | ||||
|  | ||||
| import com.jme3.network.serializing.Serializable; | ||||
|  | ||||
| import pp.monopoly.message.server.DiceResult; | ||||
| import pp.monopoly.model.FieldVisitor; | ||||
| import pp.monopoly.model.Figure; | ||||
| @@ -30,7 +28,6 @@ import pp.monopoly.model.fields.WacheField; | ||||
| /** | ||||
|  * Class representing a player | ||||
|  */ | ||||
| @Serializable | ||||
| public class Player implements FieldVisitor<Void>{ | ||||
|     private final int id; | ||||
|     private String name; | ||||
| @@ -43,14 +40,6 @@ public class Player implements FieldVisitor<Void>{ | ||||
|     private final PlayerHandler handler; | ||||
|     private PlayerState state = new LobbyState(); | ||||
|  | ||||
|     /** | ||||
|      * Default constructor for serialization purposes. | ||||
|      */ | ||||
|     private Player(){ | ||||
|         id = 0; | ||||
|         handler = null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Constructs a player with the speciefied params | ||||
|      * @param id the id of the player | ||||
| @@ -95,7 +84,7 @@ public class Player implements FieldVisitor<Void>{ | ||||
|      * Set the name of the Player | ||||
|      * @param name the new name | ||||
|      */ | ||||
|     public void setName(String name) { | ||||
|     void setName(String name) { | ||||
|         this.name = name; | ||||
|     } | ||||
|  | ||||
| @@ -179,7 +168,6 @@ public class Player implements FieldVisitor<Void>{ | ||||
|     public void buyProperty(PropertyField property) { | ||||
|         if (property.getOwner() == null && accountBalance >= property.getPrice()) { | ||||
|             properties.add(property); | ||||
|             property.setOwner(this); | ||||
|             pay(property.getPrice()); | ||||
|         } | ||||
|     } | ||||
| @@ -513,7 +501,7 @@ public class Player implements FieldVisitor<Void>{ | ||||
|             getOutOfJailCard--; | ||||
|             state = new ActiveState(); | ||||
|         } | ||||
|  | ||||
|          | ||||
|     } | ||||
|     private class WaitForTurnState implements PlayerState { | ||||
|  | ||||
| @@ -529,6 +517,6 @@ public class Player implements FieldVisitor<Void>{ | ||||
|         @Override | ||||
|         public void useJailCard() { | ||||
|         } | ||||
|  | ||||
|          | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -8,13 +8,10 @@ import java.util.List; | ||||
| import java.util.NoSuchElementException; | ||||
| import java.util.Set; | ||||
|  | ||||
| import com.jme3.network.serializing.Serializable; | ||||
|  | ||||
| import pp.monopoly.model.LimitedLinkedList; | ||||
| /** | ||||
|  * A class for helping with player actions and managing thier turns | ||||
|  */ | ||||
| @Serializable | ||||
| public class PlayerHandler { | ||||
|     private List<Player> players = new LimitedLinkedList<>(6); | ||||
|     private Set<Player> readyPlayers = new HashSet<>(); | ||||
| @@ -22,11 +19,6 @@ public class PlayerHandler { | ||||
|     private Player hostPlayer; | ||||
|     private Player extra = null; | ||||
|  | ||||
|     /** | ||||
|      * Default constructor for serialization purposes. | ||||
|      */ | ||||
|     private PlayerHandler() {} | ||||
|  | ||||
|     /** | ||||
|      * Contructs a PlayerHandler | ||||
|      * @param logic the {@link ServerGameLogic} this PlayerHandler is a part of | ||||
| @@ -165,7 +157,7 @@ public class PlayerHandler { | ||||
|      * @param id the id to be searched for | ||||
|      * @return the player with the required id | ||||
|      */ | ||||
|     public Player getPlayerById(int id) { | ||||
|     Player getPlayerById(int id) { | ||||
|         for (Player player : players) { | ||||
|             if (player.getId() == id) return player; | ||||
|         } | ||||
| @@ -184,7 +176,7 @@ public class PlayerHandler { | ||||
|         players.get(0).setActive(); | ||||
|     } | ||||
|  | ||||
|     public void setStartBalance(int amount) { | ||||
|     void setStartBalance(int amount) { | ||||
|         for (Player player : players) { | ||||
|             player.setAccountBalance(amount); | ||||
|         } | ||||
|   | ||||
| @@ -204,7 +204,7 @@ public class ServerGameLogic implements ClientInterpreter { | ||||
|         if(playerHandler.allPlayersReady()) { | ||||
|             playerHandler.setStartBalance(startMoney); | ||||
|             for (Player p : playerHandler.getPlayers()) { | ||||
|                send(p, new GameStart(playerHandler.getPlayers()));  | ||||
|                send(p, new GameStart(playerHandler));  | ||||
|             } | ||||
|             playerHandler.randomOrder(); | ||||
|             send(playerHandler.getPlayerAtIndex(0), new NextPlayerTurn(playerHandler.getPlayerAtIndex(0))); | ||||
|   | ||||
| @@ -1,27 +1,25 @@ | ||||
| package pp.monopoly.message.server; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import com.jme3.network.serializing.Serializable; | ||||
|  | ||||
| import pp.monopoly.game.server.Player; | ||||
| import pp.monopoly.game.server.PlayerHandler; | ||||
|  | ||||
| @Serializable | ||||
| public class GameStart extends ServerMessage{ | ||||
|  | ||||
|     private List<Player> players; | ||||
|     private PlayerHandler ph; | ||||
|  | ||||
|     /** | ||||
|      * Default constructor for serialization purposes. | ||||
|      */ | ||||
|     private GameStart() { /* empty */ } | ||||
|  | ||||
|     public GameStart(List<Player> players) { | ||||
|         this.players = players; | ||||
|     public GameStart(PlayerHandler ph) { | ||||
|         this.ph = ph; | ||||
|     } | ||||
|  | ||||
|     public List<Player> getPlayers() { | ||||
|         return players; | ||||
|     public PlayerHandler getPlayerHandler() { | ||||
|         return ph; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -4,12 +4,9 @@ import java.util.Collections; | ||||
| import java.util.HashSet; | ||||
| import java.util.Set; | ||||
|  | ||||
| import com.jme3.network.serializing.Serializable; | ||||
|  | ||||
| import static java.lang.Math.max; | ||||
| import static java.lang.Math.min; | ||||
|  | ||||
| @Serializable | ||||
| public class Figure implements Item{ | ||||
|     private final String type; | ||||
|     private final int length; // The length of the Figure | ||||
|   | ||||
| @@ -2,22 +2,14 @@ package pp.monopoly.model; | ||||
|  | ||||
| import java.util.LinkedList; | ||||
|  | ||||
| import com.jme3.network.serializing.Serializable; | ||||
|  | ||||
| /** | ||||
|  * A LinkedList with a maximum size limit. | ||||
|  * | ||||
|  * @param <E> the type of elements held in this collection | ||||
|  */ | ||||
| @Serializable | ||||
| public class LimitedLinkedList<E> extends LinkedList<E> { | ||||
|  | ||||
|     private int maxSize; | ||||
|  | ||||
|     /** | ||||
|      * Default constructor for serialization purposes. | ||||
|      */ | ||||
|     private LimitedLinkedList() {} | ||||
|     private final int maxSize; | ||||
|  | ||||
|     /** | ||||
|      * Constructs a LimitedLinkedList with the specified maximum size. | ||||
|   | ||||
| @@ -15,9 +15,9 @@ public class Card { | ||||
|         visitor.visit(this, player); | ||||
|     } | ||||
|  | ||||
|     public String getDescription() { | ||||
|     String getDescription() { | ||||
|         return description; | ||||
|     } // TODO wird gerade in der EventCard zur erstellung des Popup genutzt | ||||
|     } | ||||
|  | ||||
|     String getKeyword() { | ||||
|         return keyword; | ||||
|   | ||||
| @@ -1,25 +1,26 @@ | ||||
| //////////////////////////////////////// | ||||
| // Programming project code | ||||
| // UniBw M, 2022, 2023, 2024 | ||||
| // www.unibw.de/inf2 | ||||
| // (c) Mark Minas (mark.minas@unibw.de) | ||||
| //////////////////////////////////////// | ||||
|  | ||||
| package pp.monopoly.notification; | ||||
|  | ||||
| /** | ||||
|  * Event when a sound needs to be played. | ||||
|  * Event when an item is added to a map. | ||||
|  * | ||||
|  * @param soundFileName the sound file to be played | ||||
|  * @param sound the sound to be played | ||||
|  */ | ||||
| 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; | ||||
|     } | ||||
| public record SoundEvent(Sound sound) implements GameEvent { | ||||
|  | ||||
|     /** | ||||
|      * Notifies the game event listener of this event. | ||||
|      * | ||||
|      * @param listener the game event listener | ||||
|      */ | ||||
|     @Override | ||||
|     public void notifyListener(GameEventListener listener) { | ||||
|         listener.receivedEvent(this); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| /* | ||||
| package pp.monopoly; | ||||
| import org.junit.Test; | ||||
| import static org.junit.Assert.assertNotNull; | ||||
| @@ -384,4 +383,3 @@ public class Testhandbuch { | ||||
|     } | ||||
|  | ||||
|  | ||||
| */ | ||||
| @@ -1,106 +1,30 @@ | ||||
| package pp.monopoly.client; | ||||
|  | ||||
| import com.jme3.input.KeyInput; | ||||
| import com.jme3.scene.Spatial; | ||||
| import com.jme3.scene.Node; | ||||
| import com.simsilica.lemur.Button; | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
|  | ||||
| import static org.junit.Assert.assertNotNull; | ||||
| import static org.mockito.Mockito.*; | ||||
| import static org.junit.Assert.assertNull; | ||||
|  | ||||
| public class ClientLogicTest { | ||||
|  | ||||
|     private MonopolyApp app; | ||||
|     private Node guiNodeMock; | ||||
|  | ||||
|     @Before | ||||
|     public void setUp() { | ||||
|         // Erstelle eine Mock-Instanz der MonopolyApp | ||||
|         app = spy(new MonopolyApp()); | ||||
|  | ||||
|         // Mock GuiNode | ||||
|         guiNodeMock = mock(Node.class); | ||||
|         doReturn(guiNodeMock).when(app).getGuiNode(); | ||||
|  | ||||
|         // Initialisiere die App | ||||
|         doNothing().when(app).simpleInitApp(); | ||||
|         app = new MonopolyApp(); | ||||
|         app.simpleInitApp(); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T001: UC-game-01 - Überprüft, ob die Anwendung erfolgreich gestartet wird und das Hauptmenü angezeigt wird | ||||
|     public void testStartApplication() { | ||||
|         // Mock des Hauptmenü-Kindes | ||||
|         Spatial mainMenuMock = mock(Spatial.class); | ||||
|         when(guiNodeMock.getChild("MainMenu")).thenReturn(mainMenuMock); | ||||
|  | ||||
|         // Test, ob das Hauptmenü angezeigt wird | ||||
|         Spatial mainMenu = app.getGuiNode().getChild("MainMenu"); | ||||
|         assertNotNull("Das Hauptmenü sollte sichtbar sein", mainMenu); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T002: UC-game-02 - Überprüft, ob das Startmenü nach dem Start der Anwendung angezeigt wird | ||||
|     public void testOpenStartMenu() { | ||||
|         // Mock des Startmenü-Kindes | ||||
|         Spatial startMenuMock = mock(Spatial.class); | ||||
|         when(guiNodeMock.getChild("StartMenu")).thenReturn(startMenuMock); | ||||
|  | ||||
|         // Test, ob das Startmenü angezeigt wird | ||||
|         Spatial startMenu = app.getGuiNode().getChild("StartMenu"); | ||||
|         assertNotNull("Das Startmenü sollte sichtbar sein", startMenu); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T003: UC-game-03 - Überprüft, ob der „Spiel starten“-Button das Spielerstellungsmenü öffnet | ||||
|     public void testNavigateToPlayOption() { | ||||
|         // Mock des Spielerstellungsmenü-Kindes | ||||
|         Spatial playMenuMock = mock(Spatial.class); | ||||
|         when(guiNodeMock.getChild("PlayMenu")).thenReturn(playMenuMock); | ||||
|  | ||||
|         // Test, ob das Spielerstellungsmenü angezeigt wird | ||||
|         Spatial playMenu = app.getGuiNode().getChild("PlayMenu"); | ||||
|         assertNotNull("Das Spielerstellungsmenü sollte sichtbar sein", playMenu); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T004: UC-game-04 - Testet, ob die Anwendung geschlossen wird, wenn „Beenden“ im Hauptmenü gewählt wird | ||||
|     public void testExitApplicationFromMenu() { | ||||
|         // Simuliere den Schließen-Aufruf | ||||
|         doNothing().when(app).closeApp(); | ||||
|  | ||||
|         // Rufe die Schließen-Methode auf | ||||
|         app.closeApp(); | ||||
|  | ||||
|         // Verifiziere, dass die Methode aufgerufen wurde | ||||
|         verify(app, times(1)).closeApp(); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T005: UC-game-05 - Überprüft, ob das Einstellungen-Menü aus dem Hauptmenü aufgerufen werden kann | ||||
|     public void testOpenSettingsFromMenu() { | ||||
|         // Mock des Einstellungsmenü-Kindes | ||||
|         Spatial settingsMenuMock = mock(Spatial.class); | ||||
|         when(guiNodeMock.getChild("SettingsMenu")).thenReturn(settingsMenuMock); | ||||
|  | ||||
|         // Test, ob das Einstellungsmenü angezeigt wird | ||||
|         Spatial settingsMenu = app.getGuiNode().getChild("SettingsMenu"); | ||||
|         assertNotNull("Das Einstellungsmenü sollte sichtbar sein", settingsMenu); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T006: UC-game-06 - Testet, ob das Spielmenü geöffnet wird, wenn der Spieler im Spiel „ESC“ drückt | ||||
|     public void testOpenGameMenuWithESC() { | ||||
|         // Simuliere den ESC-Tastendruck | ||||
|         doNothing().when(app).handleEscape(true); | ||||
|  | ||||
|         // Rufe die ESC-Tastenmethode auf | ||||
|         app.handleEscape(true); | ||||
|  | ||||
|         // Verifiziere, dass die Methode aufgerufen wurde | ||||
|         verify(app, times(1)).handleEscape(true); | ||||
|     } | ||||
| } | ||||
| /* | ||||
|     @Test | ||||
|     // T002: UC-game-02 - Überprüft, ob das Startmenü nach dem Start der Anwendung angezeigt wird | ||||
| @@ -109,7 +33,6 @@ public class ClientLogicTest { | ||||
|         assertNotNull("Das Startmenü sollte sichtbar sein", startMenu); | ||||
|     } | ||||
| */ | ||||
| /* | ||||
| @Test | ||||
| // T002: UC-game-02 - Überprüft, ob das Startmenü (MainMenu) angezeigt wird und die Buttons korrekt funktionieren | ||||
| public void testMainMenuButtons() { | ||||
| @@ -235,5 +158,4 @@ public void testMainMenuButtons() { | ||||
|             throw new AssertionError("'ReturnButton' ist kein Button-Objekt."); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| */ | ||||
| } | ||||
| @@ -1,123 +1,606 @@ | ||||
| package pp.monopoly.game.client; | ||||
| /* | ||||
|  | ||||
| import com.jme3.scene.Spatial; | ||||
| import com.simsilica.lemur.Button; | ||||
| import com.simsilica.lemur.TextField; | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| import org.mockito.Mock; | ||||
| import org.mockito.MockitoAnnotations; | ||||
| import pp.monopoly.server.MonopolyServer; | ||||
| import pp.monopoly.client.ClientSender; | ||||
| import pp.monopoly.client.MonopolyApp; | ||||
| import pp.monopoly.game.server.Player; | ||||
| import pp.monopoly.message.server.DiceResult; | ||||
| import pp.monopoly.notification.ClientStateEvent; | ||||
|  | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertNotNull; | ||||
| import static org.junit.Assert.assertTrue; | ||||
| import static org.mockito.Mockito.*; | ||||
|  | ||||
| /** | ||||
|  * Tests the client-side logic of the Monopoly game. | ||||
|  */ | ||||
| /* | ||||
| public class ClientGameLogicTest { | ||||
|  | ||||
|     private ClientGameLogic logic; | ||||
|     private MonopolyApp app; | ||||
|  | ||||
|     @Mock | ||||
|     private MonopolyServer serverMock; | ||||
|  | ||||
|     @Mock | ||||
|     private ClientSender clientSenderMock; | ||||
|     private MonopolyApp app; | ||||
|     private NewGameMenu newGameMenu; | ||||
|  | ||||
|     @Before | ||||
|     public void setUp() { | ||||
|         MockitoAnnotations.openMocks(this); | ||||
|         logic = new ClientGameLogic(clientSenderMock); | ||||
|         app = new MonopolyApp(); | ||||
|         app.simpleInitApp(); // Initialisiert die App mit GUI und Spielzuständen | ||||
|         newGameMenu = new NewGameMenu(); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T006: UC-game-06 - Testet, ob das Spielmenü geöffnet wird, wenn der Spieler im Spiel „ESC“ drückt | ||||
|     public void testOpenGameMenuWithESC() { | ||||
|         app.escape(true); // Simuliert das Drücken der ESC-Taste | ||||
|  | ||||
|         Spatial gameMenu = app.getGuiNode().getChild("GameMenu"); | ||||
|         assertNotNull("Das Spielmenü sollte sichtbar sein, nachdem ESC gedrückt wurde", gameMenu); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T007: UC-game-07 - Testet, ob der Spieler erfolgreich den Namen des Hosts eingeben kann | ||||
|     public void testEnterHostName() { | ||||
|         String hostName = "localhost"; | ||||
|         logic.setHostName(hostName); | ||||
|         Spatial hostNameField = app.getGuiNode().getChild("HostNameField"); | ||||
|         assertNotNull("Das Eingabefeld für den Hostnamen sollte sichtbar sein", hostNameField); | ||||
|  | ||||
|         assertEquals("The hostname should be correctly set.", hostName, logic.getHostName()); | ||||
|         if (hostNameField instanceof TextField) { | ||||
|             TextField hostNameInput = (TextField) hostNameField; | ||||
|             hostNameInput.setText("TestHost"); | ||||
|  | ||||
|             assertEquals("Der eingegebene Hostname sollte 'TestHost' sein", "TestHost", hostNameInput.getText()); | ||||
|         } | ||||
|         else { | ||||
|             throw new AssertionError("'HostNameField' ist kein TextField-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T008: UC-game-08 - Testet, ob der Spieler die Portnummer des Hosts eingeben kann | ||||
|     public void testEnterPortNumber() { | ||||
|         int portNumber = 12345; | ||||
|         logic.setPortNumber(portNumber); | ||||
|         Spatial portNumberField = app.getGuiNode().getChild("PortNumberField"); | ||||
|         assertNotNull("Das Eingabefeld für die Portnummer sollte sichtbar sein", portNumberField); | ||||
|  | ||||
|         assertEquals("The port number should be correctly set.", portNumber, logic.getPortNumber()); | ||||
|         if (portNumberField instanceof TextField) { | ||||
|             TextField portNumberInput = (TextField) portNumberField; | ||||
|             portNumberInput.setText("12345"); | ||||
|  | ||||
|             assertEquals("Die eingegebene Portnummer sollte '12345' sein", "12345", portNumberInput.getText()); | ||||
|         } | ||||
|         else { | ||||
|             throw new AssertionError("'PortNumberField' ist kein TextField-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T009: UC-game-09 - Testet, ob der Spieler das Erstellen eines Spiels abbrechen kann | ||||
|     public void testCancelGameCreation() { | ||||
|         doNothing().when(clientSenderMock).returnToMainMenu(); | ||||
|         Spatial cancelButtonSpatial = app.getGuiNode().getChild("CancelButton"); | ||||
|         assertNotNull("Der 'Abbrechen'-Button sollte existieren", cancelButtonSpatial); | ||||
|  | ||||
|         logic.cancelGameCreation(); | ||||
|         if (cancelButtonSpatial instanceof Button) { | ||||
|             Button cancelButton = (Button) cancelButtonSpatial; | ||||
|             cancelButton.click(); | ||||
|  | ||||
|         verify(clientSenderMock, times(1)).returnToMainMenu(); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testEnterPlayerLobby() { | ||||
|         doNothing().when(clientSenderMock).enterLobby(); | ||||
|  | ||||
|         logic.enterLobby(); | ||||
|  | ||||
|         verify(clientSenderMock, times(1)).enterLobby(); | ||||
|             Spatial mainMenu = app.getGuiNode().getChild("MainMenu"); | ||||
|             assertNotNull("Das Hauptmenü sollte nach dem Abbrechen des Spiels sichtbar sein", mainMenu); | ||||
|         } | ||||
|         else { | ||||
|             throw new AssertionError("'CancelButton' ist kein Button-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|         @Test | ||||
|         // T010: UC-game-10 - Testet, ob der Spieler die Spielerlobby betreten kann | ||||
|         public void testEnterPlayerLobby() { | ||||
|             app.receivedEvent(new pp.monopoly.notification.ClientStateEvent(pp.monopoly.notification.ClientStateEvent.State.LOBBY)); | ||||
|  | ||||
|             Spatial playerLobby = app.getGuiNode().getChild("PlayerLobby"); | ||||
|             assertNotNull("Die Spielerlobby sollte nach dem Beitritt sichtbar sein", playerLobby); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         @Test | ||||
|         // T010: UC-game-10 - Testet, ob der Spieler die Spielerlobby betreten kann | ||||
|         public void testEnterPlayerLobby() { | ||||
|             // Simuliert den Empfang eines ClientStateEvent für den Lobby-State | ||||
|             app.receivedEvent(new ClientStateEvent(ClientStateEvent.State.LOBBY)); | ||||
|  | ||||
|             // Überprüft, ob das Lobby-UI sichtbar ist | ||||
|             Spatial playerLobby = app.getGuiNode().getChild("PlayerLobby"); | ||||
|             assertNotNull("Die Spielerlobby sollte nach dem Beitritt sichtbar sein", playerLobby); | ||||
|     */ | ||||
|     @Test | ||||
|     // T011: UC-game-11 - Testet, ob der hostende Spieler einen Startbetrag eingeben kann | ||||
|     public void testEnterStartingCapital() { | ||||
|         int startingCapital = 1500; | ||||
|         logic.setStartingCapital(startingCapital); | ||||
|         Spatial startingCapitalField = app.getGuiNode().getChild("StartingCapitalField"); | ||||
|         assertNotNull("Das Eingabefeld für den Startbetrag sollte existieren", startingCapitalField); | ||||
|  | ||||
|         assertEquals("The starting capital should be correctly set.", startingCapital, logic.getStartingCapital()); | ||||
|         if (startingCapitalField instanceof TextField) { | ||||
|             TextField startingCapitalInput = (TextField) startingCapitalField; | ||||
|             startingCapitalInput.setText("1500"); | ||||
|  | ||||
|             assertEquals("Der eingegebene Startbetrag sollte '1500' sein", "1500", startingCapitalInput.getText()); | ||||
|         } | ||||
|         else { | ||||
|             throw new AssertionError("'StartingCapitalField' ist kein TextField-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T012: UC-game-12 - Testet, ob der Spieler den Startbetrag um 100 € erhöhen kann | ||||
|     public void testIncreaseStartingCapital() { | ||||
|         logic.setStartingCapital(1500); | ||||
|         logic.increaseStartingCapital(); | ||||
|         Spatial increaseButton = app.getGuiNode().getChild("IncreaseCapitalButton"); | ||||
|         assertNotNull("Der 'Erhöhen'-Button sollte existieren", increaseButton); | ||||
|  | ||||
|         assertEquals("The starting capital should increase by 100.", 1600, logic.getStartingCapital()); | ||||
|         if (increaseButton instanceof Button) { | ||||
|             Button increaseCapitalButton = (Button) increaseButton; | ||||
|             increaseCapitalButton.click(); | ||||
|  | ||||
|             Spatial startingCapitalField = app.getGuiNode().getChild("StartingCapitalField"); | ||||
|             if (startingCapitalField instanceof TextField) { | ||||
|                 TextField startingCapitalInput = (TextField) startingCapitalField; | ||||
|                 assertEquals("Der Startbetrag sollte um 100 erhöht worden sein", "1600", startingCapitalInput.getText()); | ||||
|             } | ||||
|             else { | ||||
|                 throw new AssertionError("'StartingCapitalField' ist kein TextField-Objekt."); | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             throw new AssertionError("'IncreaseCapitalButton' ist kein Button-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T013: UC-game-13 - Testet, ob der Spieler den Startbetrag um 100 € senken kann | ||||
|     public void testDecreaseStartingCapital() { | ||||
|         logic.setStartingCapital(1500); | ||||
|         logic.decreaseStartingCapital(); | ||||
|         Spatial decreaseButton = app.getGuiNode().getChild("DecreaseCapitalButton"); | ||||
|         assertNotNull("Der 'Senken'-Button sollte existieren", decreaseButton); | ||||
|  | ||||
|         assertEquals("The starting capital should decrease by 100.", 1400, logic.getStartingCapital()); | ||||
|         if (decreaseButton instanceof Button) { | ||||
|             Button decreaseCapitalButton = (Button) decreaseButton; | ||||
|             decreaseCapitalButton.click(); | ||||
|  | ||||
|             Spatial startingCapitalField = app.getGuiNode().getChild("StartingCapitalField"); | ||||
|             if (startingCapitalField instanceof TextField) { | ||||
|                 TextField startingCapitalInput = (TextField) startingCapitalField; | ||||
|                 assertEquals("Der Startbetrag sollte um 100 gesenkt worden sein", "1400", startingCapitalInput.getText()); | ||||
|             } | ||||
|             else { | ||||
|                 throw new AssertionError("'StartingCapitalField' ist kein TextField-Objekt."); | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             throw new AssertionError("'DecreaseCapitalButton' ist kein Button-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T014: UC-game-14 - Testet, ob die Standard-Spielernamen korrekt voreingestellt sind | ||||
|     public void testDefaultPlayerName() { | ||||
|         logic.addPlayer("Player 1"); | ||||
|         Spatial playerNameField = app.getGuiNode().getChild("PlayerNameField"); | ||||
|         assertNotNull("Das Eingabefeld für den Spielernamen sollte existieren", playerNameField); | ||||
|  | ||||
|         assertTrue("The player name should be correctly set.", logic.getPlayerNames().contains("Player 1")); | ||||
|         if (playerNameField instanceof TextField) { | ||||
|             TextField playerNameInput = (TextField) playerNameField; | ||||
|             assertEquals("Der voreingestellte Spielername sollte 'Spieler 1' sein", "Spieler 1", playerNameInput.getText()); | ||||
|         } | ||||
|         else { | ||||
|             throw new AssertionError("'PlayerNameField' ist kein TextField-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T015: UC-game-15 - Testet, ob der Spieler einen Anzeigenamen eingeben kann | ||||
|     public void testEnterDisplayName() { | ||||
|         String displayName = "JohnDoe"; | ||||
|         logic.setPlayerName(displayName); | ||||
|         Spatial displayNameField = app.getGuiNode().getChild("DisplayNameField"); | ||||
|         assertNotNull("Das Eingabefeld für den Anzeigenamen sollte existieren", displayNameField); | ||||
|  | ||||
|         assertEquals("The display name should be correctly set.", displayName, logic.getPlayerName()); | ||||
|         if (displayNameField instanceof TextField) { | ||||
|             TextField displayNameInput = (TextField) displayNameField; | ||||
|             displayNameInput.setText("MaxMustermann"); | ||||
|  | ||||
|             assertEquals("Der eingegebene Anzeigename sollte 'MaxMustermann' sein", "MaxMustermann", displayNameInput.getText()); | ||||
|         } | ||||
|         else { | ||||
|             throw new AssertionError("'DisplayNameField' ist kein TextField-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T016: UC-game-16 - Testet, ob eine Warnung angezeigt wird, wenn ein Spieler einen bereits belegten Namen eingibt | ||||
|     public void testDuplicateNameEntry() { | ||||
|         logic.addPlayer("Player 1"); | ||||
|         boolean result = logic.addPlayer("Player 1"); | ||||
|         Spatial playerNameField = app.getGuiNode().getChild("PlayerNameField"); | ||||
|         assertNotNull("Das Eingabefeld für den Spielernamen sollte existieren", playerNameField); | ||||
|  | ||||
|         assertTrue("Duplicate names should not be allowed.", !result); | ||||
|         if (playerNameField instanceof TextField) { | ||||
|             TextField playerNameInput = (TextField) playerNameField; | ||||
|             playerNameInput.setText("Spieler 1"); | ||||
|             app.getGuiNode().getChild("AddPlayerButton").click(); // Spieler hinzufügen | ||||
|             playerNameInput.setText("Spieler 1"); | ||||
|             app.getGuiNode().getChild("AddPlayerButton").click(); // Spieler mit gleichem Namen hinzufügen | ||||
|  | ||||
|             Spatial warning = app.getGuiNode().getChild("DuplicateNameWarning"); | ||||
|             assertNotNull("Es sollte eine Warnung angezeigt werden, wenn ein Name doppelt vergeben wird", warning); | ||||
|         } | ||||
|         else { | ||||
|             throw new AssertionError("'PlayerNameField' ist kein TextField-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T017: UC-game-17 - Testet, ob der Spieler eine verfügbare Spielfigurfarbe auswählen kann | ||||
|     public void testSelectPlayerColor() { | ||||
|         logic.addPlayer("Player 1"); | ||||
|         boolean result = logic.setPlayerColor("Player 1", "Red"); | ||||
|         Spatial colorSelector = app.getGuiNode().getChild("ColorSelector"); | ||||
|         assertNotNull("Der Farbwähler sollte existieren", colorSelector); | ||||
|  | ||||
|         assertTrue("The player should be able to select an available color.", result); | ||||
|         if (colorSelector instanceof Button) { | ||||
|             Button colorButton = (Button) colorSelector; | ||||
|             colorButton.click(); | ||||
|  | ||||
|             Spatial selectedColor = app.getGuiNode().getChild("SelectedColor"); | ||||
|             assertNotNull("Die gewählte Farbe sollte sichtbar sein", selectedColor); | ||||
|         } | ||||
|         else { | ||||
|             throw new AssertionError("'ColorSelector' ist kein Button-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T018: UC-game-18 - Testet, ob eine belegte Spielfigurfarbe nicht ausgewählt werden kann | ||||
|     public void testSelectOccupiedColor() { | ||||
|         app.getGuiNode().getChild("ColorSelectorRed").click(); // Spieler 1 wählt Rot | ||||
|         app.getGuiNode().getChild("AddPlayerButton").click(); // Spieler 1 hinzufügen | ||||
|  | ||||
|         app.getGuiNode().getChild("ColorSelectorRed").click(); // Spieler 2 versucht Rot zu wählen | ||||
|         Spatial warning = app.getGuiNode().getChild("ColorOccupiedWarning"); | ||||
|         assertNotNull("Es sollte eine Warnung angezeigt werden, wenn eine belegte Farbe ausgewählt wird", warning); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T019: UC-game-19 - Testet, ob der Spieler eine Spielfigur auswählen kann | ||||
|     public void testSelectPlayerToken() { | ||||
|         Spatial tokenSelector = app.getGuiNode().getChild("TokenSelector"); | ||||
|         assertNotNull("Der Token-Wähler sollte existieren", tokenSelector); | ||||
|  | ||||
|         if (tokenSelector instanceof Button) { | ||||
|             Button tokenButton = (Button) tokenSelector; | ||||
|             tokenButton.click(); | ||||
|  | ||||
|             Spatial selectedToken = app.getGuiNode().getChild("SelectedToken"); | ||||
|             assertNotNull("Die gewählte Spielfigur sollte sichtbar sein", selectedToken); | ||||
|         } | ||||
|         else { | ||||
|             throw new AssertionError("'TokenSelector' ist kein Button-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T020: UC-game-20 - Testet, ob eine belegte Spielfigur nicht ausgewählt werden kann | ||||
|     public void testSelectOccupiedToken() { | ||||
|         app.getGuiNode().getChild("TokenSelectorShip").click(); | ||||
|         app.getGuiNode().getChild("AddPlayerButton").click(); | ||||
|  | ||||
|         app.getGuiNode().getChild("TokenSelectorShip").click(); | ||||
|         Spatial warning = app.getGuiNode().getChild("TokenOccupiedWarning"); | ||||
|         assertNotNull("Es sollte eine Warnung angezeigt werden, wenn eine belegte Spielfigur ausgewählt wird", warning); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T021: UC-game-14 - Überprüft, ob der Spieler zur „Spiel erstellen“-Ansicht zurückkehrt, wenn Abbrechen gedrückt wird | ||||
|     public void testCancelPlayerLobby() { | ||||
|         Spatial cancelButtonSpatial = app.getGuiNode().getChild("CancelLobbyButton"); | ||||
|         assertNotNull("Der 'Abbrechen'-Button in der Lobby sollte existieren", cancelButtonSpatial); | ||||
|  | ||||
|         if (cancelButtonSpatial instanceof Button) { | ||||
|             Button cancelButton = (Button) cancelButtonSpatial; | ||||
|             cancelButton.click(); | ||||
|  | ||||
|             Spatial mainMenu = app.getGuiNode().getChild("MainMenu"); | ||||
|             assertNotNull("Das Hauptmenü sollte nach dem Abbrechen der Lobby sichtbar sein", mainMenu); | ||||
|         } | ||||
|         else { | ||||
|             throw new AssertionError("'CancelLobbyButton' ist kein Button-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T022: UC-game-15 - Überprüft, ob das Spielmenü in der Lobby durch Drücken der ESC-Taste geöffnet wird | ||||
|     public void testOpenLobbyMenuWithESC() { | ||||
|         app.escape(true); // Simuliert das Drücken der ESC-Taste | ||||
|  | ||||
|         Spatial lobbyMenu = app.getGuiNode().getChild("LobbyMenu"); | ||||
|         assertNotNull("Das Lobby-Menü sollte sichtbar sein, nachdem ESC in der Lobby gedrückt wurde", lobbyMenu); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T023: UC-game-16 - Testet, ob der Spieler die Auswahl der Spielfigur bestätigen kann | ||||
|     public void testPlayerReadyConfirmation() { | ||||
|         Spatial confirmButtonSpatial = app.getGuiNode().getChild("ConfirmTokenButton"); | ||||
|         assertNotNull("Der 'Bestätigen'-Button für die Spielfigur sollte existieren", confirmButtonSpatial); | ||||
|  | ||||
|         if (confirmButtonSpatial instanceof Button) { | ||||
|             Button confirmButton = (Button) confirmButtonSpatial; | ||||
|             confirmButton.click(); | ||||
|  | ||||
|             Spatial readyStatus = app.getGuiNode().getChild("PlayerReadyStatus"); | ||||
|             assertNotNull("Der Status 'Bereit' sollte angezeigt werden, nachdem die Spielfigur bestätigt wurde", readyStatus); | ||||
|         } | ||||
|         else { | ||||
|             throw new AssertionError("'ConfirmTokenButton' ist kein Button-Objekt."); | ||||
|         } | ||||
|     } | ||||
|         @Test | ||||
|         // T024: UC-game-16 - Überprüft, ob das Spiel startet, wenn alle Spieler ihre Auswahl bestätigt haben | ||||
|         public void testAllPlayersReady() { | ||||
|             app.receivedEvent(new pp.monopoly.notification.ClientStateEvent(pp.monopoly.notification.ClientStateEvent.State.ALL_PLAYERS_READY)); | ||||
|  | ||||
|             Spatial gameScreen = app.getGuiNode().getChild("GameScreen"); | ||||
|             assertNotNull("Das Spiel sollte starten, wenn alle Spieler bereit sind", gameScreen); | ||||
|         } | ||||
|         @Test | ||||
|         // T025: UC-game-17 - Testet, ob das Einstellungen-Menü während des Spiels geöffnet wird | ||||
|         public void testOpenMainGameSettings () { | ||||
|             app.escape(true); | ||||
|  | ||||
|             Spatial settingsButton = app.getGuiNode().getChild("SettingsButton"); | ||||
|             assertNotNull("Der 'Einstellungen'-Button sollte im Spielmenü vorhanden sein", settingsButton); | ||||
|  | ||||
|             if (settingsButton instanceof Button) { | ||||
|                 ((Button) settingsButton).click(); | ||||
|                 Spatial settingsMenu = app.getGuiNode().getChild("SettingsMenu"); | ||||
|                 assertNotNull("Das Einstellungen-Menü sollte im Spiel angezeigt werden", settingsMenu); | ||||
|             } | ||||
|             else { | ||||
|                 throw new AssertionError("'SettingsButton' ist kein Button-Objekt."); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     @Test | ||||
| // T026: UC-gameplay-01 - Überprüft, ob der Spieler erfolgreich würfeln kann | ||||
|     public void testRollDice() { | ||||
|         Spatial rollDiceButton = app.getGuiNode().getChild("RollDiceButton"); | ||||
|         assertNotNull("Der 'Würfeln'-Button sollte sichtbar sein", rollDiceButton); | ||||
|  | ||||
|         if (rollDiceButton instanceof Button) { | ||||
|             ((Button) rollDiceButton).click(); // Simuliert einen Würfelwurf | ||||
|             Spatial diceResult = app.getGuiNode().getChild("DiceResult"); | ||||
|             assertNotNull("Das Ergebnis des Würfelwurfs sollte angezeigt werden", diceResult); | ||||
|         } | ||||
|     } | ||||
|     @Test | ||||
| // T027: UC-gameplay-01 - Überprüft, ob der aktive Spieler die richtige Anzahl an Feldern basierend auf dem Wurf bewegt | ||||
|     public void testMovePlayerAutomatically() { | ||||
|         Game game = new Game(); // Initialisiert ein neues Spiel | ||||
|         PlayerHandler playerHandler = game.getPlayerHandler(); // Holt den PlayerHandler, der die Spieler verwaltet | ||||
|  | ||||
|         Player activePlayer = playerHandler.getActivePlayer(); // Holt den aktuellen aktiven Spieler | ||||
|         assertNotNull("Es sollte einen aktiven Spieler geben", activePlayer); | ||||
|  | ||||
|         DiceResult diceResult = game.rollDice(); // Würfelwurf simulieren | ||||
|         int steps = diceResult.getTotal(); | ||||
|  | ||||
|         int initialPosition = activePlayer.getFieldId(); // Ursprüngliche Position des aktiven Spielers | ||||
|         playerHandler.moveActivePlayer(steps); // Bewegt den aktiven Spieler basierend auf dem Wurf | ||||
|  | ||||
|         int expectedPosition = (initialPosition + steps) % game.getGameBoard().getNumberOfFields(); // Zielposition berechnen | ||||
|         int newPosition = activePlayer.getFieldId(); | ||||
|  | ||||
|         assertEquals("Der aktive Spieler sollte sich korrekt bewegen", expectedPosition, newPosition); | ||||
|  | ||||
|         // Überprüfen, dass alle anderen Spieler im WaitForTurn-State bleiben | ||||
|         playerHandler.getPlayers().stream() | ||||
|                      .filter(player -> player != activePlayer) | ||||
|                      .forEach(player -> assertTrue("Andere Spieler sollten im WaitForTurn-State sein", player.getState() instanceof WaitForTurnState)); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
| // T028: UC-gameplay-02 - Überprüft, ob die Würfel zufällige Zahlen generieren | ||||
|     public void testGenerationDice() { | ||||
|         boolean isRandom = false; | ||||
|         DiceResult previousResult = null; | ||||
|  | ||||
|         for (int i = 0; i < 10; i++) { | ||||
|             DiceResult currentResult = app.getGame().rollDice(); | ||||
|  | ||||
|             assertNotNull("Das Würfelergebnis sollte nicht null sein", currentResult); | ||||
|             assertTrue("Die Würfelzahl 1 sollte zwischen 1 und 6 liegen", currentResult.getDice1() >= 1 && currentResult.getDice1() <= 6); | ||||
|             assertTrue("Die Würfelzahl 2 sollte zwischen 1 und 6 liegen", currentResult.getDice2() >= 1 && currentResult.getDice2() <= 6); | ||||
|  | ||||
|             if (previousResult != null && (currentResult.getDice1() != previousResult.getDice1() || currentResult.getDice2() != previousResult.getDice2())) { | ||||
|                 isRandom = true; // Unterschiedliche Würfelwerte gefunden | ||||
|                 break; | ||||
|             } | ||||
|             previousResult = currentResult; | ||||
|         } | ||||
|         assertTrue("Die Würfelergebnisse sollten zufällig sein", isRandom); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
| // T029: UC-gameplay-03 - Überprüft, ob die richtigen Augenzahlen angezeigt werden | ||||
|     public void testDisplayResults() { | ||||
|         DiceResult result = app.getGame().rollDice(); | ||||
|  | ||||
|         assertNotNull("Das Würfelergebnis sollte nicht null sein", result); | ||||
|         assertTrue("Die Würfelzahl 1 sollte zwischen 1 und 6 liegen", result.getDice1() >= 1 && result.getDice1() <= 6); | ||||
|         assertTrue("Die Würfelzahl 2 sollte zwischen 1 und 6 liegen", result.getDice2() >= 1 && result.getDice2() <= 6); | ||||
|         assertEquals("Die Summe sollte korrekt berechnet werden", result.getDice1() + result.getDice2(), result.getTotal()); | ||||
|     } | ||||
|     @Test | ||||
|     // T030: UC-gameplay-04 - Überprüfen, ob die Summe der Würfelergebnisse korrekt berechnet wird | ||||
|     public void testSumDiceResults() { | ||||
|         Spatial rollDiceButton = app.getGuiNode().getChild("RollDiceButton"); | ||||
|         assertNotNull("Der 'Würfeln'-Button sollte sichtbar sein", rollDiceButton); | ||||
|  | ||||
|         if (rollDiceButton instanceof Button) { | ||||
|             ((Button) rollDiceButton).click(); // Simuliert einen Würfelwurf | ||||
|             Spatial diceResult1 = app.getGuiNode().getChild("DiceResult1"); | ||||
|             Spatial diceResult2 = app.getGuiNode().getChild("DiceResult2"); | ||||
|  | ||||
|             assertNotNull("Die Ergebnisse des Würfelwurfs sollten angezeigt werden", diceResult1); | ||||
|             assertNotNull("Die Ergebnisse des Würfelwurfs sollten angezeigt werden", diceResult2); | ||||
|  | ||||
|             int result1 = Integer.parseInt(diceResult1.getUserData("value").toString()); | ||||
|             int result2 = Integer.parseInt(diceResult2.getUserData("value").toString()); | ||||
|             int expectedSum = result1 + result2; | ||||
|  | ||||
|             Spatial sumDisplay = app.getGuiNode().getChild("DiceSum"); | ||||
|             assertEquals("Die Summe der Würfelergebnisse sollte korrekt angezeigt werden", expectedSum, Integer.parseInt(sumDisplay.getUserData("value").toString())); | ||||
|         } else { | ||||
|             throw new AssertionError("'RollDiceButton' ist kein Button-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T031: UC-gameplay-05 - Überprüfen, ob die Würfel nach dem Wurf ausgegraut werden | ||||
|     public void testGrayOutDiceAfterRoll() { | ||||
|         Spatial rollDiceButton = app.getGuiNode().getChild("RollDiceButton"); | ||||
|         assertNotNull("Der 'Würfeln'-Button sollte sichtbar sein", rollDiceButton); | ||||
|  | ||||
|         if (rollDiceButton instanceof Button) { | ||||
|             ((Button) rollDiceButton).click(); // Simuliert einen Würfelwurf | ||||
|  | ||||
|             Spatial diceDisplay = app.getGuiNode().getChild("DiceDisplay"); | ||||
|             assertNotNull("Die Würfelanzeige sollte nach dem Wurf sichtbar sein", diceDisplay); | ||||
|  | ||||
|             boolean isGrayedOut = diceDisplay.getUserData("grayedOut"); | ||||
|             assertTrue("Die Würfel sollten nach dem Wurf ausgegraut sein", isGrayedOut); | ||||
|         } else { | ||||
|             throw new AssertionError("'RollDiceButton' ist kein Button-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T032: UC-gameplay-06 - Überprüfen, ob das Würfeln eines Paschs erkannt wird | ||||
|     public void testDetectDouble() { | ||||
|         Spatial rollDiceButton = app.getGuiNode().getChild("RollDiceButton"); | ||||
|         assertNotNull("Der 'Würfeln'-Button sollte sichtbar sein", rollDiceButton); | ||||
|  | ||||
|         if (rollDiceButton instanceof Button) { | ||||
|             // Simuliert mehrere Würfe, um einen Pasch zu erkennen | ||||
|             for (int i = 0; i < 10; i++) { | ||||
|                 ((Button) rollDiceButton).click(); | ||||
|                 Spatial diceResult1 = app.getGuiNode().getChild("DiceResult1"); | ||||
|                 Spatial diceResult2 = app.getGuiNode().getChild("DiceResult2"); | ||||
|  | ||||
|                 int result1 = Integer.parseInt(diceResult1.getUserData("value").toString()); | ||||
|                 int result2 = Integer.parseInt(diceResult2.getUserData("value").toString()); | ||||
|  | ||||
|                 if (result1 == result2) { | ||||
|                     Spatial doubleIndicator = app.getGuiNode().getChild("DoubleIndicator"); | ||||
|                     assertNotNull("Ein Pasch sollte angezeigt werden, wenn zwei identische Zahlen geworfen werden", doubleIndicator); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             throw new AssertionError("'RollDiceButton' ist kein Button-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T033: UC-gameplay-06 - Überprüfen, ob der Spieler bei einem Pasch erneut würfeln darf | ||||
|     public void testDoubleRoll() { | ||||
|         Spatial rollDiceButton = app.getGuiNode().getChild("RollDiceButton"); | ||||
|         assertNotNull("Der 'Würfeln'-Button sollte sichtbar sein", rollDiceButton); | ||||
|  | ||||
|         if (rollDiceButton instanceof Button) { | ||||
|             // Simuliert das Würfeln eines Paschs | ||||
|             ((Button) rollDiceButton).click(); | ||||
|             Spatial diceResult1 = app.getGuiNode().getChild("DiceResult1"); | ||||
|             Spatial diceResult2 = app.getGuiNode().getChild("DiceResult2"); | ||||
|  | ||||
|             int result1 = Integer.parseInt(diceResult1.getUserData("value").toString()); | ||||
|             int result2 = Integer.parseInt(diceResult2.getUserData("value").toString()); | ||||
|  | ||||
|             if (result1 == result2) { // Überprüft, ob ein Pasch geworfen wurde | ||||
|                 Spatial rollAgainIndicator = app.getGuiNode().getChild("RollAgainIndicator"); | ||||
|                 assertNotNull("Der Spieler sollte bei einem Pasch erneut würfeln dürfen", rollAgainIndicator); | ||||
|             } | ||||
|         } else { | ||||
|             throw new AssertionError("'RollDiceButton' ist kein Button-Objekt."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     // T034: UC-gameplay-06 - Überprüfen, ob der Spieler nach dem dritten Pasch ins Gefängnis muss | ||||
|     public void testTripleDoubleGulag() { | ||||
|         int doubleCount = 0; | ||||
|  | ||||
|         for (int i = 0; i < 3; i++) { | ||||
|             Spatial rollDiceButton = app.getGuiNode().getChild("RollDiceButton"); | ||||
|             assertNotNull("Der 'Würfeln'-Button sollte sichtbar sein", rollDiceButton); | ||||
|  | ||||
|             if (rollDiceButton instanceof Button) { | ||||
|                 ((Button) rollDiceButton).click(); | ||||
|                 Spatial diceResult1 = app.getGuiNode().getChild("DiceResult1"); | ||||
|                 Spatial diceResult2 = app.getGuiNode().getChild("DiceResult2"); | ||||
|  | ||||
|                 int result1 = Integer.parseInt(diceResult1.getUserData("value").toString()); | ||||
|                 int result2 = Integer.parseInt(diceResult2.getUserData("value").toString()); | ||||
|  | ||||
|                 if (result1 == result2) { | ||||
|                     doubleCount++; | ||||
|                 } | ||||
|  | ||||
|                 if (doubleCount == 3) { | ||||
|                     Spatial jailIndicator = app.getGuiNode().getChild("JailIndicator"); | ||||
|                     assertNotNull("Der Spieler sollte nach dem dritten Pasch ins Gefängnis gehen", jailIndicator); | ||||
|                     break; | ||||
|                 } | ||||
|             } else { | ||||
|                 throw new AssertionError("'RollDiceButton' ist kein Button-Objekt."); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         assertTrue("Der Spieler sollte drei Paschs geworfen haben", doubleCount == 3); | ||||
|     } | ||||
|     @Test | ||||
| // T035: UC-gameplay-07 - Überprüfen, ob ein Spieler für Steuerfelder korrekt belastet wird | ||||
|     public void testTaxFieldCharges() { | ||||
|         Game game = new Game(); | ||||
|         PlayerHandler playerHandler = game.getPlayerHandler(); | ||||
|         Player activePlayer = playerHandler.getActivePlayer(); | ||||
|         assertNotNull("Es sollte einen aktiven Spieler geben", activePlayer); | ||||
|  | ||||
|         int initialBalance = activePlayer.getAccountBalance(); | ||||
|  | ||||
|         activePlayer.moveToField(game.getGameBoard().getFieldById(4)); // ID 4: Steuerfeld "Diszi" | ||||
|         game.getGameBoard().applyFieldEffect(activePlayer); | ||||
|  | ||||
|         int expectedBalance = initialBalance - 200; // Beispielsteuer: 200 € | ||||
|         assertEquals("Der Spieler sollte für das Steuerfeld korrekt belastet werden", expectedBalance, activePlayer.getAccountBalance()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
| // T036: UC-gameplay-08 - Überprüfen, ob ein Spieler korrekt ins Gefängnis geschickt wird | ||||
|     public void testGoToJailField() { | ||||
|         Game game = new Game(); | ||||
|         PlayerHandler playerHandler = game.getPlayerHandler(); | ||||
|         Player activePlayer = playerHandler.getActivePlayer(); | ||||
|         assertNotNull("Es sollte einen aktiven Spieler geben", activePlayer); | ||||
|  | ||||
|         activePlayer.moveToField(game.getGameBoard().getFieldById(30)); // ID 30: Ab ins Gefängnis | ||||
|         game.getGameBoard().applyFieldEffect(activePlayer); | ||||
|  | ||||
|         assertEquals("Der Spieler sollte ins Gefängnis geschickt werden", 10, activePlayer.getFieldId()); // ID 10: Gefängnis | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
| // T037: UC-gameplay-09 - Überprüfen, ob ein Spieler bei "Frei Parken" keine Gebühren zahlt | ||||
|     public void testFreeParking() { | ||||
|         Game game = new Game(); | ||||
|         PlayerHandler playerHandler = game.getPlayerHandler(); | ||||
|         Player activePlayer = playerHandler.getActivePlayer(); | ||||
|         assertNotNull("Es sollte einen aktiven Spieler geben", activePlayer); | ||||
|  | ||||
|         int initialBalance = activePlayer.getAccountBalance(); | ||||
|  | ||||
|         activePlayer.moveToField(game.getGameBoard().getFieldById(20)); // ID 20: Frei Parken | ||||
|         game.getGameBoard().applyFieldEffect(activePlayer); | ||||
|  | ||||
|         assertEquals("Der Spieler sollte bei 'Frei Parken' keine Gebühren zahlen", initialBalance, activePlayer.getAccountBalance()); | ||||
|     } | ||||
| } | ||||
| */ | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -2,992 +2,11 @@ package pp.monopoly.game.server; | ||||
|  | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| import org.mockito.MockedStatic; | ||||
| import pp.monopoly.message.server.DiceResult; | ||||
| import pp.monopoly.model.card.Card; | ||||
| import pp.monopoly.model.card.DeckHelper; | ||||
| import pp.monopoly.model.fields.BoardManager; | ||||
| import pp.monopoly.model.fields.EventField; | ||||
| import pp.monopoly.model.fields.FineField; | ||||
| import pp.monopoly.model.fields.GulagField; | ||||
| import pp.monopoly.model.fields.PropertyField; | ||||
| import pp.monopoly.model.fields.BuildingProperty; | ||||
|  | ||||
| import java.lang.reflect.Constructor; | ||||
| import java.lang.reflect.Field; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.Queue; | ||||
|  | ||||
| import static junit.framework.TestCase.assertSame; | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertFalse; | ||||
| import static org.junit.Assert.assertThrows; | ||||
| import static org.junit.Assert.assertTrue; | ||||
| import static org.mockito.ArgumentMatchers.any; | ||||
| import static org.mockito.ArgumentMatchers.anyInt; | ||||
| import static org.mockito.Mockito.atLeastOnce; | ||||
| import static org.mockito.Mockito.doAnswer; | ||||
| import static org.mockito.Mockito.doCallRealMethod; | ||||
| import static org.mockito.Mockito.doNothing; | ||||
| import static org.mockito.Mockito.doReturn; | ||||
| import static org.mockito.Mockito.mock; | ||||
| import static org.mockito.Mockito.mockStatic; | ||||
| import static org.mockito.Mockito.never; | ||||
| import static org.mockito.Mockito.spy; | ||||
| import static org.mockito.Mockito.times; | ||||
| import static org.mockito.Mockito.verify; | ||||
| import static org.mockito.Mockito.when; | ||||
|  | ||||
|  | ||||
| public class ServerGameLogicTest { | ||||
|  | ||||
|     private ServerGameLogic serverGameLogic; | ||||
|     private PlayerHandler playerHandler; | ||||
|     private Player player; | ||||
|     private PropertyField property; | ||||
|  | ||||
|     @Before | ||||
|     public void setUp() { | ||||
|         // Initialisierung von Abhängigkeiten | ||||
|         serverGameLogic = new ServerGameLogic(null, null); | ||||
|         playerHandler = new PlayerHandler(serverGameLogic); | ||||
|         player = new Player(1, "TestPlayer", playerHandler); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T026: Überprüfen, ob der Spieler erfolgreich würfeln kann. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testRollDice() { | ||||
|         // Act: Spieler würfelt | ||||
|         player = mock(Player.class); | ||||
|         when(player.rollDice()).thenReturn(new DiceResult(List.of(4, 3))); // Beispiel: Würfel zeigen 4 und 3 | ||||
|         DiceResult diceResult = player.rollDice(); | ||||
|  | ||||
|         // Assert: Würfelwerte liegen im Bereich von 2 bis 12 | ||||
|         assertTrue(diceResult.calcTotal() >= 2 && diceResult.calcTotal() <= 12); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T027: Überprüfen, ob der Spieler die richtige Anzahl an Feldern basierend auf dem Wurf bewegt. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testMovePlayer() { | ||||
|         // Arrange: Spieler initialisieren und Position setzen | ||||
|         player.getFieldID(); // Startfeld | ||||
|         DiceResult diceResult = new DiceResult(List.of(3, 4)); // Würfel: 3 und 4 | ||||
|  | ||||
|         // Act: Spieler bewegen | ||||
|         int newFieldID = (player.getFieldID() + diceResult.calcTotal()) % 40; // Spielfeld mit 40 Feldern | ||||
|         player.move(newFieldID); | ||||
|  | ||||
|         // Assert: Position überprüfen | ||||
|         assertEquals(newFieldID, player.getFieldID()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T028: Überprüft, ob die Würfel zufällige Zahlen generieren. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testGenerationDice() { | ||||
|         // Arrange: Statistiken für Würfel | ||||
|         int min = Integer.MAX_VALUE; | ||||
|         int max = Integer.MIN_VALUE; | ||||
|  | ||||
|         // Act: Simuliere mehrere Würfe | ||||
|         for (int i = 0; i < 1000; i++) { | ||||
|             DiceResult diceResult = new DiceResult(List.of( | ||||
|                     (int) (Math.random() * 6) + 1, | ||||
|                     (int) (Math.random() * 6) + 1 | ||||
|             )); | ||||
|             int total = diceResult.calcTotal(); | ||||
|  | ||||
|             // Erfasse den minimalen und maximalen Wert | ||||
|             min = Math.min(min, total); | ||||
|             max = Math.max(max, total); | ||||
|         } | ||||
|  | ||||
|         // Assert: Überprüfung der Zufälligkeit (Werte zwischen 2 und 12) | ||||
|         assertTrue(min >= 2); // Minimaler Wurf: 1 + 1 | ||||
|         assertTrue(max <= 12); // Maximaler Wurf: 6 + 6 | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T030: Überprüfen, ob die Summe der Würfelergebnisse korrekt berechnet wird. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testSumDiceResults() { | ||||
|         // Arrange: Teste alle möglichen Würfelkombinationen | ||||
|         for (int dice1 = 1; dice1 <= 6; dice1++) { | ||||
|             for (int dice2 = 1; dice2 <= 6; dice2++) { | ||||
|                 // Act: Simuliere die Würfelergebnisse und berechne die Summe | ||||
|                 DiceResult diceResult = new DiceResult(List.of(dice1, dice2)); | ||||
|                 int sum = diceResult.calcTotal(); | ||||
|  | ||||
|                 // Assert: Überprüfe die korrekte Summe | ||||
|                 assertEquals(dice1 + dice2, sum); // Erwartetes Ergebnis: Summe der beiden Würfel | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T031 Überprüfen, ob die Würfel nach dem Wurf ausgegraut werden | ||||
|      */ | ||||
|     @Test | ||||
|     public void testGrayOutDiceAfterRoll() { | ||||
|         //TODO | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T032: Überprüfen, ob alle Paschs (zwei identische Augenzahlen) korrekt erkannt werden. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testDetectDoubleForAllPossibleDoubles() { | ||||
|         // Act & Assert: Überprüfe für alle möglichen Paschs (1-1 bis 6-6) | ||||
|         for (int i = 1; i <= 6; i++) { | ||||
|             DiceResult diceResult = new DiceResult(List.of(i, i)); // Pasch mit zwei gleichen Zahlen | ||||
|             assertTrue("Pasch wurde nicht korrekt erkannt für " + i + "-" + i, diceResult.isDoublets()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T033: Überprüfen, ob ein Spieler bei einem Pasch erneut würfeln darf. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testDoubleRoll() { | ||||
|         // Arrange: Mock für Player erstellen | ||||
|         Player mockPlayer = mock(Player.class); | ||||
|  | ||||
|         // Würfel-Ergebnis simulieren | ||||
|         DiceResult doubleResult = new DiceResult(List.of(6, 6)); | ||||
|         when(mockPlayer.rollDice()).thenReturn(doubleResult); // rollDice wird gemockt | ||||
|  | ||||
|         // Act: Spieler würfelt | ||||
|         DiceResult result = mockPlayer.rollDice(); | ||||
|  | ||||
|         // Assert: Überprüfen, ob Pasch erkannt wird | ||||
|         assertTrue(result.isDoublets()); // Pasch sollte erkannt werden | ||||
|         verify(mockPlayer, times(1)).rollDice(); // Sicherstellen, dass rollDice genau einmal aufgerufen wurde | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T034: Überprüfen, ob ein Spieler nach dem dritten Pasch ins Gulag kommt. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testTripleDoubleGulag() { | ||||
|         // Arrange: Spieler-Mock erstellen | ||||
|         Player mockedPlayer = mock(Player.class); | ||||
|  | ||||
|         // Drei aufeinanderfolgende Paschs simulieren | ||||
|         when(mockedPlayer.rollDice()) | ||||
|                 .thenReturn(new DiceResult(List.of(2, 2))) // Erster Pasch | ||||
|                 .thenReturn(new DiceResult(List.of(5, 5))) // Zweiter Pasch | ||||
|                 .thenReturn(new DiceResult(List.of(6, 6))); // Dritter Pasch | ||||
|  | ||||
|         // Act: Spieler würfelt dreimal | ||||
|         boolean firstDouble = mockedPlayer.rollDice().isDoublets(); | ||||
|         boolean secondDouble = mockedPlayer.rollDice().isDoublets(); | ||||
|         boolean thirdDouble = mockedPlayer.rollDice().isDoublets(); | ||||
|  | ||||
|         // Spieler wird ins Jail bewegt, wenn drei Paschs gewürfelt wurden | ||||
|         if (firstDouble && secondDouble && thirdDouble) { | ||||
|             mockedPlayer.movePos(10); // Jail-Position im Spiel | ||||
|         } | ||||
|  | ||||
|         // Assert: Spieler ist nach dem dritten Pasch im Jail | ||||
|         assertTrue(firstDouble); | ||||
|         assertTrue(secondDouble); | ||||
|         assertTrue(thirdDouble); | ||||
|         verify(mockedPlayer, times(1)).movePos(10); // Spieler sollte genau einmal ins Jail bewegt werden | ||||
|     } | ||||
|     /* | ||||
|     /** | ||||
|      * T035: Überprüft, ob der Spieler ein Grundstück kaufen kann. | ||||
|      */ | ||||
|     /* | ||||
|     @Test | ||||
|     public void testBuyProperty() { | ||||
|         // Arrange | ||||
|         Player player = mock(Player.class); | ||||
|         PropertyField propertyField = mock(PropertyField.class); | ||||
|         List<PropertyField> properties = new ArrayList<>(); // Liste der Immobilien | ||||
|  | ||||
|         // Simuliere das Verhalten von getProperties() und add | ||||
|         when(player.getProperties()).thenReturn(properties); | ||||
|         when(propertyField.getOwner()).thenReturn(null); // Kein Besitzer | ||||
|         when(propertyField.getPrice()).thenReturn(200); // Preis | ||||
|         when(player.getAccountBalance()).thenReturn(500); // Spieler hat genug Geld | ||||
|  | ||||
|         // Act | ||||
|         player.buyProperty(propertyField); | ||||
|  | ||||
|         // Hinzufügen der Immobilie simulieren | ||||
|         properties.add(propertyField); | ||||
|  | ||||
|         // Assert | ||||
|         verify(propertyField).setOwner(player); // Eigentümer setzen | ||||
|         verify(player).pay(200); // Betrag abziehen | ||||
|         assertTrue(properties.contains(propertyField)); // Überprüfen, ob die Immobilie hinzugefügt wurde | ||||
|     } | ||||
|  | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * T037: Überprüft, ob der Spieler in den Gulag geschickt wird. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testGoToGulag() { | ||||
|         // Arrange | ||||
|         Player player = mock(Player.class); | ||||
|         GulagField gulagField = mock(GulagField.class); | ||||
|  | ||||
|         // Spieler wird auf ein Ereignis gesetzt, das ihn ins Gefängnis schickt | ||||
|         when(player.getFieldID()).thenReturn(30); // Beispiel: Feld 30 = Gehe-ins-Gefängnis-Feld | ||||
|  | ||||
|         // Act: Spieler wird ins Gefängnis geschickt | ||||
|         player.movePos(gulagField.getId()); | ||||
|  | ||||
|         // Assert: Überprüfe, ob der Spieler korrekt ins Gefängnis bewegt wurde | ||||
|         verify(player, times(1)).movePos(gulagField.getId()); | ||||
|         verify(player, never()).earnMoney(anyInt()); // Spieler sollte kein Geld erhalten | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T039: Überprüft, ob der Spieler nicht mehr als vier Häuser bauen kann. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testMaxBuildHouses() { | ||||
|         // Arrange: Mock des BuildingProperty | ||||
|         BuildingProperty buildingProperty = mock(BuildingProperty.class); | ||||
|  | ||||
|         // Setze Rückgabewerte für Methoden | ||||
|         when(buildingProperty.buildHouse()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false); | ||||
|  | ||||
|         // Act: Spieler versucht mehr als 4 Häuser zu bauen | ||||
|         boolean firstBuild = buildingProperty.buildHouse();  // Haus 1 | ||||
|         boolean secondBuild = buildingProperty.buildHouse(); // Haus 2 | ||||
|         boolean thirdBuild = buildingProperty.buildHouse();  // Haus 3 | ||||
|         boolean fourthBuild = buildingProperty.buildHouse(); // Haus 4 | ||||
|         boolean fifthBuild = buildingProperty.buildHouse();  // Versuch, Haus 5 zu bauen | ||||
|  | ||||
|         // Assert: Überprüfung, dass der fünfte Bau abgelehnt wird | ||||
|         assertTrue(firstBuild); | ||||
|         assertTrue(secondBuild); | ||||
|         assertTrue(thirdBuild); | ||||
|         assertTrue(fourthBuild); | ||||
|         assertFalse(fifthBuild); // Der fünfte Hausbau sollte blockiert werden | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T040: Überprüfen, ob der Spieler eine Hypothek auf ein Grundstück aufnehmen kann. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testTakeMortgage() { | ||||
|         // Arrange: Mock für Spieler und Grundstück | ||||
|         Player player = mock(Player.class); | ||||
|         BuildingProperty property = mock(BuildingProperty.class); | ||||
|  | ||||
|         // Voraussetzungen: Spieler ist der Besitzer und Grundstück ist nicht hypothekiert | ||||
|         when(property.getOwner()).thenReturn(player); | ||||
|         when(property.isMortgaged()).thenReturn(false); | ||||
|         when(property.getHypo()).thenReturn(500); | ||||
|  | ||||
|         // Act: Spieler nimmt Hypothek auf | ||||
|         property.setMortgaged(true); // Hypothek setzen | ||||
|         verify(property).setMortgaged(true); // Hypothek bestätigt | ||||
|         when(property.isMortgaged()).thenReturn(true); // Zustand simulieren | ||||
|         player.earnMoney(property.getHypo()); // Spieler erhält Geld | ||||
|  | ||||
|         // Assert: Überprüfe die Ergebnisse | ||||
|         verify(player).earnMoney(500); // Spieler erhält Hypothekenwert | ||||
|         assertTrue(property.isMortgaged()); // Hypothek erfolgreich | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T041: UC-gameplay-12 | ||||
|      * Überprüfen, ob eine Würfelanimation beim Würfeln ausgeführt wird. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testDiceRollAnimation() { | ||||
|         //TODO | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T042: UC-gameplay-13 | ||||
|      * Überprüfen, ob der Spieler beim Betreten von Steuerfeldern Steuern zahlt. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testPayTaxes() { | ||||
|         // Arrange: Mock für Spieler und Steuerfeld | ||||
|         Player player = mock(Player.class); | ||||
|         FineField taxField = mock(FineField.class); | ||||
|  | ||||
|         // Mocking: Stub für Steuerbetrag und Guthaben des Spielers | ||||
|         when(taxField.getFine()).thenReturn(200); // Steuerbetrag | ||||
|         when(player.getAccountBalance()).thenReturn(1000); // Spieler hat 1000 Guthaben | ||||
|  | ||||
|         // Mock visit() Logik, um die Zahlung auszulösen | ||||
|         doAnswer(invocation -> { | ||||
|             FineField field = invocation.getArgument(0); | ||||
|             player.pay(field.getFine()); | ||||
|             return null; | ||||
|         }).when(player).visit(any(FineField.class)); | ||||
|  | ||||
|         // Act: Spieler betritt das Steuerfeld | ||||
|         taxField.accept(player); | ||||
|         assertEquals(800, player.getAccountBalance()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T044: UC-gameplay-14 | ||||
|      * Überprüfen, ob der Spieler eine Ereigniskarte zieht und die entsprechende Aktion ausgeführt wird. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testDrawEventCard() { | ||||
|         // Arrange: Mock für Spieler und Karten | ||||
|         Player player = mock(Player.class); | ||||
|         EventField eventField = new EventField("Ereignisfeld", 1); | ||||
|  | ||||
|         // Mocking: Ereigniskarte simulieren | ||||
|         Card eventCard = mock(Card.class); | ||||
|         Queue<Card> mockCardQueue = mock(Queue.class); | ||||
|  | ||||
|         // Mock DeckHelper: Simuliere Kartenstapel | ||||
|         try (MockedStatic<DeckHelper> mockedDeckHelper = mockStatic(DeckHelper.class)) { | ||||
|             mockedDeckHelper.when(DeckHelper::drawCard).thenReturn(eventCard); | ||||
|  | ||||
|             // Mocking: Simuliere die Aktion der Karte | ||||
|             doNothing().when(eventCard).accept(any()); | ||||
|  | ||||
|             // Act: Spieler betritt das Ereignisfeld und zieht eine Karte | ||||
|             eventField.accept(player); | ||||
|             Card drawnCard = eventField.drawCard(); | ||||
|  | ||||
|             // Assert: Überprüfe die Interaktionen | ||||
|             verify(eventCard).accept(any()); // Aktion der Karte ausführen | ||||
|             assertSame(eventCard, drawnCard); // Sicherstellen, dass die gezogene Karte zurückgegeben wurde | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T043: Überprüfen, ob der Spieler die Hypothek zurückzahlt. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testPayBackMortgage() { | ||||
|         // Arrange: Mock für Spieler und Grundstück | ||||
|         Player player = mock(Player.class); | ||||
|         BuildingProperty property = mock(BuildingProperty.class); | ||||
|  | ||||
|         // Voraussetzungen: Spieler ist der Besitzer und Grundstück ist hypothekiert | ||||
|         when(property.getOwner()).thenReturn(player); | ||||
|         when(property.isMortgaged()).thenReturn(true); | ||||
|         when(property.getHypo()).thenReturn(500); | ||||
|  | ||||
|         // Act: Spieler zahlt Hypothek zurück | ||||
|         int repaymentAmount = (int) Math.round(property.getHypo() * 1.1); // Hypothek + 10% Zinsen | ||||
|         player.pay(repaymentAmount); // Spieler zahlt zurück | ||||
|         verify(player).pay(repaymentAmount); // Zahlung bestätigt | ||||
|         property.setMortgaged(false); // Hypothek wird aufgehoben | ||||
|         when(property.isMortgaged()).thenReturn(false); // Zustand simulieren | ||||
|  | ||||
|         // Assert: Überprüfe die Ergebnisse | ||||
|         verify(property).setMortgaged(false); // Hypothek aufgehoben | ||||
|         assertFalse(property.isMortgaged()); // Hypothekenstatus ist aufgehoben | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T045 - UC-gameplay-16 | ||||
|      * Testet, ob der Spieler nur ein Hotel auf einem Grundstück bauen kann. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testBuildHotel() { | ||||
|         // Arrange: Spieler und Grundstück mocken | ||||
|         Player player = mock(Player.class); | ||||
|         BuildingProperty buildingProperty = mock(BuildingProperty.class); | ||||
|  | ||||
|         // Verhalten des Mocks definieren | ||||
|         when(buildingProperty.getOwner()).thenReturn(player); // Spieler ist der Besitzer | ||||
|         when(buildingProperty.buildHotel()) | ||||
|                 .thenReturn(true)  // Erster Versuch: Hotel erfolgreich gebaut | ||||
|                 .thenReturn(false); // Zweiter Versuch: Hotelbau blockiert | ||||
|  | ||||
|         // Act: Spieler versucht, Hotels zu bauen | ||||
|         boolean firstBuildSuccess = buildingProperty.buildHotel(); // Erster Versuch | ||||
|         boolean secondBuildSuccess = buildingProperty.buildHotel(); // Zweiter Versuch | ||||
|  | ||||
|         // Assert: Überprüfen der Ergebnisse | ||||
|         assertTrue(firstBuildSuccess); // Erstes Hotel sollte erlaubt sein | ||||
|         assertFalse(secondBuildSuccess); // Zweites Hotel sollte blockiert werden | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T046: Überprüfen, ob das Spiel korrekt zum nächsten Spieler wechselt. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testSwitchTurnToNextPlayer() { | ||||
|         // Arrange | ||||
|         ServerGameLogic logic = mock(ServerGameLogic.class); | ||||
|         Player player1 = mock(Player.class); | ||||
|         Player player2 = mock(Player.class); | ||||
|         Player player3 = mock(Player.class); | ||||
|  | ||||
|         when(player1.getId()).thenReturn(1); | ||||
|         when(player2.getId()).thenReturn(2); | ||||
|         when(player3.getId()).thenReturn(3); | ||||
|  | ||||
|         // Initialisiere den PlayerHandler mit Spielern | ||||
|         PlayerHandler playerHandler = new PlayerHandler(logic); | ||||
|         playerHandler.addPlayer(player1); | ||||
|         playerHandler.addPlayer(player2); | ||||
|         playerHandler.addPlayer(player3); | ||||
|  | ||||
|         // Act | ||||
|         Player currentPlayer = playerHandler.nextPlayer(); | ||||
|  | ||||
|         // Assert | ||||
|         assertEquals(player2, currentPlayer); // Spieler 2 ist an der Reihe | ||||
|         assertEquals(player3, playerHandler.nextPlayer()); // Spieler 3 ist danach dran | ||||
|         assertEquals(player1, playerHandler.nextPlayer()); // Spieler 1 ist danach wieder dran | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T048: Überprüft, ob der Spieler korrekt die Strafzahlung entrichtet. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testPenaltyPayment() { | ||||
|         // Arrange: Mock für Spieler und die Strafe | ||||
|         Player player = mock(Player.class); | ||||
|         int penaltyAmount = 300; // Beispiel-Strafbetrag | ||||
|  | ||||
|         // Voraussetzungen: Der Spieler hat ein Konto mit genügend Guthaben | ||||
|         when(player.getAccountBalance()).thenReturn(1000); | ||||
|  | ||||
|         // Act: Spieler zahlt die Strafe | ||||
|         player.pay(penaltyAmount); | ||||
|  | ||||
|         // Assert: Überprüfe, ob der Betrag abgezogen wurde | ||||
|         verify(player).pay(penaltyAmount); | ||||
|         assertEquals(700, player.getAccountBalance() - penaltyAmount); // Neues Guthaben nach Strafzahlung | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T049: Überprüft, ob der Spieler korrekt Strafzahlungen erhält. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testReceivePenaltyPayment() { | ||||
|         // Arrange: Mock für den zahlenden und empfangenden Spieler | ||||
|         Player payingPlayer = mock(Player.class); | ||||
|         Player receivingPlayer = mock(Player.class); | ||||
|         int penaltyAmount = 200; // Beispiel-Strafbetrag | ||||
|  | ||||
|         // Voraussetzungen: Der zahlende Spieler hat genug Guthaben | ||||
|         when(payingPlayer.getAccountBalance()).thenReturn(1000); | ||||
|  | ||||
|         // Act: Strafzahlung durchführen | ||||
|         payingPlayer.pay(penaltyAmount); | ||||
|         receivingPlayer.earnMoney(penaltyAmount); | ||||
|  | ||||
|         // Assert: Überprüfen, ob der Betrag korrekt abgezogen wurde | ||||
|         verify(payingPlayer).pay(penaltyAmount); | ||||
|  | ||||
|         // Überprüfen, ob der Betrag beim Empfänger gutgeschrieben wurde | ||||
|         verify(receivingPlayer).earnMoney(penaltyAmount); | ||||
|  | ||||
|         // Optional: Überprüfen der neuen Guthabenstände | ||||
|         assertEquals(800, payingPlayer.getAccountBalance() - penaltyAmount); // Neues Guthaben des zahlenden Spielers | ||||
|         assertEquals(200, receivingPlayer.getAccountBalance() + penaltyAmount); // Neues Guthaben des empfangenden Spielers | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T050: Überprüfen, ob der Spieler das Gulag verlassen kann. | ||||
|      * | ||||
|      * / | ||||
|  | ||||
|      @Test public void testLeaveGulag() { | ||||
|      // Arrange: Mock für PlayerHandler | ||||
|      PlayerHandler handlerMock = mock(PlayerHandler.class); | ||||
|      Player player = new Player(1, handlerMock); | ||||
|  | ||||
|      // Simuliere, dass der Spieler eine "Gulag-Frei"-Karte besitzt | ||||
|      player.addJailCard(); // Spieler erhält eine "Gulag-Frei"-Karte | ||||
|      assertEquals(1, player.getNumJailCard()); // Sicherstellen, dass die Karte vorhanden ist | ||||
|  | ||||
|      // Simuliere, dass der Spieler das Gulag betritt | ||||
|      GulagField gulagFieldMock = mock(GulagField.class); | ||||
|      gulagFieldMock.accept(player); // Spieler wird in den JailState versetzt | ||||
|  | ||||
|      // Act: Spieler nutzt die "Gulag-Frei"-Karte | ||||
|      player.useJailCard(); // Spieler verlässt das Gulag durch die Karte | ||||
|  | ||||
|      // Assert: Überprüfen, ob die Karte entfernt wurde und der Spieler aktiv ist | ||||
|      assertEquals(0, player.getNumJailCard()); // Keine Karten mehr übrig | ||||
|      assertEquals(1, player.getFieldID()); // Sicherstellen, dass der Spieler nicht mehr im Gulag ist | ||||
|      } | ||||
|  | ||||
|      /** | ||||
|       * T051: UC-gameplay-23 | ||||
|       * Überprüfen, ob die Spielreihenfolge korrekt bestimmt wird. | ||||
|      */ | ||||
|     /* | ||||
|     @Test | ||||
|     public void testDetermineTurnOrder() { | ||||
|         // Arrange: Erstellen einer Liste von Spielern mit simulierten Würfel-Ergebnissen | ||||
|         PlayerHandler playerHandler = new PlayerHandler(mock(ServerGameLogic.class)); | ||||
|         Player player1 = mock(Player.class); | ||||
|         Player player2 = mock(Player.class); | ||||
|         Player player3 = mock(Player.class); | ||||
|  | ||||
|         when(player1.rollDice()).thenReturn(new DiceResult(List.of(4, 3))); // Ergebnis: 7 | ||||
|         when(player2.rollDice()).thenReturn(new DiceResult(List.of(6, 1))); // Ergebnis: 7 | ||||
|         when(player3.rollDice()).thenReturn(new DiceResult(List.of(5, 5))); // Ergebnis: 10 | ||||
|  | ||||
|         playerHandler.addPlayer(player1); | ||||
|         playerHandler.addPlayer(player2); | ||||
|         playerHandler.addPlayer(player3); | ||||
|  | ||||
|         // Act: Reihenfolge der Spieler bestimmen | ||||
|         List<Player> turnOrder = playerHandler.determineTurnOrder(); | ||||
|  | ||||
|         // Assert: Überprüfung, ob die Spieler in der korrekten Reihenfolge sortiert sind | ||||
|         assertEquals(player3, turnOrder.get(0)); // Spieler 3 hat die höchste Summe (10) | ||||
|         assertTrue(turnOrder.containsAll(List.of(player1, player2))); // Spieler 1 und 2 folgen | ||||
|         assertEquals(3, turnOrder.size()); // Überprüfung, ob alle Spieler berücksichtigt wurden | ||||
|     } | ||||
| */ | ||||
|     /** | ||||
|      * T052: UC-gameplay-24 | ||||
|      * Überprüfen, ob der Spieler Bankrott erklären kann. | ||||
|      *//* | ||||
|     @Test | ||||
|     public void testDeclareBankruptcy() { | ||||
|         // Arrange: Mock für Spieler, Bank und Besitz | ||||
|         Player player = new Player(1, "Spieler 1", mock(PlayerHandler.class)); | ||||
|         PropertyField property1 = mock(PropertyField.class); | ||||
|         PropertyField property2 = mock(PropertyField.class); | ||||
|         List<PropertyField> properties = List.of(property1, property2); | ||||
|  | ||||
|         // Spieler besitzt zwei Grundstücke und hat kein Geld mehr | ||||
|         player.earnMoney(500); // Spieler hat 500 auf dem Konto | ||||
|         when(property1.getOwner()).thenReturn(player); | ||||
|         when(property2.getOwner()).thenReturn(player); | ||||
|         player.getProperties().addAll(properties); | ||||
|  | ||||
|         // Spieler hat Schulden (z. B. 1000) | ||||
|         int debt = 1000; | ||||
|  | ||||
|         // Act: Spieler erklärt Bankrott | ||||
|         player.pay(debt); // Schulden abziehen | ||||
|         player.declareBankruptcy(); // Bankrott erklären | ||||
|  | ||||
|         // Assert: Überprüfen, ob Besitz zurückgegeben wurde und Spieler bankrott ist | ||||
|         for (PropertyField property : properties) { | ||||
|             verify(property).setOwner(null); // Besitz zurück an die Bank | ||||
|         } | ||||
|         assertTrue(player.state instanceof Player.BankruptState); // Spieler ist jetzt bankrott | ||||
|         assertEquals(0, player.getAccountBalance()); // Spieler hat kein Geld mehr | ||||
|     } | ||||
| */ | ||||
|     /** | ||||
|      * T053: UC-gameplay-25 | ||||
|      * Überprüfen, ob der Spieler aufgrund eines anderen Spielers Bankrott geht. | ||||
|      *//* | ||||
|     @Test | ||||
|     public void testBankruptcyByPlayer() { | ||||
|         // Arrange: Mock für Spieler und Besitz | ||||
|         Player player1 = new Player(1, "Spieler 1", mock(PlayerHandler.class)); // Schuldner | ||||
|         Player player2 = new Player(2, "Spieler 2", mock(PlayerHandler.class)); // Gläubiger | ||||
|         PropertyField property1 = mock(PropertyField.class); | ||||
|         PropertyField property2 = mock(PropertyField.class); | ||||
|         List<PropertyField> properties = List.of(property1, property2); | ||||
|  | ||||
|         // Spieler 1 besitzt zwei Grundstücke und hat wenig Geld | ||||
|         player1.earnMoney(500); // Spieler 1 hat 500 auf dem Konto | ||||
|         when(property1.getOwner()).thenReturn(player1); | ||||
|         when(property2.getOwner()).thenReturn(player1); | ||||
|         player1.getProperties().addAll(properties); | ||||
|  | ||||
|         // Spieler 2 ist der Gläubiger | ||||
|         player2.earnMoney(1000); // Spieler 2 hat genug Geld | ||||
|  | ||||
|         // Act: Spieler 1 zahlt an Spieler 2, bis er bankrott geht | ||||
|         int debt = 1000; // Spieler 1 schuldet Spieler 2 1000 | ||||
|         player1.pay(debt); | ||||
|         player2.earnMoney(debt); // Spieler 2 erhält das Geld | ||||
|         if (player1.getAccountBalance() < 0) { | ||||
|             player1.declareBankruptcy(); | ||||
|         } | ||||
|  | ||||
|         // Assert: Überprüfen, ob Spieler 1 bankrott ist und Spieler 2 das Geld erhalten hat | ||||
|         for (PropertyField property : properties) { | ||||
|             verify(property).setOwner(null); // Besitz von Spieler 1 zurück an die Bank | ||||
|         } | ||||
|         assertTrue(player1.state instanceof Player.BankruptState); // Spieler 1 ist bankrott | ||||
|         assertEquals(0, player1.getAccountBalance()); // Spieler 1 hat kein Geld mehr | ||||
|         assertEquals(1500, player2.getAccountBalance()); // Spieler 2 hat das Geld erhalten | ||||
|     } | ||||
| */ | ||||
|     /** | ||||
|      * T054: UC-gameplay-26 | ||||
|      * Überprüfen, ob das Spiel bei Bankrott eines Spielers mit Game Over endet. | ||||
|      */ | ||||
|     /*@Test | ||||
|     public void testGameOverBankruptcy() { | ||||
|         // Arrange: Mock für Spieler und Spiel-Logik | ||||
|         PlayerHandler playerHandler = mock(PlayerHandler.class); | ||||
|         ServerGameLogic gameLogic = mock(ServerGameLogic.class); | ||||
|         when(playerHandler.getLogic()).thenReturn(gameLogic); | ||||
|  | ||||
|         Player player1 = new Player(1, "Spieler 1", playerHandler); // Spieler, der bankrott geht | ||||
|         Player player2 = new Player(2, "Spieler 2", playerHandler); // Letzter verbleibender Spieler | ||||
|  | ||||
|         // Spieler in die PlayerHandler-Liste hinzufügen | ||||
|         List<Player> players = List.of(player1, player2); | ||||
|         when(playerHandler.getPlayerCount()).thenReturn(players.size()); | ||||
|  | ||||
|         // Spieler 1 verliert alles und erklärt Bankrott | ||||
|         player1.declareBankruptcy(); | ||||
|         players.remove(player1); // Spieler 1 wird entfernt | ||||
|         when(playerHandler.getPlayerCount()).thenReturn(players.size() - 1); | ||||
|  | ||||
|         // Act: Überprüfen, ob nur noch ein Spieler übrig ist | ||||
|         if (players.size() == 1) { | ||||
|             gameLogic.endGame(player2); // Spielende auslösen | ||||
|         } | ||||
|  | ||||
|         // Assert: Prüfen, ob das Spiel im GameOver-Zustand ist und der Gewinner korrekt gesetzt wurde | ||||
|         verify(gameLogic).setGameState(GameState.GAME_OVER); // Spielstatus auf "Game Over" setzen | ||||
|         verify(gameLogic).endGame(player2); // Gewinner ist Spieler 2 | ||||
|         assertTrue(player2.getAccountBalance() > 0); // Gewinner hat ein positives Guthaben | ||||
|     } | ||||
|     */ | ||||
|  | ||||
|     /** | ||||
|      * T056: UC-gameplay-29 | ||||
|      * Überprüfen, ob das Ereignisfeld eine zufällige Karte anzeigt und die entsprechende Aktion ausführt. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testTriggerEventTile() { | ||||
|         // Arrange: Mock für Spieler, Ereignisfeld und DeckHelper | ||||
|         Player player = mock(Player.class); | ||||
|         EventField eventField = mock(EventField.class); | ||||
|         DeckHelper deckHelper = mock(DeckHelper.class); | ||||
|         Card eventCard = mock(Card.class); // Ereigniskarte | ||||
|  | ||||
|         // Stubbing: Ereigniskarte ziehen | ||||
|         when(eventField.drawCard()).thenReturn(eventCard); | ||||
|         when(eventCard.getDescription()).thenReturn("Du bekommst 200€!"); // Beispieltext | ||||
|  | ||||
|         // Stubbing: Spieleraktion durch Ereigniskarte | ||||
|         doAnswer(invocation -> { | ||||
|             player.earnMoney(200); // Aktion: Geld dem Spieler gutschreiben | ||||
|             return null; | ||||
|         }).when(eventCard).accept(any()); | ||||
|  | ||||
|         // Act: Spieler betritt das Ereignisfeld | ||||
|         eventField.accept(player); // Spieler interagiert mit dem Ereignisfeld | ||||
|         Card drawnCard = eventField.drawCard(); // Ereigniskarte wird gezogen | ||||
|         drawnCard.accept(deckHelper); // Ereigniskarte führt ihre Aktion aus | ||||
|  | ||||
|         // Assert: Überprüfen, ob die Karte korrekt angezeigt und die Aktion ausgeführt wurde | ||||
|         assertEquals("Du bekommst 200€!", drawnCard.getDescription()); // Überprüfung der Kartenbeschreibung | ||||
|         verify(player).earnMoney(200); // Überprüfung, ob dem Spieler 200€ gutgeschrieben wurden | ||||
|     } | ||||
|     /** | ||||
|      * T057: UC-gameplay-30 | ||||
|      * Überprüfen, ob der Spieler beim Erreichen des Gulag-Feldes in den Gulag versetzt wird. | ||||
|      */ | ||||
|     /* | ||||
|     @Test | ||||
|     public void testTriggerGulagTransfer() { | ||||
|         // Arrange: Mock-Objekte erstellen | ||||
|         Player player = mock(Player.class); | ||||
|         PlayerHandler handler = mock(PlayerHandler.class); | ||||
|         ServerGameLogic logic = mock(ServerGameLogic.class); | ||||
|         BoardManager boardManager = mock(BoardManager.class); | ||||
|         GulagField gulagField = mock(GulagField.class); | ||||
|  | ||||
|         // Setup: Spieler-Setup mit Logik und Mock-Feld | ||||
|         when(handler.getLogic()).thenReturn(logic); | ||||
|         when(logic.getBoardManager()).thenReturn(boardManager); | ||||
|  | ||||
|         // Act: Spieler interagiert mit dem Gulag-Feld | ||||
|         doCallRealMethod().when(player).visit(gulagField); | ||||
|         player.visit(gulagField); // Spieler landet auf dem Gulag-Feld | ||||
|  | ||||
|         // Assert: Überprüfen, ob der Spieler in den "JailState" versetzt wird | ||||
|         verify(player).setState(any(Player.JailState.class)); | ||||
|         assertTrue(player.getState() instanceof Player.JailState); // Spieler ist jetzt im JailState | ||||
|     }*/ | ||||
|     /** | ||||
|      * T058: UC-gameplay-31 | ||||
|      * Überprüfen, ob der Spieler eine Karte von der Bank erfolgreich kaufen kann. | ||||
|      */ | ||||
|     /* | ||||
|     @Test | ||||
|     public void testBuyCard() { | ||||
|         // Arrange: Mock-Objekte für Spieler und Property erstellen | ||||
|         Player player = spy(new Player(1, mock(PlayerHandler.class))); // Verwenden Sie spy, um die reale Methode zu testen | ||||
|         BuildingProperty property = mock(BuildingProperty.class); | ||||
|  | ||||
|         // Voraussetzungen: Karte ist unbesessen und der Spieler hat genug Geld | ||||
|         when(property.getOwner()).thenReturn(null); // Karte gehört niemandem | ||||
|         when(property.getPrice()).thenReturn(1000); // Kartenpreis | ||||
|         when(player.getAccountBalance()).thenReturn(2000); // Spieler hat genug Geld | ||||
|  | ||||
|         // Act: Spieler kauft die Karte | ||||
|         player.buyProperty(property); | ||||
|  | ||||
|         // Assert: Überprüfen, ob der Spieler die Karte besitzt und das Geld abgezogen wurde | ||||
|         verify(player).pay(1000); // Geld abgezogen | ||||
|         verify(property).setOwner(player); // Spieler wird als Besitzer gesetzt | ||||
|         verify(property).getOwner(); // Prüfen, ob das Eigentümer-Attribut korrekt gesetzt wurde | ||||
|     } | ||||
|     */ | ||||
|     /** | ||||
|      * T059: UC-gameplay-32 | ||||
|      * Überprüfen, ob der Kartenerwerb fehlschlägt, wenn der Spieler nicht genug Geld hat. | ||||
|      */ | ||||
|     /*@Test | ||||
|     public void testCardPurchaseFailed() { | ||||
|         // Arrange: Mock-Objekte für Spieler und Property erstellen | ||||
|         Player player = spy(new Player(1, mock(PlayerHandler.class))); // Spy verwendet für reale Methoden | ||||
|         BuildingProperty property = mock(BuildingProperty.class); | ||||
|  | ||||
|         // Voraussetzungen: Karte gehört der Bank und Spieler hat zu wenig Geld | ||||
|         when(property.getOwner()).thenReturn(null); // Karte gehört der Bank | ||||
|         when(property.getPrice()).thenReturn(1000); // Preis der Karte | ||||
|         when(player.getAccountBalance()).thenReturn(500); // Spieler hat zu wenig Geld | ||||
|  | ||||
|         // Act & Assert: Spieler versucht, die Karte zu kaufen | ||||
|         Exception exception = assertThrows(IllegalStateException.class, () -> { | ||||
|             player.buyProperty(property); // Kaufversuch | ||||
|         }); | ||||
|  | ||||
|         // Überprüfen, ob die erwartete Ausnahme mit der korrekten Nachricht ausgelöst wurde | ||||
|         assertEquals("Property cannot be purchased", exception.getMessage()); | ||||
|  | ||||
|         // Verifizieren, dass der Besitzer nicht geändert wurde | ||||
|         verify(property, never()).setOwner(player); // Spieler darf nicht als Besitzer gesetzt werden | ||||
|  | ||||
|         // Verifizieren, dass kein Geld abgezogen wurde | ||||
|         verify(player, never()).pay(anyInt()); | ||||
|     } | ||||
|     */ | ||||
|     /** | ||||
|      * T60: Überprüfen, ob der Spieler korrekt Miete zahlt, wenn er auf einem besetzten Grundstück landet. | ||||
|      */ | ||||
|     /* | ||||
|     @Test | ||||
|     public void testPayRent() { | ||||
|         // Arrange: Erstelle Mock-Objekte für Spieler und Grundstück | ||||
|         Player tenant = spy(new Player(1, mock(PlayerHandler.class))); // Spieler, der die Miete zahlt | ||||
|         Player owner = spy(new Player(2, mock(PlayerHandler.class))); // Spieler, der die Miete erhält | ||||
|         BuildingProperty property = mock(BuildingProperty.class); // Grundstück | ||||
|  | ||||
|         // Voraussetzungen: | ||||
|         when(property.getOwner()).thenReturn(owner); // Eigentümer des Grundstücks | ||||
|         when(property.calcRent()).thenReturn(300); // Berechnete Miete beträgt 300 | ||||
|         when(tenant.getAccountBalance()).thenReturn(1000); // Mieter hat 1000 Guthaben | ||||
|         when(owner.getAccountBalance()).thenReturn(2000); // Vermieter hat 2000 Guthaben | ||||
|  | ||||
|         // Act: Spieler besucht das Grundstück | ||||
|         property.accept(tenant); | ||||
|  | ||||
|         // Assert: Überprüfen, ob die Miete korrekt verarbeitet wurde | ||||
|         verify(tenant).pay(300); // Spieler zahlt 300 | ||||
|         verify(owner).earnMoney(300); // Eigentümer erhält 300 | ||||
|         assertEquals(700, tenant.getAccountBalance()); // Mieter hat noch 700 übrig | ||||
|         assertEquals(2300, owner.getAccountBalance()); // Vermieter hat jetzt 2300 | ||||
|     } | ||||
|     */ | ||||
|     /** | ||||
|      * T61:  Überprüfen, ob der Spieler bei fehlendem Guthaben die Miete nicht zahlen kann. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testRentPaymentFailed() { | ||||
|         // Arrange: Mock-Objekte für Spieler und Grundstück | ||||
|         Player tenant = spy(new Player(1, mock(PlayerHandler.class))); // Spieler, der die Miete zahlen soll | ||||
|         Player owner = spy(new Player(2, mock(PlayerHandler.class))); // Vermieter | ||||
|         BuildingProperty property = mock(BuildingProperty.class); // Grundstück | ||||
|  | ||||
|         // Voraussetzungen | ||||
|         when(property.getOwner()).thenReturn(owner); // Eigentümer des Grundstücks | ||||
|         when(property.calcRent()).thenReturn(300); // Berechnete Miete | ||||
|         when(tenant.getAccountBalance()).thenReturn(200); // Guthaben des Mieters unzureichend | ||||
|         when(owner.getAccountBalance()).thenReturn(2000); // Guthaben des Vermieters | ||||
|  | ||||
|         // Act: Spieler besucht das Grundstück | ||||
|         property.accept(tenant); | ||||
|  | ||||
|         // Assert: Überprüfe, dass keine Zahlung stattfindet | ||||
|         verify(tenant, never()).pay(300); // Spieler zahlt nichts | ||||
|         verify(owner, never()).earnMoney(300); // Vermieter erhält nichts | ||||
|         assertEquals(200, tenant.getAccountBalance()); // Guthaben des Mieters bleibt unverändert | ||||
|         assertEquals(2000, owner.getAccountBalance()); // Guthaben des Vermieters bleibt unverändert | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T63:  Überprüfen, ob der Spieler aufgrund einer Strafe eine Runde aussetzen muss. | ||||
|      */ | ||||
|     /* | ||||
|     @Test | ||||
|     public void testSkipTurnDueToPenalty() { | ||||
|         // Arrange | ||||
|         Player player = mock(Player.class); | ||||
|         PlayerHandler handler = mock(PlayerHandler.class); | ||||
|         when(handler.nextPlayer()).thenReturn(player); // Spielerwechsel simulieren | ||||
|  | ||||
|         EventField penaltyField = mock(EventField.class); | ||||
|         ServerGameLogic logic = mock(ServerGameLogic.class); | ||||
|         when(penaltyField.accept(player)).then(invocation -> { | ||||
|             player.skipTurn(); // Spieler erhält eine Strafe und muss aussetzen | ||||
|             return null; | ||||
|         }); | ||||
|  | ||||
|         // Act | ||||
|         penaltyField.accept(player); | ||||
|  | ||||
|         // Assert | ||||
|         verify(player).skipTurn(); // Spieler muss Runde aussetzen | ||||
|     } | ||||
|     */ | ||||
|  | ||||
|      /** | ||||
|      T68: Überprüfen, ob die Anzahl der "Gulag-Frei"-Karten nach der Verwendung korrekt abgezogen wird | ||||
|      */ | ||||
|     @Test | ||||
|     public void testDeductGulagFreeCard() { | ||||
|         // Arrange | ||||
|         Player player = new Player(1, mock(PlayerHandler.class)); | ||||
|         player.addJailCard(); // Spieler besitzt eine Karte | ||||
|         player.addJailCard(); // Spieler besitzt zwei Karten | ||||
|  | ||||
|         assertEquals(2, player.getNumJailCard()); // Sicherstellen, dass Spieler 2 Karten hat | ||||
|  | ||||
|         // Act | ||||
|         player.removeJailCard(); // Spieler verwendet eine Karte | ||||
|  | ||||
|         // Assert | ||||
|         assertEquals(1, player.getNumJailCard()); // Anzahl der Karten sollte um 1 reduziert sein | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * T070: Überprüfen, ob der Spieler erfolgreich aus dem Gulag rauswürfeln kann. | ||||
|      */ | ||||
|     /* | ||||
|     @Test | ||||
|     public void testRollToExitGulag() { | ||||
|         // Arrange | ||||
|         Player player = new Player(1, mock(PlayerHandler.class)); | ||||
|         player.addJailCard(); | ||||
|         player.state = player.new JailState(); | ||||
|  | ||||
|         DiceResult successfulRoll = new DiceResult(List.of(3, 3)); // Doppelte gewürfelt | ||||
|         when(player.rollDice()).thenReturn(successfulRoll); | ||||
|  | ||||
|         // Act | ||||
|         DiceResult rollResult = player.rollDice(); | ||||
|  | ||||
|         // Assert | ||||
|         assertTrue(rollResult.isDoublets()); // Sicherstellen, dass doppelte gewürfelt wurde | ||||
|         assertTrue(player.state instanceof Player.ActiveState); // Spieler ist jetzt aktiv | ||||
|     } | ||||
|      */ | ||||
|     /** | ||||
|      * T071: Überprüfen, ob das Rauswürfeln aus dem Gulag fehlschlägt. | ||||
|      */ | ||||
|     /* | ||||
|     @Test | ||||
|     public void testFailRollToExitGulag() { | ||||
|         // Arrange | ||||
|         Player player = new Player(1, mock(PlayerHandler.class)); | ||||
|         player.state = player.new JailState(); | ||||
|  | ||||
|         DiceResult unsuccessfulRoll = new DiceResult(List.of(1, 2)); // Keine Doppel | ||||
|         when(player.rollDice()).thenReturn(unsuccessfulRoll); | ||||
|  | ||||
|         // Act | ||||
|         DiceResult rollResult = player.rollDice(); | ||||
|  | ||||
|         // Assert | ||||
|         assertFalse(rollResult.isDoublets()); // Sicherstellen, dass keine Doppel gewürfelt wurden | ||||
|         assertTrue(player.state instanceof Player.JailState); // Spieler bleibt im Gulag | ||||
|     } | ||||
|  | ||||
|      */ | ||||
|     /** | ||||
|      * T072: Überprüfen, ob der Spieler durch Zahlung erfolgreich das Gulag verlassen kann. | ||||
|      */ | ||||
|     /* | ||||
|     @Test | ||||
|     public void testPayToExitGulag() { | ||||
|         // Arrange | ||||
|         Player player = new Player(1, mock(PlayerHandler.class)); | ||||
|         player.state = player.new JailState(); | ||||
|         player.earnMoney(500); // Spieler hat genug Geld | ||||
|  | ||||
|         // Act | ||||
|         player.payBail(); | ||||
|  | ||||
|         // Assert | ||||
|         assertTrue(player.state instanceof Player.ActiveState); // Spieler ist jetzt aktiv | ||||
|         assertEquals(0, player.getAccountBalance()); // Geld korrekt abgezogen | ||||
|     } | ||||
|  | ||||
|      */ | ||||
|     /** | ||||
|      * T073: Überprüfen, ob der Ausstieg aus dem Gulag durch Zahlung fehlschlägt, wenn nicht genug Geld vorhanden ist. | ||||
|      */ | ||||
|     /* | ||||
|     @Test | ||||
|     public void testFailPayToExitGulag() { | ||||
|         // Arrange | ||||
|         Player player = new Player(1, mock(PlayerHandler.class)); | ||||
|         player.state = player.new JailState(); | ||||
|         player.pay(100); // Spieler hat kein Geld mehr | ||||
|  | ||||
|         // Act & Assert | ||||
|         assertThrows(IllegalStateException.class, () -> player.payBail()); | ||||
|         assertTrue(player.state instanceof Player.JailState); // Spieler bleibt im Gulag | ||||
|     } | ||||
|  | ||||
|      */ | ||||
|     /* | ||||
|     /** | ||||
|      * T074: Überprüfen, ob der Spieler eine "Gulag-Frei"-Karte erfolgreich nutzen kann. | ||||
|      */ | ||||
|     /* | ||||
|     @Test | ||||
|     public void testUseGulagFreeCardToExit() { | ||||
|         // Arrange | ||||
|         Player player = new Player(1, mock(PlayerHandler.class)); | ||||
|         player.state = player.new JailState(); | ||||
|         player.addJailCard(); // Spieler besitzt eine Karte | ||||
|  | ||||
|         // Act | ||||
|         player.useJailCard(); | ||||
|  | ||||
|         // Assert | ||||
|         assertEquals(0, player.getNumJailCard()); // Karte wurde verbraucht | ||||
|         assertTrue(player.state instanceof Player.ActiveState); // Spieler ist jetzt aktiv | ||||
|     } | ||||
|  | ||||
|      */ | ||||
|     /** | ||||
|      * T075: Überprüfen, ob der Spieler das Gulag nicht verlassen kann, wenn keine "Gulag-Frei"-Karten verfügbar sind. | ||||
|      */ | ||||
|     /* | ||||
|     @Test | ||||
|     public void testFailUseGulagFreeCardToExit() { | ||||
|         // Arrange | ||||
|         Player player = new Player(1, mock(PlayerHandler.class)); | ||||
|         player.state = player.new JailState(); | ||||
|  | ||||
|         // Act & Assert | ||||
|         assertThrows(IllegalStateException.class, () -> player.useJailCard()); | ||||
|         assertTrue(player.state instanceof Player.JailState); // Spieler bleibt im Gulag | ||||
|     } | ||||
|  | ||||
|      */ | ||||
|  | ||||
| } | ||||
| @@ -26,7 +26,6 @@ import com.jme3.network.serializing.Serializer; | ||||
|  | ||||
| import pp.monopoly.MonopolyConfig; | ||||
| import pp.monopoly.game.server.Player; | ||||
| import pp.monopoly.game.server.PlayerHandler; | ||||
| import pp.monopoly.game.server.ServerGameLogic; | ||||
| import pp.monopoly.game.server.ServerSender; | ||||
| import pp.monopoly.message.client.BuyPropertyRequest; | ||||
| @@ -37,12 +36,8 @@ import pp.monopoly.message.client.RollDice; | ||||
| import pp.monopoly.message.client.TradeOffer; | ||||
| import pp.monopoly.message.client.TradeResponse; | ||||
| import pp.monopoly.message.client.ViewAssetsRequest; | ||||
| import pp.monopoly.message.server.GameStart; | ||||
| import pp.monopoly.message.server.NextPlayerTurn; | ||||
| import pp.monopoly.message.server.ServerMessage; | ||||
| import pp.monopoly.model.Figure; | ||||
| import pp.monopoly.model.IntPoint; | ||||
| import pp.monopoly.model.LimitedLinkedList; | ||||
|  | ||||
| /** | ||||
|  * Server implementing the visitor pattern as MessageReceiver for ClientMessages | ||||
| @@ -124,12 +119,6 @@ public class MonopolyServer implements MessageListener<HostedConnection>, Connec | ||||
|         Serializer.registerClass(TradeOffer.class); | ||||
|         Serializer.registerClass(TradeResponse.class); | ||||
|         Serializer.registerClass(ViewAssetsRequest.class); | ||||
|         Serializer.registerClass(GameStart.class); | ||||
|         Serializer.registerClass(LimitedLinkedList.class); | ||||
|         Serializer.registerClass(NextPlayerTurn.class); | ||||
|         Serializer.registerClass(Player.class); | ||||
|         Serializer.registerClass(Figure.class); | ||||
|         Serializer.registerClass(PlayerHandler.class); | ||||
|     } | ||||
|  | ||||
|     private void registerListeners() { | ||||
|   | ||||