diff --git a/Projekte/.run/MdgaApp.run.xml b/Projekte/.run/MdgaApp.run.xml
index 8b467373..123a07af 100644
--- a/Projekte/.run/MdgaApp.run.xml
+++ b/Projekte/.run/MdgaApp.run.xml
@@ -1,5 +1,7 @@
+
+
@@ -14,4 +16,4 @@
-
+
\ No newline at end of file
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/InitControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/InitControl.java
new file mode 100644
index 00000000..73f259ff
--- /dev/null
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/InitControl.java
@@ -0,0 +1,48 @@
+package pp.mdga.client;
+
+import com.jme3.renderer.RenderManager;
+import com.jme3.renderer.ViewPort;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.control.AbstractControl;
+
+/**
+ * An abstract control class that serves as a base for initializing spatial objects
+ * in jMonkeyEngine. This class overrides the controlUpdate and controlRender methods
+ * from the AbstractControl class, providing default empty implementations,
+ * and adds the ability to initialize spatial objects when they are set.
+ */
+public abstract class InitControl extends AbstractControl {
+
+ @Override
+ protected void controlUpdate(float tpf) {
+
+ }
+
+ @Override
+ protected void controlRender(RenderManager rm, ViewPort vp) {
+
+ }
+
+ /**
+ * Sets the spatial object to be controlled. This method also initializes the spatial
+ * if it is being set for the first time.
+ *
+ * @param spatial The spatial object to control.
+ */
+ @Override
+ public void setSpatial(Spatial spatial) {
+ if (this.spatial == null && spatial != null) {
+ super.setSpatial(spatial);
+ initSpatial();
+ }
+ }
+
+ /**
+ * Initializes the spatial object. This method can be overridden by subclasses
+ * to define custom initialization logic for the spatial.
+ * This method is called automatically when the spatial is set for the first time.
+ */
+ protected void initSpatial() {
+ // Default empty implementation. Override to add initialization logic.
+ }
+}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java
index e66c6ede..807a37c4 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java
@@ -17,11 +17,13 @@
import pp.mdga.client.board.OutlineControl;
import pp.mdga.client.board.PieceControl;
import pp.mdga.client.gui.CardControl;
+import pp.mdga.client.gui.DiceControl;
import pp.mdga.client.view.GameView;
import pp.mdga.game.BonusCard;
import pp.mdga.game.Color;
import pp.mdga.game.Piece;
import pp.mdga.notification.FinishNotification;
+import pp.mdga.notification.MovePieceNotification;
import pp.mdga.notification.SelectableCardsNotification;
import java.util.List;
@@ -92,10 +94,14 @@ public void onAction(String name, boolean isPressed, float tpf) {
}
if(name.equals("Click") && isPressed) {
if (app.getView() instanceof GameView gameView) {
+ DiceControl diceSelect = checkHover(gameView.getGuiHandler().getCardLayerCamera(), gameView.getGuiHandler().getCardLayerRootNode(), DiceControl.class);
CardControl cardLayerSelect = checkHover(gameView.getGuiHandler().getCardLayerCamera(), gameView.getGuiHandler().getCardLayerRootNode(), CardControl.class);
OutlineControl boardSelect = checkHover(app.getCamera(), app.getRootNode(), OutlineControl.class);
- if(cardLayerSelect != null) {
+ if(diceSelect != null) {
+ app.getModelSynchronize().rolledDice();
+ }
+ else if(cardLayerSelect != null) {
//cardSelect
if(cardLayerSelect.isSelectable()) gameView.getGuiHandler().selectCard(cardLayerSelect);
}
@@ -117,7 +123,11 @@ else if(boardSelect != null) {
}
if(name.equals("Test") &&isPressed){
if(app.getView() instanceof GameView gameView){
- app.getNotificationSynchronizer().addTestNotification(new FinishNotification(Color.NAVY));
+// gameView.getGuiHandler().rollRankingResult(Color.AIRFORCE, 1);
+// gameView.getGuiHandler().rollRankingResult(Color.ARMY, 2);
+// gameView.getGuiHandler().rollRankingResult(Color.NAVY, 3);
+// gameView.getGuiHandler().rollRankingResult(Color.CYBER, 4);
+ gameView.getGuiHandler().showDice();
}
}
}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java
index 80a44dbd..9eca1ab8 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java
@@ -1,14 +1,11 @@
package pp.mdga.client;
import com.jme3.app.SimpleApplication;
-import com.jme3.system.JmeContext;
+import com.jme3.system.AppSettings;
import com.simsilica.lemur.GuiGlobals;
import pp.mdga.client.acoustic.AcousticHandler;
-import pp.mdga.client.animation.AnimationHandler;
-import com.jme3.system.AppSettings;
import pp.mdga.client.dialog.JoinDialog;
import pp.mdga.client.view.*;
-import pp.mdga.message.server.ServerInterpreter;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
@@ -23,9 +20,6 @@ public class MdgaApp extends SimpleApplication {
private static Preferences prefs = Preferences.userNodeForPackage(JoinDialog.class);
- /** Handles animations in the application. */
- private AnimationHandler animationHandler;
-
/** Handles acoustic effects and state-based sounds. */
private AcousticHandler acousticHandler;
@@ -88,6 +82,7 @@ public static void main(String[] args) {
MdgaApp app = new MdgaApp();
app.setSettings(settings);
app.setShowSettings(false);
+ app.setPauseOnLostFocus(false);
app.start();
}
@@ -102,7 +97,6 @@ public void simpleInitApp() {
flyCam.setEnabled(false);
- animationHandler = new AnimationHandler(this);
acousticHandler = new AcousticHandler(this);
notificationSynchronizer = new NotificationSynchronizer(this);
inputSynchronizer = new InputSynchronizer(this);
@@ -163,14 +157,6 @@ public void enter(MdgaState state) {
view.enter();
}
- /**
- * Gets the animation handler.
- *
- * @return the {@link AnimationHandler} instance
- */
- public AnimationHandler getAnimationHandler() {
- return animationHandler;
- }
/**
* Gets the acoustic handler.
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/ModelSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/ModelSynchronizer.java
index e1c1b987..0b26a305 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/ModelSynchronizer.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/ModelSynchronizer.java
@@ -107,8 +107,8 @@ public void selectTsk(Color color) {
app.getGameLogic().selectTsk(color);
}
- public void unselectTsk() {
- app.getGameLogic().selectTsk(Color.NONE);
+ public void unselectTsk(Color color) {
+ app.getGameLogic().deselectTSK(color);
}
public void rolledDice() {
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java
index a704e3e8..f23eda0e 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java
@@ -60,15 +60,15 @@ private void handleLobby(Notification notification) {
if (notification instanceof TskSelectNotification n) {
lobbyView.setTaken(n.getColor(), true, n.isSelf(), n.getName());
- lobbyView.setTaken(n.getColor(), true, false, n.getName());
} else if (notification instanceof StartDialogNotification) {
app.enter(MdgaState.MAIN);
} else if (notification instanceof TskUnselectNotification n) {
lobbyView.setTaken(n.getColor(), false, false, null);
} else if(notification instanceof LobbyReadyNotification lobbyReadyNotification) {
lobbyView.setReady(lobbyReadyNotification.getColor(), lobbyReadyNotification.isReady());
- } else if (notification instanceof GameNotification) {
+ } else if (notification instanceof GameNotification n) {
app.enter(MdgaState.GAME);
+ ((GameView) app.getView()).setOwnColor(n.getOwnColor());
} else {
throw new RuntimeException("notification not expected: " + notification.toString());
}
@@ -84,6 +84,7 @@ private void handleGame(Notification notification) {
guiHandler.addCard(n.getBonusCard());
} else if (notification instanceof ActivePlayerNotification n) {
gameView.getGuiHandler().setActivePlayer(n.getColor());
+ boardHandler.showDice(n.getColor());
} else if (notification instanceof CeremonyNotification ceremonyNotification) {
app.enter(MdgaState.CEREMONY);
CeremonyView ceremonyView = (CeremonyView) app.getView();
@@ -116,22 +117,22 @@ private void handleGame(Notification notification) {
} else if (notification instanceof DrawCardNotification n) {
guiHandler.drawCard(n.getColor());
} else if (notification instanceof HomeMoveNotification home) {
- boardHandler.moveHomePiece(home.getPieceId(), home.getHomeIndex());
+ boardHandler.movePieceHomeAnim(home.getPieceId(), home.getHomeIndex());
guiHandler.hideText();
} else if (notification instanceof InterruptNotification) {
app.enter(MdgaState.LOBBY);
} else if (notification instanceof MovePieceNotification n) {
if(n.isMoveStart()) {
//StartMove
- boardHandler.movePieceStart(n.getPiece(), n.getMoveIndex());
+ boardHandler.movePieceStartAnim(n.getPiece(), n.getMoveIndex());
}
else {
//InfieldMove
- boardHandler.movePiece(n.getPiece(), n.getStartIndex(), n.getMoveIndex());
+ boardHandler.movePieceAnim(n.getPiece(), n.getStartIndex(), n.getMoveIndex());
}
guiHandler.hideText();
} else if (notification instanceof ThrowPieceNotification n) {
- boardHandler.throwPiece(n.getPieceId());
+ boardHandler.throwPieceAnim(n.getPieceId());
} else if (notification instanceof NoShieldNotification n) {
boardHandler.unshieldPiece(n.getPieceId());
} else if (notification instanceof PlayCardNotification n) {
@@ -147,10 +148,12 @@ private void handleGame(Notification notification) {
} else if (notification instanceof ResumeNotification) {
//TODO
} else if (notification instanceof RollDiceNotification n) {
+ gameView.getGuiHandler().hideText();
if(n.getColor() == gameView.getOwnColor()){
guiHandler.rollDice(n.getEyes(), n.isTurbo() ? n.getMultiplier() : -1);
}
else {
+ boardHandler.hideDice();
if (n.isTurbo()) guiHandler.showRolledDiceMult(n.getEyes(), n.getMultiplier(), n.getColor());
else guiHandler.showRolledDice(n.getEyes(), n.getColor());
}
@@ -163,7 +166,7 @@ private void handleGame(Notification notification) {
} else if (notification instanceof StartDialogNotification) {
app.enter(MdgaState.MAIN);
} else if (notification instanceof SwapPieceNotification n) {
- boardHandler.swapPieces(n.getFirstPiece(), n.getSecondPiece());
+// boardHandler.swapPieces(n.getFirstPiece(), n.getSecondPiece());
guiHandler.swap();
} else if (notification instanceof WaitMoveNotification) {
//TODO ???
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/Animation.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/Animation.java
deleted file mode 100644
index b808f9d3..00000000
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/Animation.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package pp.mdga.client.animation;
-
-abstract class Animation {
-
- abstract void play();
-
- abstract void stop();
-
- abstract boolean isOver();
-}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/AnimationHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/AnimationHandler.java
deleted file mode 100644
index cee17634..00000000
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/AnimationHandler.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package pp.mdga.client.animation;
-
-import pp.mdga.client.MdgaApp;
-
-public class AnimationHandler {
- private MdgaApp app;
-
- private Animation animation = null;
-
- public AnimationHandler(MdgaApp app) {
- this.app = app;
- }
-
- public void playAnimation(MdgaAnimation type) {
-
- }
-
- public void update() {
- if (null == animation) {
- return;
- }
-
- if (animation.isOver()) {
- animation = null;
-
- //trigger next state in model
- }
- }
-}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/EmptyAnimation.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/EmptyAnimation.java
deleted file mode 100644
index b51d5535..00000000
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/EmptyAnimation.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package pp.mdga.client.animation;
-
-class EmptyAnimation extends Animation {
- @Override
- void play() {
- //nothing
- }
-
- @Override
- void stop() {
- //nothing
- }
-
- @Override
- boolean isOver() {
- return true;
- }
-}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MdgaAnimation.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MdgaAnimation.java
deleted file mode 100644
index cddf535d..00000000
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MdgaAnimation.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package pp.mdga.client.animation;
-
-public enum MdgaAnimation {
-}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java
new file mode 100644
index 00000000..8aea4efc
--- /dev/null
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java
@@ -0,0 +1,109 @@
+package pp.mdga.client.animation;
+
+import com.jme3.math.Vector3f;
+import pp.mdga.client.InitControl;
+
+/**
+ * A control that smoothly moves a spatial from an initial position to an end position
+ * using a quadratic interpolation, with the option to perform an action after the movement is complete.
+ * The movement path includes an intermediate "middle" position at a specified height.
+ *
+ *
Movement speed can be adjusted by modifying the MOVE_SPEED constant. The movement easing follows
+ * an ease-in-out curve to create a smooth start and stop effect.
+ *
+ */
+public class MoveControl extends InitControl {
+
+ private boolean moving;
+ private final Vector3f initPos;
+ private final Vector3f endPos;
+ private final Vector3f middlePos;
+ private final static float HEIGHT = 2;
+ private final static float MOVE_SPEED = 1f;
+ private float progress = 0;
+ private final Runnable actionAfter;
+
+ /**
+ * Creates a new MoveControl with specified initial and end positions, and an action to run after the movement.
+ * The movement follows a path with a midpoint at a fixed height.
+ *
+ * @param initPos The starting position of the spatial.
+ * @param endPos The target position of the spatial.
+ * @param actionAfter A Runnable that will be executed after the movement finishes.
+ */
+ public MoveControl(Vector3f initPos, Vector3f endPos, Runnable actionAfter){
+ moving = false;
+ this.initPos = initPos;
+ this.endPos = endPos;
+ middlePos = new Vector3f(
+ (initPos.x + endPos.x) / 2,
+ (initPos.y + endPos.y) / 2,
+ HEIGHT
+ );
+ this.actionAfter = actionAfter;
+ }
+
+ /**
+ * Initializes the movement by resetting the progress and setting the moving flag to true.
+ * This is called automatically when the spatial is set.
+ */
+ @Override
+ protected void initSpatial() {
+ moving = true;
+ progress = 0;
+ }
+
+ /**
+ * Updates the movement of the spatial by interpolating its position along the defined path.
+ * The movement is smoothed using an easing function.
+ * Once the movement reaches the target, the {@link #end()} method is called to finish the movement.
+ *
+ * @param tpf Time per frame, the time elapsed since the last frame.
+ */
+ @Override
+ protected void controlUpdate(float tpf) {
+ if(!moving) return;
+ progress += tpf * MOVE_SPEED;
+ if(progress > 1) progress = 1;
+ spatial.setLocalTranslation(quadInt(initPos,middlePos,endPos, easeInOut(progress)));
+ if(progress == 1) end();
+ }
+
+ /**
+ * Ends the movement by stopping the interpolation, running the action after the movement,
+ * and removing this control from the spatial.
+ */
+ private void end(){
+ moving = false;
+ actionAfter.run();
+ spatial.removeControl(this);
+ }
+
+ /**
+ * Performs quadratic interpolation between three points.
+ *
+ * @param p1 The initial point.
+ * @param p2 The middle point.
+ * @param p3 The final point.
+ * @param t The interpolation parameter (0 <= t <= 1).
+ * @return The interpolated point.
+ */
+ private Vector3f quadInt(Vector3f p1, Vector3f p2, Vector3f p3, float t) {
+ // Quadratic interpolation: (1-t)^2 * p1 + 2 * (1-t) * t * p2 + t^2 * p3
+ float oneMinusT = 1 - t;
+ return p1.mult(oneMinusT * oneMinusT)
+ .add(p2.mult(2 * oneMinusT * t))
+ .add(p3.mult(t * t));
+ }
+
+ /**
+ * A smooth ease-in-out function for interpolation.
+ * It accelerates and decelerates the interpolation for a smoother effect.
+ *
+ * @param x The interpolation parameter (0 <= x <= 1).
+ * @return The adjusted interpolation value.
+ */
+ private float easeInOut(float x){
+ return x < 0.5 ? 4 * x * x * x : (float) (1 - Math.pow(-2 * x + 2, 3) / 2);
+ }
+}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/SymbolControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/SymbolControl.java
similarity index 57%
rename from Projekte/mdga/client/src/main/java/pp/mdga/client/gui/SymbolControl.java
rename to Projekte/mdga/client/src/main/java/pp/mdga/client/animation/SymbolControl.java
index cfeb0ced..1abf533c 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/SymbolControl.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/SymbolControl.java
@@ -1,13 +1,23 @@
-package pp.mdga.client.gui;
+package pp.mdga.client.animation;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
-import com.jme3.renderer.RenderManager;
-import com.jme3.renderer.ViewPort;
-import com.jme3.scene.control.AbstractControl;
+import pp.mdga.client.InitControl;
import pp.mdga.game.BonusCard;
-public class SymbolControl extends AbstractControl {
+/**
+ * A control that manages the animation of symbols representing different bonus card states.
+ * The symbol can animate with zoom, rotation, and translation effects based on the state of the bonus card.
+ *
+ *
The control supports three main states: SHIELD, SWAP, and TURBO. Each state has its own specific animation logic:
+ *
+ *
SHIELD: Zooms in and out, with a scaling effect.
+ *
SWAP: Rotates the symbol 360 degrees.
+ *
TURBO: Moves the symbol along the Y-axis with a zoom effect.
+ *
+ *
+ */
+public class SymbolControl extends InitControl {
private boolean zoomingIn = false;
private boolean zoomingOut = false;
private float zoomSpeed = 1f;
@@ -18,7 +28,12 @@ public class SymbolControl extends AbstractControl {
private Quaternion initialRotation = null;
private float y = 5;
-
+ /**
+ * Updates the symbol animation based on the current bonus card state.
+ * The method calls the corresponding update method for each state (SHIELD, SWAP, TURBO).
+ *
+ * @param tpf Time per frame, the time elapsed since the last frame.
+ */
@Override
protected void controlUpdate(float tpf) {
if (state == null) return;
@@ -30,11 +45,12 @@ protected void controlUpdate(float tpf) {
}
}
- @Override
- protected void controlRender(RenderManager rm, ViewPort vp) {
-
- }
-
+ /**
+ * Updates the symbol when the state is SHIELD. The symbol zooms in and then zooms out.
+ * When the zooming out finishes, the symbol is removed from the parent spatial.
+ *
+ * @param tpf Time per frame, the time elapsed since the last frame.
+ */
private void shieldUpdate(float tpf) {
if (zoomingIn) {
progress += tpf * zoomSpeed;
@@ -57,6 +73,12 @@ private void shieldUpdate(float tpf) {
}
}
+ /**
+ * Updates the symbol when the state is SWAP. The symbol rotates 360 degrees.
+ * After the rotation finishes, the symbol is removed from the parent spatial.
+ *
+ * @param tpf Time per frame, the time elapsed since the last frame.
+ */
private void swapUpdate(float tpf) {
if (initialRotation == null) {
initialRotation = spatial.getLocalRotation().clone();
@@ -80,6 +102,12 @@ private void swapUpdate(float tpf) {
}
}
+ /**
+ * Updates the symbol when the state is TURBO. The symbol moves along the Y-axis with a zoom effect.
+ * After the movement finishes, the symbol is removed from the parent spatial.
+ *
+ * @param tpf Time per frame, the time elapsed since the last frame.
+ */
private void turboUpdate(float tpf) {
if (zoomingIn) {
progress += tpf * zoomSpeed;
@@ -103,6 +131,10 @@ private void turboUpdate(float tpf) {
}
}
+ /**
+ * Starts the SHIELD animation by zooming the symbol in and out.
+ * The symbol will first zoom in and then zoom out, and will be removed from the parent spatial once done.
+ */
public void shield() {
if (state != null) throw new RuntimeException("another state is avtive");
state = BonusCard.SHIELD;
@@ -112,6 +144,10 @@ public void shield() {
spatial.setLocalScale(1f);
}
+ /**
+ * Starts the SWAP animation by rotating the symbol 360 degrees.
+ * The symbol will rotate once and then be removed from the parent spatial.
+ */
public void swap() {
if (state != null) throw new RuntimeException("another state is avtive");
spatial.setLocalScale(3);
@@ -119,6 +155,10 @@ public void swap() {
progress = -0.2f;
}
+ /**
+ * Starts the TURBO animation by moving the symbol along the Y-axis.
+ * The symbol will move upwards and then return to its initial position.
+ */
public void turbo() {
if (state != null) throw new RuntimeException("another state is avtive");
spatial.setLocalScale(2);
@@ -128,19 +168,45 @@ public void turbo() {
progress = 0;
}
+ /**
+ * Performs linear interpolation between two values.
+ *
+ * @param start The starting value.
+ * @param end The target value.
+ * @param t The interpolation parameter (0 <= t <= 1).
+ * @return The interpolated value.
+ */
private static float lerp(float start, float end, float t) {
return (1 - t) * start + t * end;
}
+ /**
+ * Ease-out function for smoothing the interpolation.
+ *
+ * @param t The interpolation parameter (0 <= t <= 1).
+ * @return The eased value.
+ */
private static float easeOut(float t) {
return (float) Math.sqrt(1 - Math.pow(t - 1, 2));
}
+ /**
+ * Ease-in-out function for smoothing the interpolation.
+ *
+ * @param t The interpolation parameter (0 <= t <= 1).
+ * @return The eased value.
+ */
private float easeInOut(float t) {
if (t > 1) t = 1;
return (float) -(Math.cos(Math.PI * t) - 1) / 2;
}
+ /**
+ * Ease-in function for smoothing the interpolation.
+ *
+ * @param t The interpolation parameter (0 <= t <= 1).
+ * @return The eased value.
+ */
private float easeIn(float t) {
return t * t * t * t;
}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/ZoomControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/ZoomControl.java
new file mode 100644
index 00000000..eb4319cd
--- /dev/null
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/ZoomControl.java
@@ -0,0 +1,110 @@
+package pp.mdga.client.animation;
+
+import pp.mdga.client.InitControl;
+
+/**
+ * A control that applies a zoom effect to a spatial, smoothly scaling it in and out.
+ * The zoom effect can be customized with speed and scaling factor.
+ *
+ *
The control supports zooming in and out with ease-in and ease-out transitions.
+ * It starts by zooming in, and once complete, it zooms out, eventually removing the spatial from its parent when the animation ends.
+ */
+public class ZoomControl extends InitControl {
+ private boolean zoomingIn = false;
+ private boolean zoomingOut = false;
+ private float progress = 0;
+ private float zoomSpeed = 1f;
+ private float zoomFactor = 1f;
+
+ /**
+ * Constructs a new ZoomControl with the default zoom speed.
+ */
+ public ZoomControl() {
+ }
+
+ /**
+ * Constructs a new ZoomControl with a specified zoom speed.
+ *
+ * @param speed The speed at which the zoom effect occurs.
+ */
+ public ZoomControl(float speed) {
+ zoomSpeed = speed;
+ }
+
+ /**
+ * Initializes the spatial for the zoom effect. This method is called when the control is added to the spatial.
+ * It sets the zooming state to zooming in.
+ */
+ @Override
+ protected void initSpatial() {
+ zoomingIn = true;
+ }
+
+ /**
+ * Updates the zoom effect over time, either zooming in or zooming out.
+ *
+ * @param tpf Time per frame, the time elapsed since the last frame.
+ */
+ @Override
+ protected void controlUpdate(float tpf) {
+ if (zoomingIn) {
+ progress += tpf * zoomSpeed;
+ if (progress > 1) progress = 1;
+ spatial.setLocalScale(lerp(0, zoomFactor, easeOut(progress)));
+ if (progress >= 1) {
+ zoomingIn = false;
+ zoomingOut = true;
+ progress = 0;
+ }
+ } else if (zoomingOut) {
+ progress += tpf * zoomSpeed;
+ spatial.setLocalScale(lerp(zoomFactor, 0, easeIn(progress)));
+ if (progress > 1) {
+ zoomingOut = false;
+ end();
+ }
+ }
+ }
+
+ /**
+ * Ends the zoom animation by removing the spatial from its parent and the control from the spatial.
+ */
+ private void end() {
+ spatial.removeFromParent();
+ spatial.removeControl(this);
+ }
+
+ /**
+ * Performs linear interpolation between two values.
+ *
+ * @param start The starting value.
+ * @param end The target value.
+ * @param t The interpolation parameter (0 <= t <= 1).
+ * @return The interpolated value.
+ */
+ private static float lerp(float start, float end, float t) {
+ return (1 - t) * start + t * end;
+ }
+
+ /**
+ * Ease-out function for smoothing the zoom-in transition.
+ *
+ * @param x The interpolation parameter (0 <= x <= 1).
+ * @return The eased value.
+ */
+ private float easeOut(float x) {
+ return x == 1 ? 1 : (float) (1 - Math.pow(2, -10 * x));
+
+ }
+
+ /**
+ * Ease-in function for smoothing the zoom-out transition.
+ *
+ * @param x The interpolation parameter (0 <= x <= 1).
+ * @return The eased value.
+ */
+ private float easeIn(float x) {
+ return x == 0 ? 0 : (float) Math.pow(2, 10 * x - 10);
+
+ }
+}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/AssetOnMap.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/AssetOnMap.java
index d78d48fd..ac6bdf53 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/AssetOnMap.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/AssetOnMap.java
@@ -2,4 +2,7 @@
import pp.mdga.client.Asset;
+/**
+ * Record for holding Asset information
+ */
record AssetOnMap(Asset asset, int x, int y, float rot) {}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java
index 74a2223d..a00508e8 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java
@@ -9,34 +9,45 @@
import com.jme3.scene.control.AbstractControl;
import pp.mdga.client.Asset;
import pp.mdga.client.MdgaApp;
+import pp.mdga.client.animation.MoveControl;
import pp.mdga.client.gui.DiceControl;
import pp.mdga.game.Color;
+import pp.mdga.game.Piece;
import java.util.*;
+/**
+ * BoardHandler is responsible for managing the game board in the MDGA client, including handling
+ * the initialization, movement, and management of game pieces and assets.
+ * It works closely with the MdgaApp to create and manipulate 3D models of assets, track player pieces,
+ * and manage movement across the game board.
+ */
public class BoardHandler {
+ // Constants defining the grid size and elevation of the board
private static final float GRID_SIZE = 1.72f;
private static final float GRID_ELEVATION = 0.0f;
private static final String MAP_NAME = "Maps/map.mdga";
+ // The main application instance for accessing game assets and logic
private final MdgaApp app;
+ // Collection of in-game assets and board elements
private ArrayList infield;
private Map pieces;
-
private Map> colorAssetsMap;
private Map> homeNodesMap;
private Map> waitingNodesMap;
private Map> waitingPiecesMap;
+ private Map> waitingNodes;
private Map pieceColor;
- private Node rootNodeBoard;
+ private final Node rootNodeBoard;
private final Node rootNode;
-
private final FilterPostProcessor fpp;
private boolean isInitialised;
+ // Flags and lists for handling piece selection and movement
private List selectableOwnPieces;
private List selectableEnemyPieces;
private List outlineNodes;
@@ -44,6 +55,14 @@ public class BoardHandler {
private PieceControl selectedEnemyPiece;
private DiceControl diceControl;
+ /**
+ * Creates a new BoardHandler.
+ *
+ * @param app The main application instance
+ * @param rootNode The root node where the board will be attached
+ * @param fpp The post-processor for effects like shadows or filters
+ * @throws RuntimeException if the app is null
+ */
public BoardHandler(MdgaApp app, Node rootNode, FilterPostProcessor fpp) {
if(app == null) throw new RuntimeException("app is null");
@@ -54,6 +73,9 @@ public BoardHandler(MdgaApp app, Node rootNode, FilterPostProcessor fpp) {
isInitialised = false;
}
+ /**
+ * Initializes the game board by setting up the pieces and nodes.
+ */
public void init() {
isInitialised = true;
selectableOwnPieces = new ArrayList<>();
@@ -65,17 +87,30 @@ public void init() {
rootNode.attachChild(rootNodeBoard);
}
+ /**
+ * Shuts down the board handler by detaching all board-related nodes and clearing selected pieces.
+ */
public void shutdown(){
clearSelectable();
isInitialised = false;
rootNode.detachChild(rootNodeBoard);
}
+ /**
+ * Adds an asset to the map of player assets, ensuring that the player does not have too many assets.
+ *
+ * @param col The color of the player
+ * @param assetOnMap The asset to be added
+ * @throws RuntimeException if there are too many assets for the player
+ */
private void addFigureToPlayerMap(Color col, AssetOnMap assetOnMap) {
List inMap = addItemToMapList(colorAssetsMap, col, assetOnMap);
if (inMap.size() > 4) throw new RuntimeException("to many assets for " + col);
}
+ /**
+ * Initializes the map with the assets loaded from the map file and corresponding nodes.
+ */
private void initMap() {
pieces = new HashMap<>();
colorAssetsMap = new HashMap<>();
@@ -86,6 +121,12 @@ private void initMap() {
pieceColor = new HashMap<>();
diceControl = new DiceControl(app.getAssetManager());
diceControl.create(new Vector3f(0,0,0), 0.7f, true);
+ waitingNodes = new HashMap<>();
+ waitingNodes.put(Color.AIRFORCE, new HashMap<>());
+ waitingNodes.put(Color.ARMY, new HashMap<>());
+ waitingNodes.put(Color.NAVY, new HashMap<>());
+ waitingNodes.put(Color.CYBER, new HashMap<>());
+
List assetOnMaps = MapLoader.loadMap(MAP_NAME);
@@ -111,6 +152,13 @@ private void initMap() {
}
}
+ /**
+ * Converts an asset to its corresponding color.
+ *
+ * @param asset The asset to be converted
+ * @return The color associated with the asset
+ * @throws RuntimeException if the asset is invalid
+ */
private Color assetToColor(Asset asset) {
return switch (asset) {
case lw -> Color.AIRFORCE;
@@ -121,6 +169,14 @@ private Color assetToColor(Asset asset) {
};
}
+ /**
+ * Creates a 3D model of an asset and adds it to the board.
+ *
+ * @param asset The asset to be displayed
+ * @param pos The position of the asset on the board
+ * @param rot The rotation of the asset
+ * @return The Spatial representation of the asset
+ */
private Spatial createModel(Asset asset, Vector3f pos, float rot) {
String modelName = asset.getModelPath();
String texName = asset.getDiffPath();
@@ -137,10 +193,23 @@ private Spatial createModel(Asset asset, Vector3f pos, float rot) {
return model;
}
+ /**
+ * Converts grid coordinates to world space.
+ *
+ * @param x The x-coordinate on the grid
+ * @param y The y-coordinate on the grid
+ * @return The corresponding world position
+ */
private static Vector3f gridToWorld(int x, int y) {
return new Vector3f(GRID_SIZE * x, GRID_SIZE * y, GRID_ELEVATION);
}
+ /**
+ * Displays an asset on the map at the given position with the specified rotation.
+ *
+ * @param assetOnMap The asset to be displayed.
+ * @return A spatial representation of the asset at the specified location and rotation.
+ */
private Spatial displayAsset(AssetOnMap assetOnMap) {
int x = assetOnMap.x();
int y = assetOnMap.y();
@@ -162,6 +231,13 @@ private void addHomeNode(Map> map, Color color, AssetOn
if (homeNodes.size() > 4) throw new RuntimeException("too many homeNodes for " + color);
}
+ /**
+ * Calculates the rotation angle required to move a piece from one position to another.
+ *
+ * @param prev The previous position.
+ * @param next The target position.
+ * @return The rotation angle in degrees.
+ */
private float getRotationMove(Vector3f prev, Vector3f next) {
Vector3f direction = next.subtract(prev).normalizeLocal();
//I had to reverse dir.y, because then it worked.
@@ -170,6 +246,14 @@ private float getRotationMove(Vector3f prev, Vector3f next) {
return newRot;
}
+ /**
+ * Recursively moves a piece from its current index to the destination index,
+ * to keep track of the piece rotation.
+ *
+ * @param uuid The UUID of the piece to move.
+ * @param curIndex The current index of the piece.
+ * @param moveIndex The target index to move the piece to.
+ */
private void movePieceRek(UUID uuid, int curIndex, int moveIndex){
if (curIndex == moveIndex) return;
@@ -202,6 +286,12 @@ private Vector3f getWaitingPos(Color color){
return getMeanPosition(waitingNodesMap.get(color).stream().map(NodeControl::getLocation).toList());
}
+ /**
+ * Gets the mean position of a list of vectors.
+ *
+ * @param vectors The list of vectors.
+ * @return The mean position as a Vector3f.
+ */
public static Vector3f getMeanPosition(List vectors) {
if (vectors.isEmpty()) return new Vector3f(0, 0, 0);
@@ -212,9 +302,14 @@ public static Vector3f getMeanPosition(List vectors) {
return sum.divide(vectors.size());
}
- //public methods****************************************************************************************************
+ /**
+ * Adds a player to the game by associating a color and a list of UUIDs to corresponding assets and waiting nodes.
+ *
+ * @param color the color of the player
+ * @param uuid the list of UUIDs representing the player's assets
+ * @throws RuntimeException if the number of assets or waiting nodes does not match the provided UUIDs
+ */
public void addPlayer(Color color, List uuid) {
- if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized");
List playerAssets = colorAssetsMap.get(color);
if (playerAssets == null) throw new RuntimeException("Assets for Player color are not defined");
@@ -226,20 +321,34 @@ public void addPlayer(Color color, List uuid) {
for (int i = 0; i < playerAssets.size(); i++){
AssetOnMap assetOnMap = playerAssets.get(i);
+ UUID pieceUuid = uuid.get(i);
+
+ // Initialize PieceControl
PieceControl pieceControl = displayAndControl(assetOnMap, new PieceControl(assetOnMap.rot(), app.getAssetManager(), app, fpp));
pieceControl.setRotation(assetOnMap.rot());
- movePieceToNode(pieceControl, waitNodes.get(i));
- pieces.put(uuid.get(i), pieceControl);
+ // Assign piece to waiting node
+ NodeControl waitNode = getNextWaitingNode(color);
+ waitingNodes.get(color).put(pieceUuid, waitNode);
- pieceColor.put(uuid.get(i), color);
+ // Move piece to node
+ movePieceToNode(pieceControl, waitNode);
+ // Update mappings
+ pieces.put(pieceUuid, pieceControl);
+ pieceColor.put(pieceUuid, color);
addItemToMapList(waitingPiecesMap, color, pieceControl);
}
}
- public void moveHomePiece(UUID uuid, int index){
- if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized");
+ /**
+ * Moves a piece to its corresponding home node based on the given index.
+ *
+ * @param uuid the UUID of the piece to move
+ * @param index the index of the home node to move the piece to
+ * @throws RuntimeException if the UUID is not mapped to a color or if the home nodes are not properly defined
+ */
+ private void moveHomePiece(UUID uuid, int index){
Color color = pieceColor.get(uuid);
if(color == null) throw new RuntimeException("uuid is not mapped to a color");
@@ -257,90 +366,145 @@ public void moveHomePiece(UUID uuid, int index){
NodeControl lastHomeNode = homeNodes.get(homeNodes.size()-1);
pieceControl.setRotation(getRotationMove(firstHomeNode.getLocation(), lastHomeNode.getLocation()));
+ app.getModelSynchronize().animationEnd();
}
- public void movePieceStart(UUID uuid, int nodeIndex){
- if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized");
+ /**
+ * Starts the movement of a piece to a target node based on the given index.
+ *
+ * @param uuid the UUID of the piece to move
+ * @param nodeIndex the index of the target node to move the piece to
+ * @throws RuntimeException if the UUID is not mapped to a color or the piece control is not found
+ * @throws IllegalArgumentException if the node index is invalid
+ */
+ private void movePieceStart(UUID uuid, int nodeIndex){
+ // Farbe des Pieces abrufen
Color color = pieceColor.get(uuid);
- if(color == null) throw new RuntimeException("uuid is not mapped to a color");
+ if (color == null) throw new RuntimeException("UUID is not mapped to a color");
+ // PieceControl abrufen
PieceControl pieceControl = pieces.get(uuid);
- movePieceToNode(pieceControl, infield.get(nodeIndex));
+ if (pieceControl == null) throw new RuntimeException("PieceControl not found for UUID: " + uuid);
+
+ // Zielknoten abrufen und prüfen
+ if (nodeIndex < 0 || nodeIndex >= infield.size()) {
+ throw new IllegalArgumentException("Invalid nodeIndex: " + nodeIndex);
+ }
+ NodeControl targetNode = infield.get(nodeIndex);
+
+ movePieceToNode(pieceControl, targetNode);
removeItemFromMapList(waitingPiecesMap, color, pieceControl);
+ waitingNodes.get(color).remove(uuid);
+ app.getModelSynchronize().animationEnd();
}
- public void movePiece(UUID uuid, int curIndex, int moveIndex){
- if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized");
+ /**
+ * Moves a piece from its current position to the target position based on the given indexes.
+ *
+ * @param uuid the UUID of the piece to move
+ * @param curIndex the current index of the piece
+ * @param moveIndex the target index of the move
+ */
+ private void movePiece(UUID uuid, int curIndex, int moveIndex){
movePieceRek(uuid, curIndex, moveIndex);
+ app.getModelSynchronize().animationEnd();
}
- public void throwPiece(UUID uuid){
- if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized");
+ /**
+ * Throws a piece to the next available waiting node and updates the waiting node mapping.
+ *
+ * @param uuid the UUID of the piece to throw
+ * @throws RuntimeException if the UUID is not mapped to a color or if no available waiting nodes are found
+ */
+ private void throwPiece(UUID uuid){
+ // Farbe des Pieces abrufen
Color color = pieceColor.get(uuid);
- if(color == null) throw new RuntimeException("uuid is not mapped to a color");
-
+ if (color == null) throw new RuntimeException("UUID is not mapped to a color");
+ // PieceControl abrufen
PieceControl pieceControl = pieces.get(uuid);
- List waitNodes = waitingNodesMap.get(color);
- List waitPieces = waitingPiecesMap.get(color);
+ if (pieceControl == null) throw new RuntimeException("PieceControl not found for UUID: " + uuid);
- movePieceToNode(pieceControl, waitNodes.get(waitPieces.size()));
+ // Nächste freie Waiting Node abrufen
+ NodeControl nextWaitNode = getNextWaitingNode(color);
+ if (nextWaitNode == null) {
+ throw new IllegalStateException("No available waiting nodes for color: " + color);
+ }
+
+ // Bewegung durchführen
+ movePieceToNode(pieceControl, nextWaitNode);
+
+ // Waiting Nodes aktualisieren
+ waitingNodes.get(color).put(uuid, nextWaitNode);
+
+ // Synchronisation oder Animation
pieceControl.rotateInit();
+ app.getModelSynchronize().animationEnd();
}
+
+ /**
+ * Activates the shield for the specified piece.
+ *
+ * @param uuid the UUID of the piece to shield
+ */
public void shieldPiece(UUID uuid){
- if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized");
pieces.get(uuid).activateShield();
}
+ /**
+ * Deactivates the shield for the specified piece.
+ *
+ * @param uuid the UUID of the piece to unshield
+ */
public void unshieldPiece(UUID uuid){
- if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized");
pieces.get(uuid).deactivateShield();
}
+ /**
+ * Suppresses the shield for the specified piece.
+ *
+ * @param uuid the UUID of the piece to suppress the shield
+ */
public void suppressShield(UUID uuid){
- if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized");
pieces.get(uuid).suppressShield();
}
- public void swapPieces(UUID piece1, UUID piece2){
- if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized");
+ /**
+ * Swaps the positions and rotations of two pieces.
+ *
+ * @param p1 the first piece to swap
+ * @param p2 the second piece to swap
+ * @param loc1 the original location of the first piece
+ * @param rot1 the original rotation of the first piece
+ * @param loc2 the original location of the second piece
+ * @param rot2 the original rotation of the second piece
+ */
+ private void swapPieces(PieceControl p1, PieceControl p2, Vector3f loc1, float rot1, Vector3f loc2, float rot2){
+ p1.setLocation(loc2);
+ p2.setLocation(loc1);
- PieceControl piece1Control = pieces.get(piece1);
- PieceControl piece2Control = pieces.get(piece2);
+ p1.setRotation(rot2);
+ p2.setRotation(rot1);
- if(piece1Control == null) throw new RuntimeException("piece1 UUID is not valid");
- if(piece2Control == null) throw new RuntimeException("piece2 UUID is not valid");
-
- float rot1 = piece1Control.getRotation();
- float rot2 = piece2Control.getRotation();
-
- piece1Control.setRotation(rot2);
- piece2Control.setRotation(rot1);
-
- Vector3f pos1 = piece1Control.getLocation().clone();
- Vector3f pos2 = piece2Control.getLocation().clone();
-
- piece1Control.setLocation(pos2);
- piece2Control.setLocation(pos1);
+ app.getModelSynchronize().animationEnd();
}
- public void highlight(UUID uuid, boolean bool){
- if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized");
-
- pieces.get(uuid).highlight(bool);
- pieces.get(uuid).setSelectable(bool);
-
- }
-
- //called when (dice) moveNum is received from server to display the movable pieces and corresponding moveNodes
+ /**
+ * Outlines the possible move nodes for a list of pieces based on the move indices and whether it's a home move.
+ *
+ * @param pieces the list of UUIDs representing the pieces to outline
+ * @param moveIndexe the list of indices for the target move nodes
+ * @param homeMoves the list indicating whether the move is a home move
+ * @throws RuntimeException if the sizes of the input lists do not match
+ */
public void outlineMove(List pieces, List moveIndexe, List homeMoves) {
if(pieces.size() != moveIndexe.size() || pieces.size() != homeMoves.size()) throw new RuntimeException("arrays are not the same size");
@@ -370,7 +534,12 @@ public void outlineMove(List pieces, List moveIndexe, List ownPieces, List enemyPieces){
selectableEnemyPieces.clear();
@@ -394,6 +563,11 @@ public void outlineSwap(List ownPieces, List enemyPieces){
}
}
+ /**
+ * Outlines the pieces that can be shielded based on the provided list of pieces.
+ *
+ * @param pieces the list of UUIDs representing the pieces to be shielded
+ */
public void outlineShield(List pieces){
selectableOwnPieces.clear();
selectableEnemyPieces.clear();
@@ -409,7 +583,11 @@ public void outlineShield(List pieces){
}
}
- //called from inputSynchronizer when a piece is selectable
+ /**
+ * Selects a piece from either the own or enemy pieces based on the input and deselects others if needed.
+ *
+ * @param pieceSelected the PieceControl instance representing the piece selected by the user
+ */
public void pieceSelect(PieceControl pieceSelected) {
boolean isSelected = pieceSelected.isSelected();
if(selectableOwnPieces.contains(pieceSelected)){
@@ -443,7 +621,9 @@ else if(selectableEnemyPieces.contains(pieceSelected)) {
app.getModelSynchronize().select(getKeyByValue(pieces, selectedOwnPiece), getKeyByValue(pieces, selectedEnemyPiece));
}
- //called when view is no longer needed to select pieces
+ /**
+ * Clears all highlighted, selectable, and selected pieces and nodes.
+ */
public void clearSelectable(){
for(PieceControl p : selectableEnemyPieces) {
p.unSelect();
@@ -465,16 +645,20 @@ public void clearSelectable(){
selectedOwnPiece = null;
}
- public void enableHover(UUID uuid){
- pieces.get(uuid).setHoverable(true);
- }
-
+ /**
+ * Displays the dice for the specified color at the appropriate position.
+ *
+ * @param color the color of the player whose dice should be displayed
+ */
public void showDice(Color color){
rootNodeBoard.attachChild(diceControl.getSpatial());
diceControl.setPos(getWaitingPos(color).add(new Vector3f(0,0,4)));
diceControl.spin();
}
+ /**
+ * Hides the dice from the view.
+ */
public void hideDice(){
diceControl.hide();
}
@@ -488,4 +672,107 @@ private K getKeyByValue(Map map, V value) {
return null;
}
+ /**
+ * Animates the movement of a piece from its current index to a target index.
+ *
+ * @param uuid the UUID of the piece to animate
+ * @param curIndex the current index of the piece
+ * @param moveIndex the target index to animate the piece to
+ */
+ public void movePieceAnim(UUID uuid, int curIndex, int moveIndex){
+ pieces.get(uuid).getSpatial().addControl(new MoveControl(
+ infield.get(curIndex).getLocation(),
+ infield.get(moveIndex).getLocation(),
+ ()->movePiece(uuid,curIndex,moveIndex)));
+ }
+
+ /**
+ * Animates the movement of a piece to its home position based on the given home index.
+ *
+ * @param uuid the UUID of the piece to animate
+ * @param homeIndex the index of the home node to move the piece to
+ */
+ public void movePieceHomeAnim(UUID uuid, int homeIndex){
+ pieces.get(uuid).getSpatial().addControl(new MoveControl(
+ pieces.get(uuid).getLocation(),
+ homeNodesMap.get(pieceColor.get(uuid)).get(homeIndex).getLocation(),
+ ()->moveHomePiece(uuid,homeIndex)));
+ }
+
+ /**
+ * Animates the start of the movement of a piece to a target index.
+ *
+ * @param uuid the UUID of the piece to animate
+ * @param moveIndex the target index to animate the piece to
+ */
+ public void movePieceStartAnim(UUID uuid, int moveIndex){
+ pieces.get(uuid).getSpatial().addControl(new MoveControl(
+ pieces.get(uuid).getLocation(),
+ infield.get(moveIndex).getLocation(),
+ ()->movePieceStart(uuid, moveIndex)
+ ));
+ }
+
+ /**
+ * Animates the throwing of a piece to the next available waiting node.
+ *
+ * @param uuid the UUID of the piece to animate
+ */
+ public void throwPieceAnim(UUID uuid){
+ pieces.get(uuid).getSpatial().addControl(new MoveControl(
+ pieces.get(uuid).getLocation(),
+ getNextWaitingNode(pieceColor.get(uuid)).getLocation(),
+ ()->throwPiece(uuid)
+ ));
+ }
+
+ /**
+ * Animates the swapping of two pieces by swapping their positions and rotations.
+ *
+ * @param piece1 the UUID of the first piece
+ * @param piece2 the UUID of the second piece
+ */
+ public void swapPieceAnim(UUID piece1, UUID piece2){
+ PieceControl piece1Control = pieces.get(piece1);
+ PieceControl piece2Control = pieces.get(piece2);
+
+ Vector3f loc1 = piece1Control.getLocation().clone();
+ Vector3f loc2 = piece2Control.getLocation().clone();
+ float rot1 = piece1Control.getRotation();
+ float rot2 = piece2Control.getRotation();
+
+ piece1Control.getSpatial().addControl(new MoveControl(
+ piece1Control.getLocation().clone(),
+ piece2Control.getLocation().clone(),
+ ()->{}
+ ));
+ piece2Control.getSpatial().addControl(new MoveControl(
+ piece2Control.getLocation().clone(),
+ piece1Control.getLocation().clone(),
+ ()->swapPieces(piece1Control,piece2Control,loc1,rot1,loc2,rot2)
+ ));
+ }
+
+ /**
+ * Retrieves the next available waiting node for the specified color.
+ *
+ * @param color the color of the player to get the next waiting node for
+ * @return the next available NodeControl for the specified color
+ * @throws IllegalStateException if no available waiting nodes are found for the color
+ */
+ private NodeControl getNextWaitingNode(Color color) {
+ List nodes = waitingNodesMap.get(color);
+
+ if (nodes == null || nodes.isEmpty()) {
+ throw new IllegalStateException("Keine verfügbaren Warteschleifen-Knoten für die Farbe " + color);
+ }
+
+ for (NodeControl node : nodes) {
+ if (!waitingNodes.getOrDefault(color, new HashMap<>()).containsValue(node)) {
+ return node;
+ }
+ }
+
+ throw new IllegalStateException("Keine freien Nodes im Wartebereich für die Farbe " + color);
+ }
}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/CameraHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/CameraHandler.java
index c0469eef..57da8393 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/CameraHandler.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/CameraHandler.java
@@ -15,6 +15,10 @@
import pp.mdga.client.MdgaApp;
import pp.mdga.game.Color;
+/**
+ * Handles the camera position, rotation, and lighting effects for the game.
+ * Provides methods for camera initialization, updates based on user input, and shutdown operations.
+ */
public class CameraHandler {
MdgaApp app;
@@ -34,6 +38,12 @@ public class CameraHandler {
private boolean init;
private boolean initRot;
+ /**
+ * Constructor for the CameraHandler. Initializes the camera settings and lighting.
+ *
+ * @param app The main application instance that provides the camera and root node.
+ * @param fpp The FilterPostProcessor used for post-processing effects.
+ */
public CameraHandler(MdgaApp app, FilterPostProcessor fpp) {
init = false;
initRot = false;
@@ -61,6 +71,12 @@ public CameraHandler(MdgaApp app, FilterPostProcessor fpp) {
}
+ /**
+ * Initializes the camera with a specific color orientation.
+ * Adds lights, sky, and shadow filters to the scene.
+ *
+ * @param ownColor The color that defines the initial camera view angle.
+ */
public void init(Color ownColor) {
app.getRootNode().addLight(sun);
app.getRootNode().addLight(ambient);
@@ -72,6 +88,10 @@ public void init(Color ownColor) {
app.getInputSynchronize().setRotation(getInitAngleByColor(ownColor)*2);
}
+ /**
+ * Shuts down the camera handler by removing all lights, sky, and filters,
+ * and resets the camera position and rotation to its default state.
+ */
public void shutdown() {
app.getRootNode().removeLight(sun);
app.getRootNode().removeLight(ambient);
@@ -84,6 +104,13 @@ public void shutdown() {
fpp.removeFilter(dlsf);
}
+ /**
+ * Updates the camera position and rotation based on user input (scroll and rotation).
+ * Adjusts the vertical angle and radius based on zoom and rotation values.
+ *
+ * @param scroll The scroll input, determining zoom level.
+ * @param rotation The rotation input, determining camera orientation.
+ */
public void update(float scroll, float rotation) {
if(!init) return;
float scrollValue = Math.max(0, Math.min(scroll, 100));
@@ -117,6 +144,12 @@ public void update(float scroll, float rotation) {
app.getCamera().lookAt(Vector3f.ZERO, Vector3f.UNIT_Z);
}
+ /**
+ * Returns the camera angle based on the specified color.
+ *
+ * @param color The color used to determine the camera angle.
+ * @return The camera angle in degrees.
+ */
private float getAngleByColor(Color color){
return switch (color){
case ARMY -> 0;
@@ -127,6 +160,12 @@ private float getAngleByColor(Color color){
};
}
+ /**
+ * Returns the initial camera angle based on the specified color.
+ *
+ * @param color The color used to determine the camera angle.
+ * @return The initial camera angle in degrees.
+ */
private float getInitAngleByColor(Color color){
return (getAngleByColor(color) + 180) % 360;
}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/MapLoader.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/MapLoader.java
index c85a7dcc..9d283f8f 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/MapLoader.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/MapLoader.java
@@ -10,11 +10,27 @@
import java.util.ArrayList;
import java.util.List;
+/**
+ * A utility class for loading and parsing map data from a file.
+ * The map contains asset names and coordinates for objects placed on the map.
+ */
class MapLoader {
+ /**
+ * Private constructor to prevent instantiation.
+ */
private MapLoader() {
}
+ /**
+ * Loads a map file and parses its contents into a list of assets and their positions.
+ * Each line in the map file defines an asset, its coordinates, and its rotation.
+ *
+ * @param mapName The name of the map file to load. The file is expected to be located in the resources directory.
+ * @return A list of {@link AssetOnMap} objects representing the assets placed on the map.
+ * @throws IOException If an error occurs while reading the map file.
+ * @throws IllegalArgumentException If the map file contains invalid data.
+ */
public static List loadMap(String mapName) {
List assetsOnMap = new ArrayList<>();
@@ -60,6 +76,13 @@ public static List loadMap(String mapName) {
return assetsOnMap;
}
+ /**
+ * Returns the corresponding {@link Asset} for a given asset name.
+ *
+ * @param assetName The name of the asset to load.
+ * @return The {@link Asset} associated with the given name.
+ * @throws IllegalStateException If the asset name is unrecognized.
+ */
private static Asset getLoadedAsset(String assetName) {
return switch (assetName) {
case "lw" -> Asset.lw;
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/NodeControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/NodeControl.java
index 5288b537..d3f1d80e 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/NodeControl.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/NodeControl.java
@@ -8,19 +8,40 @@
import com.jme3.scene.control.AbstractControl;
import pp.mdga.client.MdgaApp;
+/**
+ * A control that adds highlighting functionality to a node in the game.
+ * This class extends {@link OutlineControl} to add an outline effect when the node is highlighted.
+ */
public class NodeControl extends OutlineControl {
private static final ColorRGBA OUTLINE_HIGHLIGHT_COLOR = ColorRGBA.White;
private static final int OUTLINE_HIGHLIGHT_WIDTH = 6;
+ /**
+ * Constructs a {@link NodeControl} with the specified application and post processor.
+ * This constructor sets up the necessary elements for highlighting functionality.
+ *
+ * @param app The {@link MdgaApp} instance to use for the application context.
+ * @param fpp The {@link FilterPostProcessor} to apply post-processing effects.
+ */
public NodeControl(MdgaApp app, FilterPostProcessor fpp) {
super(app, fpp);
}
+ /**
+ * Returns the location of the node in 3D space.
+ * This is the node's local translation in the scene.
+ *
+ * @return The {@link Vector3f} representing the node's location.
+ */
public Vector3f getLocation(){
return this.getSpatial().getLocalTranslation();
}
+ /**
+ * Highlights the node by applying an outline effect.
+ * The outline color and width are predefined as white and 6, respectively.
+ */
public void highlight() {
super.outline(OUTLINE_HIGHLIGHT_COLOR, OUTLINE_HIGHLIGHT_WIDTH);
}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/OutlineControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/OutlineControl.java
index 7872dbe4..f0dfba51 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/OutlineControl.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/OutlineControl.java
@@ -3,16 +3,19 @@
import com.jme3.math.ColorRGBA;
import com.jme3.post.FilterPostProcessor;
import com.jme3.renderer.Camera;
-import com.jme3.renderer.RenderManager;
-import com.jme3.renderer.ViewPort;
-import com.jme3.scene.Spatial;
-import com.jme3.scene.control.AbstractControl;
import pp.mdga.client.MdgaApp;
-import pp.mdga.client.board.outline.SelectObjectOutliner;
+import pp.mdga.client.InitControl;
+import pp.mdga.client.outline.SelectObjectOutliner;
-public class OutlineControl extends AbstractControl {
- private static final int THICKNESS_DEFAULT = 6;
+/**
+ * A control that provides outline functionality to a spatial object.
+ * This class is responsible for adding an outline effect to a spatial
+ * object, allowing it to be highlighted or deselected.
+ */
+public class OutlineControl extends InitControl {
+ /** The {@link SelectObjectOutliner} responsible for managing the outline effect. */
private final SelectObjectOutliner outlineOwn;
+ private static final int THICKNESS_DEFAULT = 6;
private MdgaApp app;
@@ -31,44 +34,33 @@ public OutlineControl(MdgaApp app, FilterPostProcessor fpp, Camera cam, int thic
outlineOwn = new SelectObjectOutliner(thickness, fpp, app.getRenderManager(), app.getAssetManager(), cam, app);
}
+ /**
+ * Applies an outline to the spatial object with the given color.
+ *
+ * @param color The {@link ColorRGBA} representing the color of the outline.
+ */
public void outline(ColorRGBA color){
outlineOwn.select(spatial, color);
}
+ /**
+ * Applies an outline to the spatial object with the given color and width.
+ *
+ * @param color The {@link ColorRGBA} representing the color of the outline.
+ * @param width The width of the outline.
+ */
public void outline(ColorRGBA color, int width){
deOutline();
outlineOwn.select(spatial, color, width);
}
+ /**
+ * Removes the outline effect from the spatial object.
+ */
public void deOutline(){
outlineOwn.deselect(spatial);
}
- @Override
- protected void controlUpdate(float tpf) {
-
- }
-
- @Override
- protected void controlRender(RenderManager rm, ViewPort vp) {
-
- }
-
- public void initSpatial(){
-
- }
-
- @Override
- public void setSpatial(Spatial spatial){
- if(this.spatial == null && spatial != null){
- super.setSpatial(spatial);
- initSpatial();
- }
- else{
- super.setSpatial(spatial);
- }
- }
-
public MdgaApp getApp() {
return app;
}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/PieceControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/PieceControl.java
index d9b22030..4a75533d 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/PieceControl.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/PieceControl.java
@@ -14,6 +14,12 @@
import pp.mdga.client.Asset;
import pp.mdga.client.MdgaApp;
+/**
+ * A control that manages the behavior and properties of a game piece, such as its rotation,
+ * position, shield activation, and highlighting. This class extends {@link OutlineControl}
+ * to provide outline functionality and includes additional features like shield effects,
+ * hover states, and selection states.
+ */
public class PieceControl extends OutlineControl {
private final float initRotation;
private final AssetManager assetManager;
@@ -43,7 +49,15 @@ public class PieceControl extends OutlineControl {
private boolean selectable;
private boolean select;
-
+ /**
+ * Constructs a {@link PieceControl} with the specified initial rotation, asset manager,
+ * application, and post-processor.
+ *
+ * @param initRotation The initial rotation of the piece in degrees.
+ * @param assetManager The {@link AssetManager} used for loading models and materials.
+ * @param app The {@link MdgaApp} instance to use for the application context.
+ * @param fpp The {@link FilterPostProcessor} to apply post-processing effects.
+ */
public PieceControl(float initRotation, AssetManager assetManager, MdgaApp app, FilterPostProcessor fpp){
super(app, fpp);
this.parentNode = new Node();
@@ -59,10 +73,20 @@ public PieceControl(float initRotation, AssetManager assetManager, MdgaApp app,
select = false;
}
+ /**
+ * Gets the current rotation of the piece in degrees.
+ *
+ * @return The rotation of the piece in degrees.
+ */
public float getRotation() {
return (float) Math.toDegrees(spatial.getLocalRotation().toAngleAxis(new Vector3f(0,0,1)));
}
+ /**
+ * Sets the rotation of the piece to the specified value in degrees.
+ *
+ * @param rot The rotation in degrees to set.
+ */
public void setRotation(float rot){
if(rot < 0) rot =- 360;
@@ -71,10 +95,20 @@ public void setRotation(float rot){
spatial.setLocalRotation(quaternion);
}
+ /**
+ * Gets the current location (position) of the piece.
+ *
+ * @return The location of the piece as a {@link Vector3f}.
+ */
public Vector3f getLocation(){
return spatial.getLocalTranslation();
}
+ /**
+ * Updates the piece control every frame. If the shield is active, it will rotate.
+ *
+ * @param delta The time difference between frames (time per frame).
+ */
@Override
protected void controlUpdate(float delta) {
if(shieldRing != null){
@@ -82,10 +116,19 @@ protected void controlUpdate(float delta) {
}
}
+ /**
+ * Sets the location (position) of the piece.
+ *
+ * @param loc The location to set as a {@link Vector3f}.
+ */
public void setLocation(Vector3f loc){
this.spatial.setLocalTranslation(loc);
}
+ /**
+ * Initializes the spatial object and sets its rotation.
+ * This also moves the spatial to a new parent node for organizational purposes.
+ */
@Override
public void initSpatial(){
setRotation(this.initRotation);
@@ -101,6 +144,10 @@ public void rotateInit() {
// rotate(rotation - initRotation);
}
+ /**
+ * Activates the shield around the piece.
+ * This adds a visual shield effect in the form of a rotating ring.
+ */
public void activateShield(){
shieldRing = assetManager.loadModel(Asset.shieldRing.getModelPath());
shieldRing.scale(1f);
@@ -115,11 +162,18 @@ public void activateShield(){
parentNode.attachChild(shieldRing);
}
+ /**
+ * Deactivates the shield by removing the shield ring from the scene.
+ */
+
public void deactivateShield(){
parentNode.detachChild(shieldRing);
shieldRing = null;
}
+ /**
+ * Suppresses the shield, changing its color to a suppressed state.
+ */
public void suppressShield(){
assert(shieldRing != null) : "PieceControl: shieldRing is not set";
shieldMat.setColor("Color", SHIELD_SUPPRESSED_COLOR);
@@ -133,22 +187,36 @@ public Material getMaterial(){
return ((Geometry) getSpatial()).getMaterial();
}
+ /**
+ * Highlights the piece with the appropriate outline color based on whether it is an enemy or not.
+ *
+ * @param enemy True if the piece is an enemy, false if it is owned by the player.
+ */
public void highlight(boolean enemy) {
this.enemy = enemy;
highlight = true;
super.outline(enemy ? OUTLINE_ENEMY_COLOR : OUTLINE_OWN_COLOR, OUTLINE_HIGHLIGHT_WIDTH);
}
+ /**
+ * Removes the highlight effect from the piece.
+ */
public void unHighlight(){
highlight = false;
deOutline();
}
+ /**
+ * Applies a hover effect on the piece if it is hoverable.
+ */
public void hover(){
if(!hoverable) return;
super.outline(enemy ? OUTLINE_ENEMY_HOVER_COLOR : OUTLINE_OWN_HOVER_COLOR, OUTLINE_HOVER_WIDTH);
}
+ /**
+ * Removes the hover effect from the piece.
+ */
public void hoverOff(){
if(!hoverable) return;
@@ -157,28 +225,56 @@ public void hoverOff(){
else deOutline();
}
+ /**
+ * Deselects the piece and removes the selection outline. If the piece was highlighted,
+ * it will be re-highlighted. Otherwise, the outline is removed.
+ */
public void unSelect(){
select = false;
if(highlight) highlight(enemy);
else deOutline();
}
+ /**
+ * Selects the piece and applies the selection outline. If the piece is an enemy, it will
+ * be outlined with the enemy selection color; otherwise, the own selection color will be used.
+ */
public void select(){
if(!selectable) return;
select = true;
super.outline(enemy ? OUTLINE_ENEMY_SELECT_COLOR : OUTLINE_OWN_SELECT_COLOR, OUTLINE_SELECT_WIDTH);
}
+ /**
+ * Sets whether the piece is selectable.
+ *
+ * @param selectable True if the piece can be selected, false otherwise.
+ */
public void setSelectable(boolean selectable){
this.selectable = selectable;
}
+ /**
+ * Checks if the piece is selected.
+ *
+ * @return True if the piece is selected, false otherwise.
+ */
public boolean isSelected() { return select; }
+ /**
+ * Checks if the piece is selectable.
+ *
+ * @return True if the piece is selectable, false otherwise.
+ */
public boolean isSelectable() {
return selectable;
}
+ /**
+ * Sets whether the piece is hoverable.
+ *
+ * @param hoverable True if the piece can be hovered over, false otherwise.
+ */
public void setHoverable(boolean hoverable) {
this.hoverable = hoverable;
}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/PileControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/PileControl.java
deleted file mode 100644
index f4e604c6..00000000
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/PileControl.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package pp.mdga.client.board;
-
-class PileControl {
-
-}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/Rotation.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/Rotation.java
deleted file mode 100644
index 5db07057..00000000
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/Rotation.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package pp.mdga.client.board;
-
-public enum Rotation {
- UP,
- RIGHT,
- DOWN,
- LEFT,
- UP_LEFT,
- UP_RIGHT,
- DOWN_RIGHT,
- DOWN_LEFT
-}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java
index 1b868163..b5bd3571 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java
@@ -7,22 +7,23 @@
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
import com.jme3.system.AppSettings;
-import pp.mdga.client.Asset;
+import pp.mdga.client.animation.ZoomControl;
import pp.mdga.game.Color;
-public class ActionTextHandler {
+ class ActionTextHandler {
private Node root;
private BitmapFont font;
private AppSettings appSettings;
+ private int ranking;
- public ActionTextHandler(Node guiNode, AssetManager assetManager, AppSettings appSettings){
+ ActionTextHandler(Node guiNode, AssetManager assetManager, AppSettings appSettings){
root = new Node("actionTextRoot");
guiNode.attachChild(root);
root.setLocalTranslation(center(appSettings.getWidth(), appSettings.getHeight(), Vector3f.ZERO));
font = assetManager.loadFont("Fonts/Gunplay.fnt");
this.appSettings = appSettings;
-
+ ranking = 0;
}
private Node createTextWithSpacing(String[] textArr, float spacing, float size, ColorRGBA[] colorArr) {
@@ -74,48 +75,48 @@ private Vector3f centerText(float width, float height, Vector3f pos){
return center(-width, height, pos);
}
- public void activePlayer(String name, Color color){
+ void activePlayer(String name, Color color){
createTopText(new String[]{name," ist dran"}, 10,90,new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl());
}
- public void ownActive(Color color){
+ void ownActive(Color color){
createTopText(new String[]{"Du"," bist dran"}, 10,90,new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl());
}
- public void diceNum(int diceNum, String name, Color color){
+ void diceNum(int diceNum, String name, Color color){
createTopText(new String[]{name," würfelt:"}, 10,90,new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0);
createTopText(String.valueOf(diceNum), 10, 100, ColorRGBA.White, 100);
}
- public void diceNumMult(int diceNum,int mult, String name, Color color){
+ void diceNumMult(int diceNum,int mult, String name, Color color){
createTopText(new String[]{name," würfelt:"}, 10,90,new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0);
createTopText(new String[]{String.valueOf(diceNum), " x" + mult + " = " + (diceNum*mult)}, 20, 100, new ColorRGBA[]{ColorRGBA.White,ColorRGBA.Red}, 100);
}
- public void ownDice(int diceNum){
+ void ownDice(int diceNum){
createTopText(String.valueOf(diceNum), 10, 100, ColorRGBA.White, 0);
}
- public void ownDiceMult(int diceNum, int mult){
+ void ownDiceMult(int diceNum, int mult){
createTopText(new String[]{String.valueOf(diceNum), " x" + mult + " = " + (diceNum*mult)}, 20, 100, new ColorRGBA[]{ColorRGBA.White,ColorRGBA.Red}, 0);
}
- public void drawCard(String name, Color color){
+ void drawCard(String name, Color color){
createTopText(new String[]{name," erhält eine Bonuskarte"}, 7,70, new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl());
}
- public void drawCardOwn(Color color){
+ void drawCardOwn(Color color){
createTopText(new String[]{"Du"," erhälst eine Bonuskarte"}, 5,70, new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl());
}
- public void finishText(String name, Color color){
+ void finishText(String name, Color color){
createTopText(new String[]{name," ist fertig!"}, 7,70, new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl());
}
- public void finishTextOwn(Color color){
+ void finishTextOwn(Color color){
createTopText(new String[]{"Du", " bist fertig!"}, 7,70, new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl());
}
@@ -131,9 +132,25 @@ private ColorRGBA playerColorToColorRGBA(Color color){
};
}
- public void hide(){
- root.detachAllChildren();
+ void hide(){
+ ranking = 0;
+ root.detachAllChildren();
}
+ float paddingRanked = 100;
+
+ void rollRankingResult(String name, Color color, int eye){
+ createTopText(new String[]{name,": "+eye}, 10,90,new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, paddingRanked*ranking);
+ ranking++;
+ }
+
+ void rollRankingResultOwn(Color color, int eye){
+ createTopText(new String[]{"Du",": "+eye}, 10,90,new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, paddingRanked*ranking);
+ ranking++;
+ }
+
+ void diceNow(){
+ createTopText("Klicke zum Würfeln", 5, 80, ColorRGBA.White, 0);
+ }
}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayerHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayerHandler.java
index fede1dba..116e0987 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayerHandler.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayerHandler.java
@@ -10,6 +10,7 @@
import com.jme3.texture.Texture2D;
import pp.mdga.client.Asset;
import pp.mdga.client.MdgaApp;
+import pp.mdga.client.animation.SymbolControl;
import pp.mdga.game.BonusCard;
import java.util.*;
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java
index 8761e3da..d4128081 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java
@@ -67,6 +67,7 @@ public void showRolledDice(int rollNum, Color color) {
public void showDice() {
cardLayerHandler.showDice();
+ actionTextHandler.diceNow();
}
public void hideDice() {
@@ -134,5 +135,10 @@ public void finish(Color color){
else actionTextHandler.finishText(playerNameHandler.getName(color), color);
}
+ public void rollRankingResult(Color color, int eye){
+ if(ownColor == color) actionTextHandler.rollRankingResultOwn(color, eye);
+ else actionTextHandler.rollRankingResult(playerNameHandler.getName(color), color, eye);
+ }
+
}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/PlayerNameHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/PlayerNameHandler.java
index 1b197d16..2d4bdbf7 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/PlayerNameHandler.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/PlayerNameHandler.java
@@ -120,6 +120,7 @@ public void setActivePlayer(Color color) {
}
public String getName(Color color){
+ if(!colorNameMap.containsKey(color)) throw new RuntimeException("color is not in colorNameMap");
return colorNameMap.get(color);
}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ZoomControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ZoomControl.java
deleted file mode 100644
index 33b10ea8..00000000
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ZoomControl.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package pp.mdga.client.gui;
-
-import com.jme3.renderer.RenderManager;
-import com.jme3.renderer.ViewPort;
-import com.jme3.scene.Spatial;
-import com.jme3.scene.control.AbstractControl;
-
-public class ZoomControl extends AbstractControl {
- private boolean zoomingIn = false;
- private boolean zoomingOut = false;
- private float progress = 0;
- private float zoomSpeed = 1f;
- private float zoomFactor = 1f;
-
- public ZoomControl() {
- }
-
- public ZoomControl(float speed) {
- zoomSpeed = speed;
- }
-
- @Override
- public void setSpatial(Spatial spatial) {
- if (this.spatial == null && spatial != null) {
- super.setSpatial(spatial);
- initSpatial();
- }
- }
-
- private void initSpatial() {
- zoomingIn = true;
- }
-
- @Override
- protected void controlUpdate(float tpf) {
- if (zoomingIn) {
- progress += tpf * zoomSpeed;
- if (progress > 1) progress = 1;
- spatial.setLocalScale(lerp(0, zoomFactor, easeOut(progress)));
- if (progress >= 1) {
- zoomingIn = false;
- zoomingOut = true;
- progress = 0;
- }
- } else if (zoomingOut) {
- progress += tpf * zoomSpeed;
- spatial.setLocalScale(lerp(zoomFactor, 0, easeIn(progress)));
- if (progress > 1) {
- zoomingOut = false;
- end();
- }
- }
- }
-
- private void end() {
- spatial.removeFromParent();
- spatial.removeControl(this);
- }
-
- @Override
- protected void controlRender(RenderManager rm, ViewPort vp) {
-
- }
-
- private static float lerp(float start, float end, float t) {
- return (1 - t) * start + t * end;
- }
-
- // private static float easeOut(float t) {
-// return (float) Math.sqrt(1 - Math.pow(t - 1, 2));
-// }
- private float easeOut(float x) {
- return x == 1 ? 1 : (float) (1 - Math.pow(2, -10 * x));
-
- }
-
- // private float easeIn(float t) {
-// return t * t * t * t;
-// }
- private float easeIn(float x) {
- return x == 0 ? 0 : (float) Math.pow(2, 10 * x - 10);
-
- }
-}
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlineFilter.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlineFilter.java
similarity index 98%
rename from Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlineFilter.java
rename to Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlineFilter.java
index d9fcaef9..109e2de7 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlineFilter.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlineFilter.java
@@ -1,4 +1,4 @@
-package pp.mdga.client.board.outline;
+package pp.mdga.client.outline;
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlinePreFilter.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlinePreFilter.java
similarity index 97%
rename from Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlinePreFilter.java
rename to Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlinePreFilter.java
index 9a385045..cb2ae654 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlinePreFilter.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlinePreFilter.java
@@ -1,4 +1,4 @@
-package pp.mdga.client.board.outline;
+package pp.mdga.client.outline;
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlineProFilter.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlineProFilter.java
similarity index 98%
rename from Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlineProFilter.java
rename to Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlineProFilter.java
index c40a9435..c49f6158 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlineProFilter.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlineProFilter.java
@@ -1,4 +1,4 @@
-package pp.mdga.client.board.outline;
+package pp.mdga.client.outline;
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/SelectObjectOutliner.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/SelectObjectOutliner.java
similarity index 98%
rename from Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/SelectObjectOutliner.java
rename to Projekte/mdga/client/src/main/java/pp/mdga/client/outline/SelectObjectOutliner.java
index 3cfbc76c..aa5049a6 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/SelectObjectOutliner.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/SelectObjectOutliner.java
@@ -1,4 +1,4 @@
-package pp.mdga.client.board.outline;
+package pp.mdga.client.outline;
import com.jme3.asset.AssetManager;
import com.jme3.math.ColorRGBA;
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java
index 533dabd7..b8e8bfb4 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java
@@ -2,6 +2,7 @@
import com.jme3.network.*;
import com.jme3.network.serializing.Serializer;
+import com.jme3.network.serializing.serializers.EnumSerializer;
import pp.mdga.game.*;
import pp.mdga.message.client.*;
import pp.mdga.message.server.*;
@@ -12,7 +13,6 @@
import java.io.IOException;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
-import java.net.InetAddress;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
@@ -130,6 +130,7 @@ private void initializeSerializables() {
Serializer.registerClass(ReconnectBriefingMessage.class);
Serializer.registerClass(ResumeGameMessage.class);
Serializer.registerClass(ServerStartGameMessage.class);
+ Serializer.registerClass(ShutdownMessage.class);
Serializer.registerClass(StartPieceMessage.class);
Serializer.registerClass(UpdateReadyMessage.class);
Serializer.registerClass(UpdateTSKMessage.class);
@@ -143,6 +144,8 @@ private void initializeSerializables() {
Serializer.registerClass(StartNode.class);
Serializer.registerClass(PlayerData.class);
Serializer.registerClass(HomeNode.class);
+ Serializer.registerClass(PlayerDataMessage.class);
+ Serializer.registerClass(StartBriefingMessage.class);
}
private void registerListeners() {
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java
index 41a2b412..f28719ac 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java
@@ -64,6 +64,13 @@ public void onEnter() {
app.getViewPort().addProcessor(fpp);
app.getAcousticHandler().playSound(MdgaSound.START);
+
+// guiHandler.addPlayer(Color.AIRFORCE, "Cedric");
+// guiHandler.addPlayer(Color.ARMY, "Ben");
+// guiHandler.addPlayer(Color.CYBER, "Felix");
+// guiHandler.addPlayer(Color.NAVY, "Daniel");
+
+
}
@Override
diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/LobbyView.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/LobbyView.java
index 0ee82c56..e96cbbb7 100644
--- a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/LobbyView.java
+++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/LobbyView.java
@@ -228,7 +228,7 @@ private void toggleTsk(Color color) {
app.getModelSynchronize().selectTsk(color);
break;
case SELF:
- app.getModelSynchronize().unselectTsk();
+ app.getModelSynchronize().unselectTsk(color);
break;
case OTHER:
//nothing
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/CeremonyState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/CeremonyState.java
index 38541512..cf6e5e5a 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/client/CeremonyState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/CeremonyState.java
@@ -18,7 +18,7 @@ public CeremonyState(ClientState parent, ClientGameLogic logic) {
@Override
public void enter() {
- currentState = podiumState;
+ setState(podiumState);
logic.addNotification(createCeremonyNotification());
}
@@ -28,7 +28,9 @@ public void exit() {
}
public void setState(CeremonyStates state){
- this.currentState.exit();
+ if(this.currentState != null){
+ this.currentState.exit();
+ }
state.enter();
currentState = state;
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java
index eeb76f55..f3a0602b 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java
@@ -190,6 +190,19 @@ public void received(ServerStartGameMessage msg) {
state.received(msg);
}
+ @Override
+ public void received(ShutdownMessage msg) {state.received(msg);}
+
+ @Override
+ public void received(StartBriefingMessage msg) {
+ state.received(msg);
+ }
+
+ @Override
+ public void received(PlayerDataMessage msg) {
+ state.received(msg);
+ }
+
@Override
public void received(StartPieceMessage msg) {
state.received(msg);
@@ -236,6 +249,10 @@ public void selectTsk(Color color){
state.selectTSK(color);
}
+ public void deselectTSK(Color color){
+ state.deselectTSK(color);
+ }
+
public void selectDice(){
state.selectDice();
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientState.java
index e53a5d92..ae500c42 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientState.java
@@ -150,6 +150,9 @@ public void received(ServerStartGameMessage msg) {
LOGGER.log(Level.DEBUG, "Received {0} not allowed.", msg);
}
+ @Override
+ public void received(ShutdownMessage msg) {LOGGER.log(Level.DEBUG, "Received {0} not allowed.", msg);}
+
@Override
public void received(StartPieceMessage msg) {
LOGGER.log(Level.DEBUG, "Received {0} not allowed.", msg);
@@ -180,6 +183,15 @@ public void received(WaitPieceMessage msg) {
LOGGER.log(Level.DEBUG, "Received {0} not allowed.", msg);
}
+ @Override
+ public void received(StartBriefingMessage msg) {
+ LOGGER.log(Level.DEBUG, "Received {0} not allowed.", msg);
+ }
+
+ public void received(PlayerDataMessage msg) {
+ LOGGER.log(Level.DEBUG, "Received {0} not allowed.", msg);
+ }
+
public void selectPiece(Piece piece) {
LOGGER.log(Level.DEBUG, "Selecting piece not allowed.");
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/DialogsState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/DialogsState.java
index 5f7cf182..c8578cd3 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/client/DialogsState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/DialogsState.java
@@ -30,13 +30,15 @@ public void exit(){
@Override
public void enter(){
- currentState = startDialogState;
+ setState(startDialogState);
ownPlayerID = 0;
ownPlayerName = null;
}
public void setState(DialogStates newState){
- currentState.exit();
+ if(currentState != null){
+ currentState.exit();
+ }
newState.enter();
currentState = newState;
}
@@ -69,11 +71,6 @@ public StartDialogState getStartDialog() {
return startDialogState;
}
- public void startGame(){
- exit();
- logic.setState(logic.getGameState());
- }
-
@Override
public void selectLeave(){
currentState.selectLeave();
@@ -144,6 +141,16 @@ public void received(ServerStartGameMessage msg){
currentState.received(msg);
}
+ @Override
+ public void received(PlayerDataMessage msg){
+ currentState.received(msg);
+ }
+
+ @Override
+ public void received(StartBriefingMessage msg){
+ currentState.received(msg);
+ }
+
public DialogStates getState() {
return currentState;
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/GameState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/GameState.java
index af449db8..31b3f340 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/client/GameState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/GameState.java
@@ -27,7 +27,6 @@ public class GameState extends ClientState {
*/
public GameState(ClientState parent, ClientGameLogic logic) {
super(parent, logic);
- state = determineStartPlayerState;
}
/**
@@ -35,7 +34,7 @@ public GameState(ClientState parent, ClientGameLogic logic) {
*/
@Override
public void enter() {
-
+ this.setState(this.determineStartPlayerState);
}
/**
@@ -52,8 +51,10 @@ public void exit() {
* @param newState the state to be set
*/
public void setState(GameStates newState){
- state.exit();
- state.enter();
+ if(this.state != null){
+ this.state.exit();
+ }
+ newState.enter();
state = newState;
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java
index 7678624a..2d48cbe1 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java
@@ -10,7 +10,9 @@
import pp.mdga.message.client.*;
import pp.mdga.message.server.LobbyPlayerJoinedMessage;
import pp.mdga.message.server.LobbyPlayerLeaveMessage;
+import pp.mdga.message.server.PlayerDataMessage;
import pp.mdga.message.server.ServerStartGameMessage;
+import pp.mdga.message.server.StartBriefingMessage;
import pp.mdga.message.server.UpdateReadyMessage;
import pp.mdga.message.server.UpdateTSKMessage;
import pp.mdga.notification.*;
@@ -74,17 +76,26 @@ public void selectStart(){
}
@Override
- public void received(ServerStartGameMessage msg){
+ public void received(StartBriefingMessage msg){
logic.getGame().setBoard(msg.getBoard());
- logic.addNotification(new GameNotification(logic.getGame().getPlayers().get(parent.getOwnPlayerId()).getColor()));
- for(Map.Entry entry : msg.getBoard().getPlayerData().entrySet()){
- List pieceIds = new ArrayList<>();
+ }
+
+ public void received(PlayerDataMessage msg){
+ logic.getGame().getBoard().addPlayerData(msg.getColor(), msg.getPlayerData());
+ }
+
+ @Override
+ public void received(ServerStartGameMessage msg){
+ logic.addNotification(new GameNotification(logic.getGame().getPlayerById(parent.getOwnPlayerId()).getColor()));
+ for (Map.Entry entry : logic.getGame().getBoard().getPlayerData().entrySet()) {
+ List pieceList = new ArrayList<>();
for(Piece piece : entry.getValue().getPieces()){
- pieceIds.add(piece.getUuid());
+ System.out.println(piece.getUuid());
+ pieceList.add(piece.getUuid());
}
- logic.addNotification(new PlayerInGameNotification(entry.getKey(), pieceIds, logic.getGame().getPlayerByColor(entry.getKey()).getName()));
+ logic.addNotification(new PlayerInGameNotification(entry.getKey(), pieceList , logic.getGame().getPlayerByColor(entry.getKey()).getName()));
}
- parent.startGame();
+ logic.setState(logic.getGameState());
}
@Override
@@ -95,15 +106,20 @@ public void received(LobbyPlayerJoinedMessage msg){
if (msg.isHost() && msg.getId() == parent.getOwnPlayerId()){
logic.setHost(true);
}
- logic.addNotification(new TskSelectNotification(msg.getPlayer().getColor(), msg.getPlayer().getName(), parent.getOwnPlayerId()== msg.getId()));
+
+ logic.addNotification(new TskSelectNotification(msg.getPlayer().getColor(), msg.getPlayer().getName(), msg.getPlayer().getName().equals(parent.getOwnPlayerName())));
logic.getGame().getPlayers().put(msg.getId(), msg.getPlayer());
}
@Override
public void received(UpdateTSKMessage msg){
- logic.addNotification(new TskUnselectNotification(logic.getGame().getPlayers().get(msg.getId()).getColor()));
+ if(msg.isTaken()) {
+ logic.addNotification(new TskSelectNotification(msg.getColor(), logic.getGame().getPlayers().get(msg.getId()).getName(), parent.getOwnPlayerId()== msg.getId()));
+ } else {
+ logic.addNotification(new TskUnselectNotification(logic.getGame().getPlayers().get(msg.getId()).getColor()));
+ }
+
logic.getGame().getPlayers().get(msg.getId()).setColor(msg.getColor());
- logic.addNotification(new TskSelectNotification(msg.getColor(), logic.getGame().getPlayers().get(msg.getId()).getName(), parent.getOwnPlayerId()== msg.getId()));
}
@Override
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/NetworkDialogState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/NetworkDialogState.java
index 09212dee..98234319 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/NetworkDialogState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/NetworkDialogState.java
@@ -14,34 +14,6 @@ public NetworkDialogState(ClientState parent, ClientGameLogic logic) {
this.parent = (DialogsState) parent;
}
- private boolean checkIP(String IP){
- String[] parts = IP.split("\\.");
-
- // Step 2: Check if there are exactly 4 parts
- if (parts.length != 4) {
- return false;
- }
-
- // Step 3: Check each part for valid number
- for (String part : parts) {
- try {
- // Step 4: Convert each part into a number
- int num = Integer.parseInt(part);
-
- // Step 5: Check whether the number lies in between 0 and 255
- if (num < 0 || num > 255) {
- return false;
- }
- } catch (NumberFormatException e) {
- // If parsing fails, it's not a valid number
- return false;
- }
- }
-
- // If all checks passed, return true
- return true;
- }
-
@Override
public void enter() {
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/DetermineStartPlayerState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/DetermineStartPlayerState.java
index cf3c48c2..4794785a 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/DetermineStartPlayerState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/DetermineStartPlayerState.java
@@ -25,7 +25,7 @@ public DetermineStartPlayerState(ClientState parent, ClientGameLogic logic) {
@Override
public void enter() {
- state = rollRankingDiceState;
+ this.setState(this.rollRankingDiceState);
}
@Override
@@ -34,7 +34,9 @@ public void exit() {
}
public void setState(DetermineStartPlayerStates state) {
- this.state.exit();
+ if(this.state != null){
+ this.state.exit();
+ }
state.enter();
this.state = state;
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/TurnState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/TurnState.java
index b59a35b8..5f075eff 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/TurnState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/TurnState.java
@@ -31,7 +31,7 @@ public TurnState(ClientState parent, ClientGameLogic logic) {
@Override
public void enter() {
- state = powerCardState;
+ this.setState(this.powerCardState);
}
@Override
@@ -40,7 +40,9 @@ public void exit() {
}
public void setState(TurnStates state){
- this.state.exit();
+ if(this.state != null){
+ this.state.exit();
+ }
state.enter();
this.state = state;
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/determineStartPlayerState/RollRankingDiceState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/determineStartPlayerState/RollRankingDiceState.java
index 3c1ec5b9..e6a98522 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/determineStartPlayerState/RollRankingDiceState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/determineStartPlayerState/RollRankingDiceState.java
@@ -6,6 +6,7 @@
import pp.mdga.message.client.RequestDieMessage;
import pp.mdga.message.server.DieMessage;
import pp.mdga.notification.DiceNowNotification;
+import pp.mdga.notification.RollDiceNotification;
public class RollRankingDiceState extends DetermineStartPlayerStates {
@@ -23,16 +24,17 @@ public void enter() {
@Override
public void exit() {
-
}
@Override
public void selectDice(){
+ System.out.println("selectDice");
logic.send(new RequestDieMessage());
}
@Override
public void received(DieMessage msg){
+ logic.addNotification(new RollDiceNotification(logic.getGame().getPlayerById(logic.getDialogs().getOwnPlayerId()).getColor(), msg.getDiceEye(),true));
parent.setState(parent.getWaitRanking());
}
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/ChoosePieceState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/ChoosePieceState.java
index b1a0c7e3..47dce439 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/ChoosePieceState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/ChoosePieceState.java
@@ -24,7 +24,7 @@ public ChoosePieceState(ClientState parent, ClientGameLogic logic) {
@Override
public void enter() {
- currentState = noPieceState;
+ this.setState(this.noPieceState);
}
@Override
@@ -34,9 +34,11 @@ public void exit() {
}
public void setState(ChoosePieceStates state){
- currentState.exit();
+ if(currentState != null){
+ currentState.exit();
+ }
+ state.enter();
currentState = state;
- currentState.enter();
}
@Override
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/PowerCardState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/PowerCardState.java
index fd80b68d..5a5fd5c3 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/PowerCardState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/PowerCardState.java
@@ -31,7 +31,7 @@ public PowerCardState(ClientState parent, ClientGameLogic logic) {
@Override
public void enter() {
- state = choosePowerCardState;
+ this.setState(this.choosePowerCardState);
}
public void exit() {
@@ -40,7 +40,9 @@ public void exit() {
}
public void setState(PowerCardStates state) {
- this.state.exit();
+ if(this.state != null){
+ this.state.exit();
+ }
state.enter();
this.state = state;
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java
index 64b671db..a01c1247 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java
@@ -42,7 +42,9 @@ public Piece(Color color, PieceState state, int id) {
}
private Piece() {
- color = null;
+ color = Color.NONE;
+ state = PieceState.WAITING;
+ shield = ShieldState.NONE;
}
/**
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java
index abab1258..780d8df0 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java
@@ -1,5 +1,7 @@
package pp.mdga.game;
+import com.jme3.network.serializing.Serializable;
+
/**
* Represents the state of a piece.
*/
@@ -19,5 +21,21 @@ public enum PieceState {
/**
* The piece is finished.
*/
- HOMEFINISHED
+ HOMEFINISHED;
+
+ PieceState(){
+
+ }
+
+ public static PieceState getPieceStateByIndex(int index){
+ if (index < 0 || index >= values().length) {
+ throw new IllegalArgumentException("");
+ }
+ return values()[index];
+ }
+
+
+ public PieceState next() {
+ return values()[(ordinal() + 1) % values().length];
+ }
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/PlayerData.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/PlayerData.java
index 8fcc85ae..cb2a788b 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/game/PlayerData.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/PlayerData.java
@@ -43,10 +43,23 @@ public PlayerData(Color color) {
}
}
+ /**
+ * Constructor.
+ */
private PlayerData() {
- homeNodes = null;
- waitingArea = null;
- pieces = null;
+ homeNodes = new HomeNode[4];
+ waitingArea = new Piece[4];
+ pieces = new Piece[4];
+ }
+
+ /**
+ * This method will be used to check if the player is finished.
+ * ToDo: Currently return always false. Implement logic!
+ *
+ * @return true or false.
+ */
+ public boolean isFinished() {
+ return false;
}
/**
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java
index 6bff3f52..19a09a5d 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java
@@ -1,8 +1,11 @@
package pp.mdga.game;
+import com.jme3.network.serializing.Serializable;
+
/**
* Represents the state of a piece's shield.
*/
+@Serializable
public enum ShieldState {
/**
* The shield is not active.
@@ -15,5 +18,20 @@ public enum ShieldState {
/**
* The shield is suppressed, when the piece is on a start node.
*/
- SUPPRESSED
+ SUPPRESSED;
+
+ ShieldState(){
+
+ }
+
+ public static ShieldState getShieldStateByIndex(int index){
+ if (index < 0 || index >= values().length) {
+ throw new IllegalArgumentException("");
+ }
+ return values()[index];
+ }
+
+ public ShieldState next() {
+ return values()[(ordinal() + 1) % values().length];
+ }
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/StartNode.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/StartNode.java
index bb203084..24b2c267 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/game/StartNode.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/StartNode.java
@@ -22,7 +22,7 @@ public StartNode(Color color) {
}
private StartNode() {
- color = null;
+ color = Color.NONE;
}
/**
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/PlayerDataMessage.java b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/PlayerDataMessage.java
new file mode 100644
index 00000000..03171e73
--- /dev/null
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/PlayerDataMessage.java
@@ -0,0 +1,40 @@
+package pp.mdga.message.server;
+
+import com.jme3.network.serializing.Serializable;
+import pp.mdga.game.Color;
+import pp.mdga.game.PlayerData;
+
+@Serializable
+public class PlayerDataMessage extends ServerMessage{
+
+ private final PlayerData playerData;
+ private final Color color;
+
+ public PlayerDataMessage(PlayerData playerData, Color color){
+ super();
+ this.playerData = playerData;
+ this.color = color;
+ }
+
+ private PlayerDataMessage(){
+ this(null, null);
+ }
+
+ @Override
+ public void accept(ServerInterpreter interpreter) {
+ interpreter.received(this);
+ }
+
+ @Override
+ public String getInfoTextKey() {
+ return "";
+ }
+
+ public PlayerData getPlayerData(){
+ return playerData;
+ }
+
+ public Color getColor(){
+ return color;
+ }
+}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerInterpreter.java b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerInterpreter.java
index d7e7487c..4491f9c1 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerInterpreter.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerInterpreter.java
@@ -207,4 +207,15 @@ public interface ServerInterpreter {
* @param msg the SelectPiece message received.
*/
void received(SelectPieceMessage msg);
+
+ /**
+ * Handles a SelectTSK message received from the server.
+ *
+ * @param shutdownMessage the SelectTSK message received.
+ */
+ void received(ShutdownMessage shutdownMessage);
+
+ void received(StartBriefingMessage msg);
+
+ void received(PlayerDataMessage msg);
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerStartGameMessage.java b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerStartGameMessage.java
index 37c22e1e..69e3fb96 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerStartGameMessage.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerStartGameMessage.java
@@ -8,28 +8,13 @@
*/
@Serializable
public class ServerStartGameMessage extends ServerMessage {
- /**
- * Create ServerStartGameMessage attributes.
- */
- private final Board board;
/**
* Constructs a new ServerStartGame instance.
*/
public ServerStartGameMessage() {
super();
- this.board = null;
}
-
- /**
- * Constructor.
- *
- * @param board as the complete board of this game as a Board object.
- */
- public ServerStartGameMessage(Board board) {
- this.board = board;
- }
-
/**
* Accepts a visitor to process this message.
*
@@ -40,15 +25,6 @@ public void accept(ServerInterpreter interpreter) {
interpreter.received(this);
}
- /**
- * This method will be used to return board attribute of ServerStartGameMessage class.
- *
- * @return board as a Board object.
- */
- public Board getBoard() {
- return this.board;
- }
-
/**
* Returns a string representation of this message.
*
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ShutdownMessage.java b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ShutdownMessage.java
new file mode 100644
index 00000000..8c898f03
--- /dev/null
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ShutdownMessage.java
@@ -0,0 +1,30 @@
+package pp.mdga.message.server;
+
+import com.jme3.network.serializing.Serializable;
+
+/**
+ * A message sent by the server to inform the clients that the server is shutting down.
+ */
+@Serializable
+public class ShutdownMessage extends ServerMessage {
+ /**
+ * Accepts a visitor to process this message.
+ *
+ * @param interpreter the visitor to process this message
+ */
+ @Override
+ public void accept(ServerInterpreter interpreter) {
+ interpreter.received(this);
+ }
+
+ /**
+ * Gets the bundle key of the informational text to be shown at the client.
+ * This key is used to retrieve the appropriate localized text for display.
+ *
+ * @return the bundle key of the informational text
+ */
+ @Override
+ public String getInfoTextKey() {
+ return "";
+ }
+}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/StartBriefingMessage.java b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/StartBriefingMessage.java
new file mode 100644
index 00000000..ba465990
--- /dev/null
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/StartBriefingMessage.java
@@ -0,0 +1,33 @@
+package pp.mdga.message.server;
+
+import com.jme3.network.serializing.Serializable;
+import pp.mdga.game.Board;
+
+@Serializable
+public class StartBriefingMessage extends ServerMessage {
+
+ private final Board board;
+
+ public StartBriefingMessage(Board board) {
+ super();
+ this.board = board;
+ }
+
+ private StartBriefingMessage() {
+ this(null);
+ }
+
+ public Board getBoard() {
+ return this.board;
+ }
+
+ @Override
+ public void accept(ServerInterpreter interpreter) {
+ interpreter.received(this);
+ }
+
+ @Override
+ public String getInfoTextKey() {
+ return "";
+ }
+}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/UpdateTSKMessage.java b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/UpdateTSKMessage.java
index bbbdf14b..2da6f682 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/UpdateTSKMessage.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/UpdateTSKMessage.java
@@ -18,23 +18,26 @@ public class UpdateTSKMessage extends ServerMessage {
*/
private final Color color;
+ private final boolean isTaken;
+
/**
* Constructs a new UpdateTSK instance with the specified id and color.
*
* @param id the name associated with the update
* @param color the color associated with the update
*/
- public UpdateTSKMessage(int id, Color color) {
+ public UpdateTSKMessage(int id, Color color, boolean isTaken) {
super();
this.id = id;
this.color = color;
+ this.isTaken = isTaken;
}
/**
* Default constructor for serialization purposes.
*/
private UpdateTSKMessage() {
- this(0, null);
+ this(0, null, false);
}
/**
@@ -84,4 +87,8 @@ public String toString() {
public String getInfoTextKey() {
return "";
}
+
+ public boolean isTaken() {
+ return isTaken;
+ }
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/notification/RollDiceNotification.java b/Projekte/mdga/model/src/main/java/pp/mdga/notification/RollDiceNotification.java
index 13bf849b..2e6f03e1 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/notification/RollDiceNotification.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/notification/RollDiceNotification.java
@@ -11,6 +11,7 @@ public class RollDiceNotification extends Notification{
private int eyes;
private boolean turbo;
private int multiplier;
+ private boolean isRanking;
/**
* Constructor.
@@ -22,6 +23,15 @@ public RollDiceNotification(Color color, int eyes) {
this.eyes = eyes;
this.turbo = false;
this.multiplier = -1;
+ this.isRanking = false;
+ }
+
+ public RollDiceNotification(Color color, int eyes, boolean isRanking) {
+ this.color = color;
+ this.eyes = eyes;
+ this.turbo = false;
+ this.multiplier = -1;
+ this.isRanking = isRanking;
}
public RollDiceNotification(Color color, int eyes, boolean turbo, int multiplier) {
@@ -29,6 +39,7 @@ public RollDiceNotification(Color color, int eyes, boolean turbo, int multiplier
this.eyes = eyes;
this.turbo = turbo;
this.multiplier = multiplier;
+ this.isRanking = false;
}
/**
@@ -54,4 +65,6 @@ public int getMultiplier() {
public boolean isTurbo() {
return turbo;
}
+
+ public boolean isRanking() { return isRanking; }
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java
index 6d72dcc5..167992c2 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java
@@ -7,6 +7,7 @@
import pp.mdga.message.server.*;
import pp.mdga.server.ServerGameLogic;
+import java.util.ArrayList;
import java.util.Map;
/**
@@ -48,7 +49,7 @@ public void exit() {
* This method will be used to initialize the game and all necessary objects.
*/
public void initializeGame() {
- for (Map.Entry entry: this.logic.getGame().getPlayers().entrySet()) {
+ for (Map.Entry entry : this.logic.getGame().getPlayers().entrySet()) {
this.logic.getGame().getBoard().addPlayerData(entry.getValue().getColor(), new PlayerData(entry.getValue().getColor()));
}
}
@@ -63,7 +64,7 @@ public void initializeGame() {
@Override
public void received(JoinedLobbyMessage msg, int from) {
Player player = new Player(msg.getName());
- player.setColor(Color.getColorByIndex(this.logic.getGame().getPlayers().size()));
+ player.setColor(Color.NONE);
this.logic.getGame().addPlayer(from, player);
for (Map.Entry entry : this.logic.getGame().getPlayers().entrySet()) {
this.logic.getServerSender().broadcast(new LobbyPlayerJoinedMessage(entry.getKey(), entry.getValue(), entry.getKey() == this.logic.getGame().getHost()));
@@ -84,8 +85,13 @@ public void received(SelectTSKMessage msg, int from) {
return;
}
}
+
+ if (this.logic.getGame().getPlayerById(from).getColor() != Color.NONE) {
+ this.logic.getServerSender().broadcast(new UpdateTSKMessage(from, this.logic.getGame().getPlayerById(from).getColor(), false));
+ }
+
this.logic.getGame().getPlayerById(from).setColor(msg.getColor());
- this.logic.getServerSender().broadcast(new UpdateTSKMessage(from, msg.getColor()));
+ this.logic.getServerSender().broadcast(new UpdateTSKMessage(from, msg.getColor(), true));
}
/**
@@ -98,7 +104,7 @@ public void received(SelectTSKMessage msg, int from) {
@Override
public void received(DeselectTSKMessage msg, int from) {
this.logic.getGame().getPlayerById(from).setColor(Color.NONE);
- this.logic.getServerSender().broadcast(new UpdateTSKMessage(from, Color.NONE));
+ this.logic.getServerSender().broadcast(new UpdateTSKMessage(from, Color.NONE, false));
}
/**
@@ -110,6 +116,28 @@ public void received(DeselectTSKMessage msg, int from) {
*/
@Override
public void received(LobbyReadyMessage msg, int from) {
+ //assign a free color
+ if (this.logic.getGame().getPlayerById(from).getColor() == Color.NONE) {
+ ArrayList colors = new ArrayList<>();
+ colors.add(Color.ARMY);
+ colors.add(Color.AIRFORCE);
+ colors.add(Color.NAVY);
+ colors.add(Color.CYBER);
+
+ for (Map.Entry entry : this.logic.getGame().getPlayers().entrySet()) {
+ if (colors.contains(entry.getValue().getColor())) {
+ colors.remove(entry.getValue().getColor());
+ }
+ }
+
+ if (colors.size() < 1) {
+ throw new RuntimeException("can not assign a color");
+ }
+
+ this.logic.getGame().getPlayerById(from).setColor(colors.get(0));
+ this.logic.getServerSender().broadcast(new UpdateTSKMessage(from, colors.get(0), true));
+ }
+
this.logic.getGame().getPlayerById(from).setReady(true);
this.logic.getServerSender().broadcast(new UpdateReadyMessage(from, true));
for (Map.Entry entry : this.logic.getGame().getPlayers().entrySet()) {
@@ -120,8 +148,12 @@ public void received(LobbyReadyMessage msg, int from) {
this.logic.getGame().setAllReady(true);
if (this.logic.getGame().allReady()) {
+ this.logic.getServerSender().broadcast(new StartBriefingMessage(this.logic.getGame().getBoard()));
this.initializeGame();
- this.logic.getServerSender().broadcast(new ServerStartGameMessage(this.logic.getGame().getBoard()));
+ for (Map.Entry entry : logic.getGame().getBoard().getPlayerData().entrySet()) {
+ this.logic.getServerSender().broadcast(new PlayerDataMessage(entry.getValue(), entry.getKey()));
+ }
+ this.logic.getServerSender().broadcast(new ServerStartGameMessage());
}
}
@@ -148,6 +180,9 @@ public void received(LobbyNotReadyMessage msg, int from) {
*/
@Override
public void received(LeaveGameMessage msg, int from) {
+ if (from == this.logic.getGame().getHost()) {
+ this.logic.getServerSender().broadcast(new ShutdownMessage());
+ }
this.logic.getGame().removePlayer(from);
this.logic.getServerSender().broadcast(new LobbyPlayerLeaveMessage(from));
this.logic.getServerSender().disconnectClient(from);
@@ -164,7 +199,7 @@ public void received(LeaveGameMessage msg, int from) {
public void received(StartGameMessage msg, int from) {
if (msg.isForceStartGame() || this.logic.getGame().allReady()) {
this.initializeGame();
- this.logic.getServerSender().broadcast(new ServerStartGameMessage(this.logic.getGame().getBoard()));
+ this.logic.getServerSender().broadcast(new ServerStartGameMessage());
this.logic.setCurrentState(this.logic.getGameState());
}
}
diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/game/DetermineStartPlayerState.java b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/game/DetermineStartPlayerState.java
index 3e76cf70..42c71629 100644
--- a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/game/DetermineStartPlayerState.java
+++ b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/game/DetermineStartPlayerState.java
@@ -4,6 +4,7 @@
import pp.mdga.message.client.RequestDieMessage;
import pp.mdga.message.server.ActivePlayerMessage;
import pp.mdga.message.server.DieMessage;
+import pp.mdga.message.server.EndOfTurnMessage;
import pp.mdga.server.ServerGameLogic;
import pp.mdga.server.automaton.GameState;
@@ -69,6 +70,7 @@ public void received(RequestDieMessage msg, int from) {
maximumRoll = entry.getValue();
} else {
this.playersHaveToRoll.remove(entry.getKey());
+ this.logic.getServerSender().send(entry.getKey(), new EndOfTurnMessage());
}
}