Merge branch 'development' into 'dev/test'

merge dev into test

See merge request progproj/gruppen-ht24/Gruppe-01!30
This commit is contained in:
Benjamin Feyer
2024-12-02 00:29:39 +00:00
31 changed files with 366 additions and 122 deletions

View File

@@ -21,6 +21,7 @@
import pp.mdga.game.BonusCard; import pp.mdga.game.BonusCard;
import pp.mdga.game.Color; import pp.mdga.game.Color;
import pp.mdga.game.Piece; import pp.mdga.game.Piece;
import pp.mdga.notification.FinishNotification;
import pp.mdga.notification.SelectableCardsNotification; import pp.mdga.notification.SelectableCardsNotification;
import java.util.List; import java.util.List;
@@ -116,7 +117,7 @@ else if(boardSelect != null) {
} }
if(name.equals("Test") &&isPressed){ if(name.equals("Test") &&isPressed){
if(app.getView() instanceof GameView gameView){ if(app.getView() instanceof GameView gameView){
app.getNotificationSynchronizer().addTestNotification(new SelectableCardsNotification(List.of(BonusCard.SHIELD))); app.getNotificationSynchronizer().addTestNotification(new FinishNotification(Color.NAVY));
} }
} }
} }
@@ -151,6 +152,7 @@ else if (name.equals("MouseLeft") || name.equals("MouseRight") || name.equals("M
* Detects the hovered piece and updates its hover state. * Detects the hovered piece and updates its hover state.
*/ */
private <T extends AbstractControl> T checkHover(Camera cam, Node root, Class<T> controlType) { private <T extends AbstractControl> T checkHover(Camera cam, Node root, Class<T> controlType) {
if(cam == null || root == null || controlType == null) return null;
CollisionResults results = new CollisionResults(); CollisionResults results = new CollisionResults();
Ray ray = new Ray(cam.getLocation(), getMousePos(cam).subtract(cam.getLocation()).normalize()); Ray ray = new Ray(cam.getLocation(), getMousePos(cam).subtract(cam.getLocation()).normalize());
root.collideWith(ray, results); root.collideWith(ray, results);
@@ -164,6 +166,7 @@ private <T extends AbstractControl> T checkHover(Camera cam, Node root, Class<T>
* Detects the hovered card and updates its hover state. * Detects the hovered card and updates its hover state.
*/ */
private <T extends AbstractControl> T checkHoverOrtho(Camera cam, Node root, Class<T> controlType) { private <T extends AbstractControl> T checkHoverOrtho(Camera cam, Node root, Class<T> controlType) {
if(cam == null || root == null || controlType == null) return null;
CollisionResults results = new CollisionResults(); CollisionResults results = new CollisionResults();
Vector3f mousePos = getMousePos(cam); Vector3f mousePos = getMousePos(cam);
mousePos.setZ(cam.getLocation().getZ()); mousePos.setZ(cam.getLocation().getZ());

View File

@@ -249,8 +249,19 @@ public ExecutorService getExecutor() {
return this.executor; return this.executor;
} }
public ServerConnection getNetworkSupport() { public ServerConnection getNetworkSupport(){
return networkConnection; return networkConnection;
} }
public void updateResolution(int width, int height) {
AppSettings settings = getContext().getSettings();
settings.setResolution(width, height);
setSettings(settings);
restart();
enter(state);
}
} }

View File

@@ -23,15 +23,22 @@ public class ModelSynchronizer {
private UUID a; private UUID a;
private UUID b; private UUID b;
private BonusCard card; private BonusCard card;
private boolean swap;
ModelSynchronizer(MdgaApp app) { ModelSynchronizer(MdgaApp app) {
this.app = app; this.app = app;
swap = false;
} }
public void animationEnd() { public void animationEnd() {
app.getGameLogic().selectAnimationEnd(); app.getGameLogic().selectAnimationEnd();
} }
public void select(UUID a, UUID b){
if(swap) selectSwap(a,b);
else selectPiece(a);
}
public void selectSwap(UUID a, UUID b) { public void selectSwap(UUID a, UUID b) {
// TODO call from somewhere // TODO call from somewhere
LOGGER.log(Level.INFO, "selectPiece"); LOGGER.log(Level.INFO, "selectPiece");
@@ -134,4 +141,8 @@ public void enter(MdgaState state) {
LOGGER.log(Level.INFO, "enter: {0}", state); LOGGER.log(Level.INFO, "enter: {0}", state);
//app.enter(state); //app.enter(state);
} }
public void setSwap(boolean swap){
this.swap = swap;
}
} }

View File

@@ -21,10 +21,12 @@ public class NotificationSynchronizer {
public void addTestNotification(Notification n) { public void addTestNotification(Notification n) {
notifications.add(n); notifications.add(n);
handleGame(n);
} }
public void update() { public void update() {
Notification n = app.getGameLogic().getNotification(); Notification n = app.getGameLogic().getNotification();
if(n != null) { if(n != null) {
switch (app.getState()) { switch (app.getState()) {
case MAIN: case MAIN:
@@ -43,7 +45,6 @@ public void update() {
throw new RuntimeException("no notification expected: " + n.toString()); throw new RuntimeException("no notification expected: " + n.toString());
} }
} }
notifications.clear();
} }
private void handleMain(Notification notification) { private void handleMain(Notification notification) {
@@ -77,6 +78,7 @@ private void handleGame(Notification notification) {
GameView gameView = (GameView) app.getView(); GameView gameView = (GameView) app.getView();
GuiHandler guiHandler = gameView.getGuiHandler(); GuiHandler guiHandler = gameView.getGuiHandler();
BoardHandler boardHandler = gameView.getBoardHandler(); BoardHandler boardHandler = gameView.getBoardHandler();
ModelSynchronizer modelSynchronizer = app.getModelSynchronize();
if (notification instanceof AcquireCardNotification n) { if (notification instanceof AcquireCardNotification n) {
guiHandler.addCard(n.getBonusCard()); guiHandler.addCard(n.getBonusCard());
@@ -111,8 +113,6 @@ private void handleGame(Notification notification) {
} }
} else if (notification instanceof DiceNowNotification) { } else if (notification instanceof DiceNowNotification) {
guiHandler.showDice(); guiHandler.showDice();
} else if (notification instanceof DicingNotification n) {
//TODO ???
} else if (notification instanceof DrawCardNotification n) { } else if (notification instanceof DrawCardNotification n) {
guiHandler.drawCard(n.getColor()); guiHandler.drawCard(n.getColor());
} else if (notification instanceof HomeMoveNotification home) { } else if (notification instanceof HomeMoveNotification home) {
@@ -129,6 +129,7 @@ private void handleGame(Notification notification) {
//InfieldMove //InfieldMove
boardHandler.movePiece(n.getPiece(), n.getStartIndex(), n.getMoveIndex()); boardHandler.movePiece(n.getPiece(), n.getStartIndex(), n.getMoveIndex());
} }
guiHandler.hideText();
} else if (notification instanceof ThrowPieceNotification n) { } else if (notification instanceof ThrowPieceNotification n) {
boardHandler.throwPiece(n.getPieceId()); boardHandler.throwPiece(n.getPieceId());
} else if (notification instanceof NoShieldNotification n) { } else if (notification instanceof NoShieldNotification n) {
@@ -168,12 +169,17 @@ private void handleGame(Notification notification) {
//TODO ??? //TODO ???
} else if (notification instanceof SelectableMoveNotification n) { } else if (notification instanceof SelectableMoveNotification n) {
boardHandler.outlineMove(n.getPieces(), n.getMoveIndices(), n.getHomeMoves()); boardHandler.outlineMove(n.getPieces(), n.getMoveIndices(), n.getHomeMoves());
modelSynchronizer.setSwap(false);
} else if (notification instanceof SelectableSwapNotification n) { } else if (notification instanceof SelectableSwapNotification n) {
boardHandler.outlineSwap(n.getOwnPieces(), n.getEnemyPieces()); boardHandler.outlineSwap(n.getOwnPieces(), n.getEnemyPieces());
modelSynchronizer.setSwap(true);
} else if (notification instanceof SelectableShieldNotification n) { } else if (notification instanceof SelectableShieldNotification n) {
boardHandler.outlineShield(n.getPieces()); boardHandler.outlineShield(n.getPieces());
modelSynchronizer.setSwap(false);
} else if (notification instanceof TurboActiveNotification){ } else if (notification instanceof TurboActiveNotification){
guiHandler.turbo(); guiHandler.turbo();
} else if (notification instanceof FinishNotification n){
guiHandler.finish(n.getColorFinished());
} else { } else {
throw new RuntimeException("notification not expected: " + notification.toString()); throw new RuntimeException("notification not expected: " + notification.toString());
} }

View File

@@ -439,6 +439,8 @@ else if(selectableEnemyPieces.contains(pieceSelected)) {
} }
} }
else throw new RuntimeException("pieceSelected is not in own/enemySelectablePieces"); else throw new RuntimeException("pieceSelected is not in own/enemySelectablePieces");
app.getModelSynchronize().select(getKeyByValue(pieces, selectedOwnPiece), getKeyByValue(pieces, selectedEnemyPiece));
} }
//called when view is no longer needed to select pieces //called when view is no longer needed to select pieces
@@ -477,5 +479,13 @@ public void hideDice(){
diceControl.hide(); diceControl.hide();
} }
private <K, V> K getKeyByValue(Map<K, V> map, V value) {
for (Map.Entry<K, V> entry : map.entrySet()) {
if (entry.getValue().equals(value)) {
return entry.getKey();
}
}
return null;
}
} }

View File

@@ -71,4 +71,8 @@ public void update(float delta) {
} }
} }
} }
public NetworkSupport getNetwork(){
return network;
}
} }

View File

@@ -9,6 +9,13 @@
public class VideoSettingsDialog extends Dialog { public class VideoSettingsDialog extends Dialog {
private MenuButton backButton; private MenuButton backButton;
private MenuButton hdButton9;
private MenuButton fullHdButton9;
private MenuButton wqhdButton9;
private MenuButton hdButton10;
private MenuButton fullHdButton10;
private MenuButton wqhdButton10;
private final MdgaView view; private final MdgaView view;
private boolean active = false; private boolean active = false;
@@ -20,6 +27,15 @@ public VideoSettingsDialog(MdgaApp app, Node node, MdgaView view) {
backButton = new MenuButton(app, node, view::leaveVideoSettings, "Zurück"); backButton = new MenuButton(app, node, view::leaveVideoSettings, "Zurück");
// MenuButton für verschiedene Auflösungen erstellen
hdButton9 = new MenuButton(app, node, () -> app.updateResolution(1280, 720), "hd 16:9");
fullHdButton9 = new MenuButton(app, node, () -> app.updateResolution(1920, 1080), "full hd 16:9");
wqhdButton9 = new MenuButton(app, node, () -> app.updateResolution(2560, 1440), "wqhd 16:9");
hdButton10 = new MenuButton(app, node, () -> app.updateResolution(1280, 800), "hd 16:10");
fullHdButton10 = new MenuButton(app, node, () -> app.updateResolution(1920, 1200), "full hd 16:10");
wqhdButton10 = new MenuButton(app, node, () -> app.updateResolution(2560, 1600), "wqhd 16:10");
float offset = 2.8f; float offset = 2.8f;
backButton.setPos(new Vector2f(0, 1.8f)); backButton.setPos(new Vector2f(0, 1.8f));
@@ -29,6 +45,14 @@ public VideoSettingsDialog(MdgaApp app, Node node, MdgaView view) {
protected void onShow() { protected void onShow() {
active = true; active = true;
hdButton9.show();
fullHdButton9.show();
wqhdButton9.show();
hdButton10.show();
fullHdButton10.show();
wqhdButton10.show();
backButton.show(); backButton.show();
} }
@@ -36,6 +60,14 @@ protected void onShow() {
protected void onHide() { protected void onHide() {
active = false; active = false;
hdButton9.hide();
fullHdButton9.hide();
wqhdButton9.hide();
hdButton10.hide();
fullHdButton10.hide();
wqhdButton10.hide();
backButton.hide(); backButton.hide();
} }

View File

@@ -111,6 +111,16 @@ public void drawCardOwn(Color color){
createTopText(new String[]{"Du"," erhälst eine Bonuskarte"}, 5,70, new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl()); 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){
createTopText(new String[]{name," ist fertig!"}, 7,70, new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl());
}
public void finishTextOwn(Color color){
createTopText(new String[]{"Du", " bist fertig!"}, 7,70, new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl());
}
private ColorRGBA playerColorToColorRGBA(Color color){ private ColorRGBA playerColorToColorRGBA(Color color){
return switch (color){ return switch (color){
case ARMY -> ColorRGBA.Green; case ARMY -> ColorRGBA.Green;

View File

@@ -51,7 +51,7 @@ public void rollDice(int rollNum, int mult) {
if(mult == -1) actionTextHandler.ownDice(rollNum); if(mult == -1) actionTextHandler.ownDice(rollNum);
else actionTextHandler.ownDiceMult(rollNum, mult); else actionTextHandler.ownDiceMult(rollNum, mult);
hideDice(); hideDice();
//TODO send Model finished app.getModelSynchronize().animationEnd();
}); });
} }
@@ -129,5 +129,10 @@ public void drawCard(Color color) {
else actionTextHandler.drawCard(playerNameHandler.getName(color), color); else actionTextHandler.drawCard(playerNameHandler.getName(color), color);
} }
public void finish(Color color){
if(ownColor == color) actionTextHandler.finishTextOwn(color);
else actionTextHandler.finishText(playerNameHandler.getName(color), color);
}
} }

View File

@@ -2,9 +2,7 @@
import com.jme3.network.*; import com.jme3.network.*;
import com.jme3.network.serializing.Serializer; import com.jme3.network.serializing.Serializer;
import pp.mdga.game.Game; import pp.mdga.game.*;
import pp.mdga.game.Player;
import pp.mdga.game.Statistic;
import pp.mdga.message.client.*; import pp.mdga.message.client.*;
import pp.mdga.message.server.*; import pp.mdga.message.server.*;
import pp.mdga.server.ServerGameLogic; import pp.mdga.server.ServerGameLogic;
@@ -138,6 +136,13 @@ private void initializeSerializables() {
Serializer.registerClass(WaitPieceMessage.class); Serializer.registerClass(WaitPieceMessage.class);
Serializer.registerClass(Player.class); Serializer.registerClass(Player.class);
Serializer.registerClass(Statistic.class); Serializer.registerClass(Statistic.class);
Serializer.registerClass(Board.class);
Serializer.registerClass(Node.class);
Serializer.registerClass(Piece.class);
Serializer.registerClass(BonusNode.class);
Serializer.registerClass(StartNode.class);
Serializer.registerClass(PlayerData.class);
Serializer.registerClass(HomeNode.class);
} }
private void registerListeners() { private void registerListeners() {
@@ -194,6 +199,9 @@ private void messageReceived(HostedConnection source, ClientMessage message) {
public void connectionAdded(Server server, HostedConnection hostedConnection) { public void connectionAdded(Server server, HostedConnection hostedConnection) {
System.out.println("new connection " + hostedConnection); //NON-NLS System.out.println("new connection " + hostedConnection); //NON-NLS
LOGGER.log(Level.DEBUG, "new connection {0}", hostedConnection); //NON-NLS LOGGER.log(Level.DEBUG, "new connection {0}", hostedConnection); //NON-NLS
if (this.myServer.getConnections().size() == 1) {
this.logic.getGame().setHost(hostedConnection.getId());
}
} }
@Override @Override

View File

@@ -20,6 +20,7 @@
import pp.mdga.notification.RollDiceNotification; import pp.mdga.notification.RollDiceNotification;
import pp.mdga.notification.SelectableCardsNotification; import pp.mdga.notification.SelectableCardsNotification;
import pp.mdga.notification.SelectableMoveNotification; import pp.mdga.notification.SelectableMoveNotification;
import pp.mdga.notification.SelectableSwapNotification;
import pp.mdga.notification.ShieldActiveNotification; import pp.mdga.notification.ShieldActiveNotification;
import java.util.ArrayList; import java.util.ArrayList;
@@ -31,8 +32,6 @@ public class GameView extends MdgaView {
private CameraHandler camera; private CameraHandler camera;
private GuiHandler guiHandler; private GuiHandler guiHandler;
private ButtonRight cheatButton; //TODO
private ButtonLeft leaveButton; private ButtonLeft leaveButton;
private ButtonRight confirmButton; private ButtonRight confirmButton;
@@ -43,7 +42,6 @@ public class GameView extends MdgaView {
public GameView(MdgaApp app) { public GameView(MdgaApp app) {
super(app); super(app);
cheatButton = new ButtonRight(app, overlayNode, () -> app.getModelSynchronize().enter(MdgaState.CEREMONY), "CHEAT", 1);
leaveButton = new ButtonLeft(app, overlayNode, () -> app.getModelSynchronize().leave(), "Spiel verlassen", 1); leaveButton = new ButtonLeft(app, overlayNode, () -> app.getModelSynchronize().leave(), "Spiel verlassen", 1);
confirmButton = new ButtonRight(app, guiNode, () -> app.getModelSynchronize().confirm(), "Bestätigen", 1); confirmButton = new ButtonRight(app, guiNode, () -> app.getModelSynchronize().confirm(), "Bestätigen", 1);
@@ -66,41 +64,6 @@ public void onEnter() {
app.getViewPort().addProcessor(fpp); app.getViewPort().addProcessor(fpp);
app.getAcousticHandler().playSound(MdgaSound.START); app.getAcousticHandler().playSound(MdgaSound.START);
//Test
// List<UUID> uuid1 = new ArrayList<>();
// UUID p1 = UUID.randomUUID();
// UUID p2 = UUID.randomUUID();
// uuid1.add(p1);
// uuid1.add(p2);
// uuid1.add(UUID.randomUUID());
// uuid1.add(UUID.randomUUID());
// List<UUID> uuid2 = new ArrayList<>();
// UUID p1_2 = UUID.randomUUID();
// UUID p2_2 = UUID.randomUUID();
// uuid2.add(p1_2);
// uuid2.add(p2_2);
// uuid2.add(UUID.randomUUID());
// uuid2.add(UUID.randomUUID());
// app.getNotificationSynchronizer().addTestNotification(new PlayerInGameNotification(Color.AIRFORCE, uuid1, "Cedric"));
// app.getNotificationSynchronizer().addTestNotification(new PlayerInGameNotification(Color.NAVY, uuid2, "Test"));
// app.getNotificationSynchronizer().addTestNotification(new MovePieceNotification(p1, 0, true));
// app.getNotificationSynchronizer().addTestNotification(new MovePieceNotification(p1_2, 30, true));
// app.getNotificationSynchronizer().addTestNotification(new SelectableMoveNotification(List.of(p1), List.of(4), List.of(false)));
// app.getNotificationSynchronizer().addTestNotification(new AcquireCardNotification(BonusCard.SHIELD));
// app.getNotificationSynchronizer().addTestNotification(new SelectableCardsNotification(List.of(BonusCard.SHIELD)));
// app.getNotificationSynchronizer().addTestNotification(new ShieldActiveNotification(p1));
// app.getNotificationSynchronizer().addTestNotification(new ActivePlayerNotification(Color.NAVY));
// app.getNotificationSynchronizer().addTestNotification(new DiceNowNotification());
// app.getNotificationSynchronizer().addTestNotification(new RollDiceNotification(Color.AIRFORCE, 5, true, 2));
//p1 = p1;
} }
@Override @Override
@@ -124,7 +87,6 @@ public void onUpdate(float tpf) {
protected void onEnterOverlay(Overlay overlay) { protected void onEnterOverlay(Overlay overlay) {
if(overlay == Overlay.SETTINGS) { if(overlay == Overlay.SETTINGS) {
leaveButton.show(); leaveButton.show();
cheatButton.show();
} }
} }
@@ -132,7 +94,6 @@ protected void onEnterOverlay(Overlay overlay) {
protected void onLeaveOverlay(Overlay overlay) { protected void onLeaveOverlay(Overlay overlay) {
if(overlay == Overlay.SETTINGS) { if(overlay == Overlay.SETTINGS) {
leaveButton.hide(); leaveButton.hide();
cheatButton.hide();
} }
} }

View File

@@ -106,13 +106,11 @@ private void tryHost() {
try { try {
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
// todo: implement
} }
hostDialog.connectServerAsClient(); hostDialog.connectServerAsClient();
try { try {
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
// todo: implement
} }
app.getModelSynchronize().setHost(port); app.getModelSynchronize().setHost(port);
//app.getAcousticHandler().playSound(MdgaSound.WRONG_INPUT); //app.getAcousticHandler().playSound(MdgaSound.WRONG_INPUT);

View File

@@ -53,6 +53,10 @@ public void setOwnPlayerName(String ownPlayerName) {
this.ownPlayerName = ownPlayerName; this.ownPlayerName = ownPlayerName;
} }
public void setOwnPlayerId(int ownPlayerId) {
this.ownPlayerID = ownPlayerId;
}
public LobbyState getLobby() { public LobbyState getLobby() {
return lobbyState; return lobbyState;
} }

View File

@@ -8,6 +8,9 @@
public class GameState extends ClientState { public class GameState extends ClientState {
/**
* the current substate
*/
private GameStates state; private GameStates state;
private final AnimationState animationState = new AnimationState(this, logic); private final AnimationState animationState = new AnimationState(this, logic);
@@ -16,21 +19,38 @@ public class GameState extends ClientState {
private final TurnState turnState = new TurnState(this, logic); private final TurnState turnState = new TurnState(this, logic);
private final WaitingState waitingState = new WaitingState(this, logic); private final WaitingState waitingState = new WaitingState(this, logic);
/**
* Constructor for GameState
*
* @param parent the parent of this state
* @param logic the ClientGameLogic
*/
public GameState(ClientState parent, ClientGameLogic logic) { public GameState(ClientState parent, ClientGameLogic logic) {
super(parent, logic); super(parent, logic);
state = determineStartPlayerState; state = determineStartPlayerState;
} }
/**
* The method to enter the state
*/
@Override @Override
public void enter() { public void enter() {
} }
/**
* the method to exit this state
*/
@Override @Override
public void exit() { public void exit() {
state.exit();
} }
/**
* This method is used to set a new SubState
*
* @param newState the state to be set
*/
public void setState(GameStates newState){ public void setState(GameStates newState){
state.exit(); state.exit();
state.enter(); state.enter();

View File

@@ -26,19 +26,35 @@ public void enter() {
previousState = null; previousState = null;
} }
/**
* exits this state
*/
@Override @Override
public void exit() { public void exit() {
previousState = null; previousState = null;
} }
/**
* This method sets the stores the gamestate as previous state
*
* @param previousState
*/
public void setPreviousState(ClientState previousState) { public void setPreviousState(ClientState previousState) {
this.previousState = previousState; this.previousState = previousState;
} }
/**
* returns teh previous gamestate
*
* @return the previous gamestate
*/
public ClientState getPreviousState() { public ClientState getPreviousState() {
return previousState; return previousState;
} }
/**
* The host resumes the game
*/
@Override @Override
public void selectResume(){ public void selectResume(){
if(logic.isHost()){ if(logic.isHost()){
@@ -46,6 +62,11 @@ public void selectResume(){
} }
} }
/**
* The server resumes the game
*
* @param msg the ResumeGame message received
*/
public void received(ResumeGameMessage msg) { public void received(ResumeGameMessage msg) {
//TODO: logic.addNotification(new ResumeNotification()); //TODO: logic.addNotification(new ResumeNotification());
logic.setState(previousState); logic.setState(previousState);

View File

@@ -4,17 +4,18 @@
import pp.mdga.client.ClientState; import pp.mdga.client.ClientState;
import pp.mdga.client.DialogsState; import pp.mdga.client.DialogsState;
import pp.mdga.game.Color; import pp.mdga.game.Color;
import pp.mdga.game.Piece;
import pp.mdga.game.Player; import pp.mdga.game.Player;
import pp.mdga.game.PlayerData;
import pp.mdga.message.client.*; import pp.mdga.message.client.*;
import pp.mdga.message.server.LobbyPlayerJoinedMessage; import pp.mdga.message.server.LobbyPlayerJoinedMessage;
import pp.mdga.message.server.LobbyPlayerLeaveMessage; import pp.mdga.message.server.LobbyPlayerLeaveMessage;
import pp.mdga.message.server.ServerStartGameMessage; import pp.mdga.message.server.ServerStartGameMessage;
import pp.mdga.message.server.UpdateReadyMessage; import pp.mdga.message.server.UpdateReadyMessage;
import pp.mdga.message.server.UpdateTSKMessage; import pp.mdga.message.server.UpdateTSKMessage;
import pp.mdga.notification.LobbyReadyNotification; import pp.mdga.notification.*;
import pp.mdga.notification.StartDialogNotification;
import pp.mdga.notification.TskSelectNotification; import java.util.*;
import pp.mdga.notification.TskUnselectNotification;
public class LobbyState extends DialogStates { public class LobbyState extends DialogStates {
@@ -74,12 +75,26 @@ public void selectStart(){
@Override @Override
public void received(ServerStartGameMessage msg){ public void received(ServerStartGameMessage msg){
logic.getGame().setBoard(msg.getBoard());
logic.addNotification(new GameNotification(logic.getGame().getPlayers().get(parent.getOwnPlayerId()).getColor()));
for(Map.Entry<Color, PlayerData> entry : msg.getBoard().getPlayerData().entrySet()){
List<UUID> pieceIds = new ArrayList<>();
for(Piece piece : entry.getValue().getPieces()){
pieceIds.add(piece.getUuid());
}
logic.addNotification(new PlayerInGameNotification(entry.getKey(), pieceIds, logic.getGame().getPlayerByColor(entry.getKey()).getName()));
}
parent.startGame(); parent.startGame();
} }
@Override @Override
public void received(LobbyPlayerJoinedMessage msg){ public void received(LobbyPlayerJoinedMessage msg){
if(msg.getPlayer().getName().equals(parent.getOwnPlayerName())){
parent.setOwnPlayerId(msg.getId());
}
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(), parent.getOwnPlayerId()== msg.getId()));
logic.getGame().getPlayers().put(msg.getId(), msg.getPlayer()); logic.getGame().getPlayers().put(msg.getId(), msg.getPlayer());
} }
@@ -99,6 +114,7 @@ public void received(LobbyPlayerLeaveMessage msg){
@Override @Override
public void received(UpdateReadyMessage msg){ public void received(UpdateReadyMessage msg){
//TODO server sendet kein update on UNready
logic.addNotification(new LobbyReadyNotification(logic.getGame().getPlayers().get(msg.getPlayerId()).getColor(), msg.isReady())); logic.addNotification(new LobbyReadyNotification(logic.getGame().getPlayers().get(msg.getPlayerId()).getColor(), msg.isReady()));
logic.getGame().getPlayers().get(msg.getPlayerId()).setReady(msg.isReady()); logic.getGame().getPlayers().get(msg.getPlayerId()).setReady(msg.isReady());
} }

View File

@@ -1,12 +1,16 @@
package pp.mdga.game; package pp.mdga.game;
import com.jme3.network.serializing.Serializable;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
* This class will be used to hold all Board relevant data. * This class will be used to hold all Board relevant data.
*/ */
@Serializable
public class Board { public class Board {
private Map<Color, PlayerData> playerData; private Map<Color, PlayerData> playerData = new HashMap<>();
private final Node[] infield; private final Node[] infield;
/** /**
@@ -30,6 +34,17 @@ public Board() {
} }
} }
/**
* This method will be used to add the given color and playerData parameters to the playerData attribute of
* Board class.
*
* @param color as the color of the player as a Color enumeration.
* @param playerData as the playerData of the player as a PlayerData object.
*/
public void addPlayerData(Color color, PlayerData playerData) {
this.playerData.put(color, playerData);
}
/** /**
* This method returns the playerData * This method returns the playerData
* *

View File

@@ -1,7 +1,13 @@
package pp.mdga.game; package pp.mdga.game;
import com.jme3.network.serializing.Serializable;
/** /**
* This class represents a BonusNode * This class represents a BonusNode
*/ */
@Serializable
public class BonusNode extends Node { public class BonusNode extends Node {
BonusNode(){
super();
}
} }

View File

@@ -42,6 +42,9 @@ public class Game {
// The die used in the game. // The die used in the game.
private Die die; private Die die;
// The host of this game
private int host;
// The color of the active player. // The color of the active player.
private Color activeColor; private Color activeColor;
@@ -232,6 +235,15 @@ public Color getActiveColor() {
return activeColor; return activeColor;
} }
/**
* This method will be used to return host attribute of Game class.
*
* @return host as an Integer.
*/
public int getHost() {
return this.host;
}
/** /**
* This method sets the dice modifier. * This method sets the dice modifier.
* *
@@ -304,6 +316,15 @@ public void setActiveColor(Color activeColor) {
this.activeColor = activeColor; this.activeColor = activeColor;
} }
/**
* This method will be used to set host attribute of Game class to the given host parameter.
*
* @param host as the new value of host as an Integer.
*/
public void setHost(int host) {
this.host = host;
}
/** /**
* This method returns the all ready state. * This method returns the all ready state.
* *

View File

@@ -1,7 +1,13 @@
package pp.mdga.game; package pp.mdga.game;
import com.jme3.network.serializing.Serializable;
/** /**
* Represents a home node. * Represents a home node.
*/ */
@Serializable
public class HomeNode extends Node { public class HomeNode extends Node {
public HomeNode() {
super();
}
} }

View File

@@ -1,11 +1,18 @@
package pp.mdga.game; package pp.mdga.game;
import com.jme3.network.serializing.Serializable;
/** /**
* This class will be used the represent a Node on which the pieces can travel along * This class will be used the represent a Node on which the pieces can travel along
*/ */
@Serializable
public class Node { public class Node {
protected Piece occupant; protected Piece occupant;
public Node(){
}
/** /**
* This method is used to get an occupant of the Node. * This method is used to get an occupant of the Node.
* *

View File

@@ -1,10 +1,13 @@
package pp.mdga.game; package pp.mdga.game;
import com.jme3.network.serializing.Serializable;
import java.util.UUID; import java.util.UUID;
/** /**
* This class will be used to hold all Piece relevant data. * This class will be used to hold all Piece relevant data.
*/ */
@Serializable
public class Piece { public class Piece {
/** /**
* The shield state of the piece. * The shield state of the piece.
@@ -38,6 +41,10 @@ public Piece(Color color, PieceState state, int id) {
shield = ShieldState.NONE; shield = ShieldState.NONE;
} }
private Piece() {
color = null;
}
/** /**
* This method is used to get the color of the piece * This method is used to get the color of the piece
* *

View File

@@ -1,8 +1,11 @@
package pp.mdga.game; package pp.mdga.game;
import com.jme3.network.serializing.Serializable;
/** /**
* This class is used to represent PlayerData related to the board * This class is used to represent PlayerData related to the board
*/ */
@Serializable
public class PlayerData { public class PlayerData {
/** /**
* An array of HomeNode objects representing the home nodes of the player. * An array of HomeNode objects representing the home nodes of the player.
@@ -31,6 +34,7 @@ public class PlayerData {
*/ */
public PlayerData(Color color) { public PlayerData(Color color) {
homeNodes = new HomeNode[4]; homeNodes = new HomeNode[4];
pieces = new Piece[4];
waitingArea = new Piece[4]; waitingArea = new Piece[4];
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
homeNodes[i] = new HomeNode(); homeNodes[i] = new HomeNode();
@@ -39,6 +43,12 @@ public PlayerData(Color color) {
} }
} }
private PlayerData() {
homeNodes = null;
waitingArea = null;
pieces = null;
}
/** /**
* This method returns an Array of HomeNodes * This method returns an Array of HomeNodes
* *

View File

@@ -1,8 +1,11 @@
package pp.mdga.game; package pp.mdga.game;
import com.jme3.network.serializing.Serializable;
/** /**
* Represents a start node. * Represents a start node.
*/ */
@Serializable
public class StartNode extends Node { public class StartNode extends Node {
/** /**
* The color of the node. * The color of the node.
@@ -18,6 +21,10 @@ public StartNode(Color color) {
this.color = color; this.color = color;
} }
private StartNode() {
color = null;
}
/** /**
* This method is used to get the color of the node * This method is used to get the color of the node
* *

View File

@@ -19,16 +19,23 @@ public class LobbyPlayerJoinedMessage extends ServerMessage {
*/ */
private final int id; private final int id;
/**
* The flag is the new player is the host
*/
private final boolean host;
/** /**
* Constructs a new LobbyPlayerJoin instance with the specified player name. * Constructs a new LobbyPlayerJoin instance with the specified player name.
* *
* @param player the player joining the lobby * @param player the player joining the lobby
* @param id the id of the player * @param id the id of the player
* @param host as the flag if the player is the host as a Boolean.
*/ */
public LobbyPlayerJoinedMessage(int id, Player player) { public LobbyPlayerJoinedMessage(int id, Player player, boolean host) {
super(); super();
this.player = player; this.player = player;
this.id = id; this.id = id;
this.host = host;
} }
/** /**
@@ -37,6 +44,7 @@ public LobbyPlayerJoinedMessage(int id, Player player) {
private LobbyPlayerJoinedMessage() { private LobbyPlayerJoinedMessage() {
player = null; player = null;
id = 0; id = 0;
host = false;
} }
/** /**
@@ -57,6 +65,10 @@ public int getId(){
return id; return id;
} }
public boolean isHost() {
return this.host;
}
/** /**
* Accepts a visitor to process this message. * Accepts a visitor to process this message.
* *

View File

@@ -1,17 +1,33 @@
package pp.mdga.message.server; package pp.mdga.message.server;
import com.jme3.network.serializing.Serializable; import com.jme3.network.serializing.Serializable;
import pp.mdga.game.Board;
/** /**
* A message indicating that the game shall start. * A message indicating that the game shall start.
*/ */
@Serializable @Serializable
public class ServerStartGameMessage extends ServerMessage { public class ServerStartGameMessage extends ServerMessage {
/**
* Create ServerStartGameMessage attributes.
*/
private final Board board;
/** /**
* Constructs a new ServerStartGame instance. * Constructs a new ServerStartGame instance.
*/ */
public ServerStartGameMessage() { public ServerStartGameMessage() {
super(); 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;
} }
/** /**
@@ -24,6 +40,15 @@ public void accept(ServerInterpreter interpreter) {
interpreter.received(this); 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. * Returns a string representation of this message.
* *

View File

@@ -1,31 +0,0 @@
package pp.mdga.notification;
import pp.mdga.game.Color;
/**
* Notification that is sent when a player has diced.
*/
public class DicingNotification extends Notification {
/**
* The color of the player that diced.
*/
private final Color color;
/**
* Constructor.
*
* @param color The color of the player that diced.
*/
public DicingNotification(Color color) {
this.color = color;
}
/**
* Get the color of the player that diced.
*
* @return The color of the player that diced.
*/
public Color getColor() {
return color;
}
}

View File

@@ -0,0 +1,15 @@
package pp.mdga.notification;
import pp.mdga.game.Color;
public class FinishNotification extends Notification{
private Color colorFinished;
public FinishNotification(Color colorFinished){
this.colorFinished = colorFinished;
}
public Color getColorFinished() {
return colorFinished;
}
}

View File

@@ -25,9 +25,9 @@ public class GameState extends ServerState {
* Create GameState states. * Create GameState states.
*/ */
private GameAutomatonState currentState; private GameAutomatonState currentState;
private final GameAutomatonState determineStartPlayerState; private final DetermineStartPlayerState determineStartPlayerState;
private final GameAutomatonState animationState; private final AnimationState animationState;
private final GameAutomatonState turnState; private final TurnState turnState;
/** /**
* Constructor. * Constructor.
@@ -122,27 +122,27 @@ public GameAutomatonState getCurrentState() {
/** /**
* This method will be used to return determineStartPlayerState attribute of GameState class. * This method will be used to return determineStartPlayerState attribute of GameState class.
* *
* @return determineStartPlayerState as a GameAutomatonState object. * @return determineStartPlayerState as a DetermineStartPlayerState object.
*/ */
public GameAutomatonState getDetermineStartPlayerState() { public DetermineStartPlayerState getDetermineStartPlayerState() {
return this.determineStartPlayerState; return this.determineStartPlayerState;
} }
/** /**
* This method will be used to return animationState attribute of GameState class. * This method will be used to return animationState attribute of GameState class.
* *
* @return animationState as a GameAutomatonState object. * @return animationState as a AnimationState object.
*/ */
public GameAutomatonState getAnimationState() { public AnimationState getAnimationState() {
return this.animationState; return this.animationState;
} }
/** /**
* This method will be used to return turnState attribute of GameState class. * This method will be used to return turnState attribute of GameState class.
* *
* @return turnState as a GameAutomatonState object. * @return turnState as a TurnState object.
*/ */
public GameAutomatonState getTurnState() { public TurnState getTurnState() {
return this.turnState; return this.turnState;
} }

View File

@@ -2,6 +2,7 @@
import pp.mdga.game.Color; import pp.mdga.game.Color;
import pp.mdga.game.Player; import pp.mdga.game.Player;
import pp.mdga.game.PlayerData;
import pp.mdga.message.client.*; import pp.mdga.message.client.*;
import pp.mdga.message.server.*; import pp.mdga.message.server.*;
import pp.mdga.server.ServerGameLogic; import pp.mdga.server.ServerGameLogic;
@@ -43,6 +44,15 @@ public void exit() {
LOGGER.log(System.Logger.Level.DEBUG, "Exited LobbyState state."); LOGGER.log(System.Logger.Level.DEBUG, "Exited LobbyState state.");
} }
/**
* This method will be used to initialize the game and all necessary objects.
*/
public void initializeGame() {
for (Map.Entry<Integer, Player> entry: this.logic.getGame().getPlayers().entrySet()) {
this.logic.getGame().getBoard().addPlayerData(entry.getValue().getColor(), new PlayerData(entry.getValue().getColor()));
}
}
/** /**
* This method will be called whenever the server received a JoinedLobbyMessage message. * This method will be called whenever the server received a JoinedLobbyMessage message.
* It will also get the client id of the player who send this message * It will also get the client id of the player who send this message
@@ -55,8 +65,8 @@ public void received(JoinedLobbyMessage msg, int from) {
Player player = new Player(msg.getName()); Player player = new Player(msg.getName());
player.setColor(Color.getColorByIndex(this.logic.getGame().getPlayers().size())); player.setColor(Color.getColorByIndex(this.logic.getGame().getPlayers().size()));
this.logic.getGame().addPlayer(from, player); this.logic.getGame().addPlayer(from, player);
for (Map.Entry<Integer, Player> entry: this.logic.getGame().getPlayers().entrySet()) { for (Map.Entry<Integer, Player> entry : this.logic.getGame().getPlayers().entrySet()) {
this.logic.getServerSender().broadcast(new LobbyPlayerJoinedMessage(entry.getKey(), entry.getValue())); this.logic.getServerSender().broadcast(new LobbyPlayerJoinedMessage(entry.getKey(), entry.getValue(), entry.getKey() == this.logic.getGame().getHost()));
} }
} }
@@ -103,12 +113,16 @@ public void received(LobbyReadyMessage msg, int from) {
this.logic.getGame().getPlayerById(from).setReady(true); this.logic.getGame().getPlayerById(from).setReady(true);
this.logic.getServerSender().broadcast(new UpdateReadyMessage(from, true)); this.logic.getServerSender().broadcast(new UpdateReadyMessage(from, true));
for (Map.Entry<Integer, Player> entry : this.logic.getGame().getPlayers().entrySet()) { for (Map.Entry<Integer, Player> entry : this.logic.getGame().getPlayers().entrySet()) {
if (!entry.getValue().isActive()) { if (!entry.getValue().isReady()) {
return; return;
} }
} }
this.logic.getGame().setAllReady(true); this.logic.getGame().setAllReady(true);
if (this.logic.getGame().allReady()) {
this.initializeGame();
this.logic.getServerSender().broadcast(new ServerStartGameMessage(this.logic.getGame().getBoard()));
}
} }
/** /**
@@ -149,7 +163,8 @@ public void received(LeaveGameMessage msg, int from) {
@Override @Override
public void received(StartGameMessage msg, int from) { public void received(StartGameMessage msg, int from) {
if (msg.isForceStartGame() || this.logic.getGame().allReady()) { if (msg.isForceStartGame() || this.logic.getGame().allReady()) {
this.logic.getServerSender().broadcast(new ServerStartGameMessage()); this.initializeGame();
this.logic.getServerSender().broadcast(new ServerStartGameMessage(this.logic.getGame().getBoard()));
this.logic.setCurrentState(this.logic.getGameState()); this.logic.setCurrentState(this.logic.getGameState());
} }
} }

View File

@@ -2,12 +2,14 @@
import pp.mdga.game.Player; import pp.mdga.game.Player;
import pp.mdga.message.client.RequestDieMessage; import pp.mdga.message.client.RequestDieMessage;
import pp.mdga.message.server.ActivePlayerMessage;
import pp.mdga.message.server.DieMessage; import pp.mdga.message.server.DieMessage;
import pp.mdga.server.ServerGameLogic; import pp.mdga.server.ServerGameLogic;
import pp.mdga.server.automaton.GameState; import pp.mdga.server.automaton.GameState;
import pp.mdga.server.automaton.game.turn.RollDiceState;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -21,7 +23,8 @@ public class DetermineStartPlayerState extends GameAutomatonState {
/** /**
* Create DetermineStartPlayerState attributes. * Create DetermineStartPlayerState attributes.
*/ */
private Map<Player, Integer> diceResults = new HashMap<>(); private Map<Integer, Integer> diceResults = new HashMap<>();
private List<Integer> playersHaveToRoll = new ArrayList<>();
/** /**
* Constructs a server state of the specified game logic. * Constructs a server state of the specified game logic.
@@ -36,6 +39,9 @@ public DetermineStartPlayerState(GameState gameAutomaton, ServerGameLogic logic)
@Override @Override
public void enter() { public void enter() {
LOGGER.log(System.Logger.Level.DEBUG, "Entered DetermineStartPlayerState state."); LOGGER.log(System.Logger.Level.DEBUG, "Entered DetermineStartPlayerState state.");
for (Map.Entry<Integer, Player> entry: this.logic.getGame().getPlayers().entrySet()) {
this.playersHaveToRoll.add(entry.getKey());
}
} }
@Override @Override
@@ -53,23 +59,26 @@ public void exit() {
@Override @Override
public void received(RequestDieMessage msg, int from) { public void received(RequestDieMessage msg, int from) {
int roll = this.logic.getGame().getDie().shuffle(); int roll = this.logic.getGame().getDie().shuffle();
this.diceResults.put(this.logic.getGame().getPlayerById(from), roll); this.diceResults.put(from, roll);
int maximumRoll = 0;
if (this.diceResults.size() == this.logic.getGame().getPlayers().size()) { if (this.diceResults.size() == this.logic.getGame().getPlayers().size()) {
Map<Integer, Long> frequencyMap = diceResults.values().stream() for (Map.Entry<Integer, Integer> entry: this.diceResults.entrySet()) {
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); if (maximumRoll == 0) {
Map.Entry<Integer, Long> result = frequencyMap.entrySet().stream() maximumRoll = this.diceResults.get(entry.getKey());
.max(Map.Entry.comparingByKey()) } else if (maximumRoll < entry.getValue()) {
.orElseThrow(() -> new IllegalStateException("Die Map ist leer")); maximumRoll = entry.getValue();
} } else {
this.logic.getServerSender().send(from, new DieMessage(roll)); this.playersHaveToRoll.remove(entry.getKey());
} }
}
/** if (this.playersHaveToRoll.size() == 1) {
* This method will be used to return diceResults attribute of DetermineStartPlayerState class. this.logic.getServerSender().broadcast(new ActivePlayerMessage(this.logic.getGame().getPlayerById(this.playersHaveToRoll.get(0)).getColor()));
* } else {
* @return diceResults as a Map combing Player objects and Integers. for (Integer id: this.playersHaveToRoll) {
*/ this.logic.getServerSender().send(id, new DieMessage(roll));
public Map<Player, Integer> getDiceResults() { }
return this.diceResults; }
}
} }
} }