Compare commits

..

5 Commits

Author SHA1 Message Date
BuildTools
854e2a914b removed unused resources 2022-01-31 22:20:53 +01:00
Johannes-coderer
bfe865a06e Netzwerkkomponente(#9) 2022-01-26 23:03:32 +01:00
Johannes-coderer
f918e23544 Anleitungsscreen(#18) 2022-01-26 15:02:03 +01:00
8313e4ed5b fixed npe in CardUtil.getDefaultTrumpSuit 2022-01-17 18:19:28 +01:00
98dbf5cb74 added sync before determining trump 2022-01-17 15:41:19 +01:00
26 changed files with 120 additions and 124 deletions

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -16,7 +16,7 @@ import eu.jonahbauer.wizard.common.model.Card;
public class InstructionScreen extends MenuScreen {
private static final int MAX_PAGE = 3;
private TextButton buttonOK;
private TextButton buttonBack;
private VerticalGroup content;
private ScrollPane scrollPane;
private TextButton nextPageButton;
@ -29,7 +29,7 @@ public class InstructionScreen extends MenuScreen {
private final ChangeListener listener = new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (actor == buttonOK) {
if (actor == buttonBack) {
game.getClient().execute(Menu.class, Menu::showMenuScreen);
sfxClick();
} else if (actor == nextPageButton) {
@ -70,9 +70,9 @@ public class InstructionScreen extends MenuScreen {
previousPageButton.addListener(listener);
getButtonGroup().addActor(previousPageButton);
buttonOK = new TextButton(messages.get("menu.instruction.back"), skin);
buttonOK.addListener(listener);
getButtonGroup().addActor(buttonOK);
buttonBack = new TextButton(messages.get("menu.instruction.back"), skin);
buttonBack.addListener(listener);
getButtonGroup().addActor(buttonBack);
nextPageButton = new TextButton(messages.get("menu.instruction.nextPageButton"), skin);
nextPageButton.addListener(listener);
@ -83,7 +83,7 @@ public class InstructionScreen extends MenuScreen {
scrollPane.setSize(0.65f * WizardGame.WIDTH, 400 + 0.1f * WizardGame.HEIGHT + 80);
stage.addActor(scrollPane);
stage.addCaptureListener(new KeyboardFocusManager(scrollPane, previousPageButton, buttonOK, nextPageButton));
stage.addCaptureListener(new KeyboardFocusManager(scrollPane, previousPageButton, buttonBack, nextPageButton));
showFirstPage();
}
@ -166,9 +166,8 @@ public class InstructionScreen extends MenuScreen {
reset();
startSection("menu.instruction.variant.title");
addParagraph("menu.instruction.variant.intro");
Label variantsIntro = new Label(messages.get("menu.instruction.variant.intro"), skin);
content.addActor(variantsIntro);
Table table = new Table(skin).padTop(10);
table.defaults().space(10.0f).left().top();
table.columnDefaults(1).grow();

View File

@ -70,6 +70,6 @@ public class CardUtil {
);
public Card.Suit getDefaultTrumpSuit(Card card) {
return DEFAULT_SUITES.get(card);
return card == null ? Card.Suit.NONE : DEFAULT_SUITES.get(card);
}
}

View File

@ -1,26 +0,0 @@
package eu.jonahbauer.wizard.common.messages.server;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import java.util.UUID;
@Getter
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = true)
public final class KickVotedMessage extends ServerMessage {
/**
* UUID of the voting player
*/
private final @NonNull UUID voter;
/**
* UUID of player who is supposed to be kicked
*/
private final @NonNull UUID player;
/**
* Time until the vote ends in {@link System#currentTimeMillis() UNIX time}
*/
private final long timeout;
}

View File

@ -1,18 +0,0 @@
package eu.jonahbauer.wizard.common.messages.server;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import java.util.UUID;
@Getter
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = true)
public final class KickedMessage extends ServerMessage {
/**
* UUID of player who was kicked
*/
private final @NonNull UUID player;
}

View File

@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;
@EqualsAndHashCode
public abstract sealed class ServerMessage permits AckMessage, GameMessage, KickVotedMessage, KickedMessage, NackMessage, PlayerLeftMessage, PlayerModifiedMessage, SessionJoinedMessage, SessionListMessage, SessionModifiedMessage, SessionRemovedMessage, StartingGameMessage {
public abstract sealed class ServerMessage permits AckMessage, GameMessage, NackMessage, PlayerLeftMessage, PlayerModifiedMessage, SessionJoinedMessage, SessionListMessage, SessionModifiedMessage, SessionRemovedMessage, StartingGameMessage {
private static final ObjectMapper MAPPER = SerializationUtil.newObjectMapper(ServerMessage.class, ObserverMessage.class);
public static ServerMessage parse(String json) throws ParseException {

View File

@ -1,26 +1,17 @@
package eu.jonahbauer.wizard.core.machine.states.round;
import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage;
import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.machine.states.GameData;
import eu.jonahbauer.wizard.core.machine.Game;
import eu.jonahbauer.wizard.common.messages.observer.HandMessage;
import eu.jonahbauer.wizard.common.messages.observer.TrumpMessage;
import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage;
import eu.jonahbauer.wizard.common.messages.player.PickTrumpMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import eu.jonahbauer.wizard.core.machine.GameState;
import eu.jonahbauer.wizard.core.model.card.GameCards;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*;
import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.PICK_TRUMP;
public final class DeterminingTrump extends RoundState {
private transient UUID player;
private transient boolean werewolf;
public DeterminingTrump(GameData data) {
super(data.require(TRUMP_CARD).requireEach(PLAYERS, HANDS));
@ -35,74 +26,31 @@ public final class DeterminingTrump extends RoundState {
var player = entry.getKey();
var hand = entry.getValue();
if (hand.contains(Card.WEREWOLF)) {
this.player = player;
this.werewolf = true;
game.notify(new TrumpMessage(trumpCard, null));
game.notify(new TrumpMessage(Card.WEREWOLF, null));
game.notify(new UserInputMessage(this.player, PICK_TRUMP, getTimeout(game, true)));
return timeout(game);
var data = getData().with(CURRENT_PLAYER, player);
return sync(data, DeterminingTrumpUserInput::new);
}
}
// default trump handling
Card.Suit trumpSuit = trumpCard != null ? GameCards.get(trumpCard).getTrumpSuit() : Card.Suit.NONE;
if (trumpSuit == null) {
this.player = getDealer();
var player = getDealer();
game.notify(new TrumpMessage(trumpCard, null));
game.notify(new UserInputMessage(this.player, PICK_TRUMP, getTimeout(game, true)));
return timeout(game);
var data = getData().with(CURRENT_PLAYER, player);
return sync(data, DeterminingTrumpUserInput::new);
} else {
return transition(game, trumpSuit);
}
}
var data = getData().with(
TRUMP_SUIT, trumpSuit,
CURRENT_PLAYER, getNextPlayer(getDealer())
);
@Override
public Optional<GameState> onTimeout(Game game) {
game.notify(new TimeoutMessage());
Card.Suit[] suits;
if (werewolf) {
suits = new Card.Suit[]{Card.Suit.BLUE, Card.Suit.GREEN, Card.Suit.RED, Card.Suit.YELLOW, Card.Suit.NONE};
} else {
suits = new Card.Suit[]{Card.Suit.BLUE, Card.Suit.GREEN, Card.Suit.RED, Card.Suit.YELLOW};
}
return transition(game, suits[game.getRandom().nextInt(suits.length)]);
}
@Override
public Optional<GameState> onMessage(Game game, UUID player, PlayerMessage message) {
if (this.player.equals(player) && message instanceof PickTrumpMessage trumpMessage) {
checkTrumpSuit(trumpMessage.getTrumpSuit());
return transition(game, trumpMessage.getTrumpSuit());
} else {
return super.onMessage(game, player, message);
}
}
private void checkTrumpSuit(Card.Suit suit) {
if (!werewolf && suit == Card.Suit.NONE) {
throw new IllegalArgumentException("Trump suit must not be " + Card.Suit.NONE + ".");
} else if (suit == null) {
throw new IllegalArgumentException("Trump suit must not be null.");
}
}
private Optional<GameState> transition(Game game, @NotNull Card.Suit trumpSuit) {
GameData data = getData().with(
TRUMP_SUIT, trumpSuit,
CURRENT_PLAYER, getNextPlayer(getDealer())
);
if (werewolf) {
var mutableHands = new HashMap<>(get(HANDS));
var mutableHand = new ArrayList<>(mutableHands.get(player));
mutableHand.set(mutableHand.indexOf(Card.WEREWOLF), get(TRUMP_CARD));
mutableHands.put(player, List.copyOf(mutableHand));
data = data.with(HANDS, Map.copyOf(mutableHands));
game.notify(new TrumpMessage(Card.WEREWOLF, trumpSuit));
game.notify(player, new HandMessage(player, mutableHands.get(player)));
} else {
game.notify(new TrumpMessage(get(TRUMP_CARD), trumpSuit));
return sync(data, Predicting::new);
}
return sync(data, Predicting::new);
}
}

View File

@ -0,0 +1,89 @@
package eu.jonahbauer.wizard.core.machine.states.round;
import eu.jonahbauer.wizard.common.messages.observer.HandMessage;
import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage;
import eu.jonahbauer.wizard.common.messages.observer.TrumpMessage;
import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage;
import eu.jonahbauer.wizard.common.messages.player.PickTrumpMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.machine.Game;
import eu.jonahbauer.wizard.core.machine.GameState;
import eu.jonahbauer.wizard.core.machine.states.GameData;
import eu.jonahbauer.wizard.core.machine.states.TransientState;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.PICK_TRUMP;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*;
import static eu.jonahbauer.wizard.core.machine.states.GameData.TRUMP_CARD;
public final class DeterminingTrumpUserInput extends RoundState implements TransientState {
private final transient UUID player;
private final transient boolean werewolf;
public DeterminingTrumpUserInput(GameData data) {
super(data.require(TRUMP_CARD).requireEach(PLAYERS, HANDS).require(CURRENT_PLAYER));
this.player = get(CURRENT_PLAYER);
this.werewolf = get(HANDS).get(this.player).contains(Card.WEREWOLF);
}
@Override
public Optional<GameState> onEnter(Game game) {
game.notify(new UserInputMessage(this.player, PICK_TRUMP, getTimeout(game, true)));
return timeout(game);
}
@Override
public Optional<GameState> onTimeout(Game game) {
game.notify(new TimeoutMessage());
Card.Suit[] suits;
if (werewolf) {
suits = new Card.Suit[] {Card.Suit.BLUE, Card.Suit.GREEN, Card.Suit.RED, Card.Suit.YELLOW, Card.Suit.NONE};
} else {
suits = new Card.Suit[] {Card.Suit.BLUE, Card.Suit.GREEN, Card.Suit.RED, Card.Suit.YELLOW};
}
return transition(game, suits[game.getRandom().nextInt(suits.length)]);
}
@Override
public Optional<GameState> onMessage(Game game, UUID player, PlayerMessage message) {
if (this.player.equals(player) && message instanceof PickTrumpMessage trumpMessage) {
checkTrumpSuit(trumpMessage.getTrumpSuit());
return transition(game, trumpMessage.getTrumpSuit());
} else {
return super.onMessage(game, player, message);
}
}
private void checkTrumpSuit(Card.Suit suit) {
if (!werewolf && suit == Card.Suit.NONE) {
throw new IllegalArgumentException("Trump suit must not be " + Card.Suit.NONE + ".");
} else if (suit == null) {
throw new IllegalArgumentException("Trump suit must not be null.");
}
}
private Optional<GameState> transition(Game game, @NotNull Card.Suit trumpSuit) {
GameData data = getData().with(
TRUMP_SUIT, trumpSuit,
CURRENT_PLAYER, getNextPlayer(getDealer())
);
if (werewolf) {
var mutableHands = new HashMap<>(get(HANDS));
var mutableHand = new ArrayList<>(mutableHands.get(player));
mutableHand.set(mutableHand.indexOf(Card.WEREWOLF), get(TRUMP_CARD));
mutableHands.put(player, List.copyOf(mutableHand));
data = data.with(HANDS, Map.copyOf(mutableHands));
game.notify(new TrumpMessage(Card.WEREWOLF, trumpSuit));
game.notify(player, new HandMessage(player, mutableHands.get(player)));
} else {
game.notify(new TrumpMessage(get(TRUMP_CARD), trumpSuit));
}
return sync(data, Predicting::new);
}
}

View File

@ -38,7 +38,7 @@ public class DeterminingTrumpTest {
@SuppressWarnings("SameParameterValue")
private Game performTest(GameConfiguration configuration, int round, Map<UUID, List<Card>> hands, Card trumpCard, MessageQueue queue) {
Game game = spy(new Game(configuration, queue));
doFinish().when(game).transition(any(SyncState.class));
doFinish().when(game).transition(argThat(argument -> argument instanceof SyncState && argument.getData().has(TRUMP_SUIT)));
queue.setGame(game);
var playerList = List.of(players);
@ -92,7 +92,8 @@ public class DeterminingTrumpTest {
);
// play cards in given order
MessageQueue queue = new MessageQueue();
MessageQueue queue = new MessageQueue()
.sync(players);
Game game = performTest(Configurations.ANNIVERSARY_2021, 0, hands, Card.GREEN_JESTER, queue);
@ -117,6 +118,7 @@ public class DeterminingTrumpTest {
// play cards in given order
MessageQueue queue = new MessageQueue()
.sync(players)
.addPickTrump(players[0], Card.Suit.GREEN);
Game game = performTest(Configurations.ANNIVERSARY_2021, 0, hands, Card.BLUE_WIZARD, queue);
@ -144,6 +146,7 @@ public class DeterminingTrumpTest {
// play cards in given order
MessageQueue queue = new MessageQueue()
.sync(players)
.addPickTrump(players[3], Card.Suit.YELLOW);
Game game = performTest(Configurations.ANNIVERSARY_2021, 0, hands, Card.GREEN_1, queue);

View File

@ -148,10 +148,11 @@ public class RoundTest {
@Test
public void run_Anniversary() throws ExecutionException, InterruptedException {
MessageQueue queue = new MessageQueue()
.sync(players)
.sync(players)
.sync(players) // starting_round
.sync(players) // dealing
.sync(players) // determining_trump
.addPickTrump(players[2], Card.Suit.YELLOW)
.sync(players)
.sync(players) // determining_trump
.addPrediction(players[3], 2)
.addPrediction(players[0], 2)
.addPrediction(players[1], 2)