modularized common and core

dev
Jonah Bauer 3 years ago
parent 8b1d001ac0
commit bd7588c0d8

@ -2,8 +2,8 @@ package eu.jonahbauer.wizard.client.cli.commands;
import eu.jonahbauer.wizard.client.cli.Client; import eu.jonahbauer.wizard.client.cli.Client;
import eu.jonahbauer.wizard.client.cli.state.Game; import eu.jonahbauer.wizard.client.cli.state.Game;
import eu.jonahbauer.wizard.client.cli.util.Pair;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.common.util.Pair;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;

@ -2,7 +2,6 @@ package eu.jonahbauer.wizard.client.cli.state;
import eu.jonahbauer.wizard.client.cli.Client; import eu.jonahbauer.wizard.client.cli.Client;
import eu.jonahbauer.wizard.client.cli.commands.GameCommand; import eu.jonahbauer.wizard.client.cli.commands.GameCommand;
import eu.jonahbauer.wizard.client.cli.util.Pair;
import eu.jonahbauer.wizard.common.messages.client.InteractionMessage; import eu.jonahbauer.wizard.common.messages.client.InteractionMessage;
import eu.jonahbauer.wizard.common.messages.data.PlayerData; import eu.jonahbauer.wizard.common.messages.data.PlayerData;
import eu.jonahbauer.wizard.common.messages.observer.*; import eu.jonahbauer.wizard.common.messages.observer.*;
@ -12,6 +11,7 @@ import eu.jonahbauer.wizard.common.messages.server.GameMessage;
import eu.jonahbauer.wizard.common.messages.server.NackMessage; import eu.jonahbauer.wizard.common.messages.server.NackMessage;
import eu.jonahbauer.wizard.common.messages.server.ServerMessage; import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.common.util.Pair;
import lombok.Getter; import lombok.Getter;
import java.time.Instant; import java.time.Instant;

@ -1,24 +0,0 @@
package eu.jonahbauer.wizard.client.cli.util;
import java.util.Map;
public record Pair<F,S>(F first, S second) implements Map.Entry<F, S> {
public static <F,S> Pair<F,S> of(F first, S second) {
return new Pair<>(first, second);
}
@Override
public F getKey() {
return first();
}
@Override
public S getValue() {
return second();
}
@Override
public S setValue(S value) {
throw new UnsupportedOperationException();
}
}

@ -1,6 +1,5 @@
package eu.jonahbauer.wizard.client.cli.util; package eu.jonahbauer.wizard.client.cli.util;
import eu.jonahbauer.wizard.client.cli.Client; import eu.jonahbauer.wizard.client.cli.Client;
import eu.jonahbauer.wizard.client.cli.state.ClientState; import eu.jonahbauer.wizard.client.cli.state.ClientState;
import picocli.CommandLine; import picocli.CommandLine;

@ -3,7 +3,7 @@ package eu.jonahbauer.wizard.common.messages.client;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import eu.jonahbauer.wizard.common.messages.ParseException; import eu.jonahbauer.wizard.common.messages.ParseException;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage; import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import eu.jonahbauer.wizard.common.util.SerializationUtil; import eu.jonahbauer.wizard.common.messages.util.SerializationUtil;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.SneakyThrows; import lombok.SneakyThrows;

@ -2,7 +2,7 @@ package eu.jonahbauer.wizard.common.messages.observer;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import eu.jonahbauer.wizard.common.messages.ParseException; import eu.jonahbauer.wizard.common.messages.ParseException;
import eu.jonahbauer.wizard.common.util.SerializationUtil; import eu.jonahbauer.wizard.common.messages.util.SerializationUtil;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.SneakyThrows; import lombok.SneakyThrows;

@ -2,7 +2,7 @@ package eu.jonahbauer.wizard.common.messages.player;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import eu.jonahbauer.wizard.common.messages.ParseException; import eu.jonahbauer.wizard.common.messages.ParseException;
import eu.jonahbauer.wizard.common.util.SerializationUtil; import eu.jonahbauer.wizard.common.messages.util.SerializationUtil;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.SneakyThrows; import lombok.SneakyThrows;

@ -3,7 +3,7 @@ package eu.jonahbauer.wizard.common.messages.server;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import eu.jonahbauer.wizard.common.messages.ParseException; import eu.jonahbauer.wizard.common.messages.ParseException;
import eu.jonahbauer.wizard.common.messages.observer.ObserverMessage; import eu.jonahbauer.wizard.common.messages.observer.ObserverMessage;
import eu.jonahbauer.wizard.common.util.SerializationUtil; import eu.jonahbauer.wizard.common.messages.util.SerializationUtil;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.SneakyThrows; import lombok.SneakyThrows;

@ -1,4 +1,4 @@
package eu.jonahbauer.wizard.common.util; package eu.jonahbauer.wizard.common.messages.util;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
@ -10,10 +10,10 @@ import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import eu.jonahbauer.wizard.common.messages.ParseException; import eu.jonahbauer.wizard.common.messages.ParseException;
import eu.jonahbauer.wizard.common.util.StringUtil;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.Locale;
@UtilityClass @UtilityClass
public class SerializationUtil { public class SerializationUtil {
@ -61,7 +61,7 @@ public class SerializationUtil {
if (Modifier.isFinal(modifiers) || subclass.isSealed() && !Modifier.isAbstract(modifiers)) { if (Modifier.isFinal(modifiers) || subclass.isSealed() && !Modifier.isAbstract(modifiers)) {
var name = subclass.getSimpleName(); var name = subclass.getSimpleName();
if (name.endsWith(suffix)) name = name.substring(0, name.length() - suffix.length()); if (name.endsWith(suffix)) name = name.substring(0, name.length() - suffix.length());
name = name.replaceAll("([a-z])([A-Z]+)", "$1_$2").toLowerCase(Locale.ROOT); name = StringUtil.toSnakeCase(name);
objectMapper.registerSubtypes(new NamedType(subclass, name)); objectMapper.registerSubtypes(new NamedType(subclass, name));
} }

@ -1,4 +1,4 @@
package eu.jonahbauer.wizard.core.util; package eu.jonahbauer.wizard.common.util;
import java.util.Map; import java.util.Map;

@ -1,11 +1,11 @@
package eu.jonahbauer.wizard.core.util; package eu.jonahbauer.wizard.common.util;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import java.util.Locale; import java.util.Locale;
@UtilityClass @UtilityClass
public class Util { public class StringUtil {
public static String toSnakeCase(String str) { public static String toSnakeCase(String str) {
return str.replaceAll("([a-z])([A-Z]+)", "$1_$2").toLowerCase(Locale.ROOT); return str.replaceAll("([a-z])([A-Z]+)", "$1_$2").toLowerCase(Locale.ROOT);
} }

@ -0,0 +1,23 @@
module eu.jonahbauer.wizard.common {
exports eu.jonahbauer.wizard.common.machine;
exports eu.jonahbauer.wizard.common.messages;
exports eu.jonahbauer.wizard.common.messages.client;
exports eu.jonahbauer.wizard.common.messages.data;
exports eu.jonahbauer.wizard.common.messages.observer;
exports eu.jonahbauer.wizard.common.messages.player;
exports eu.jonahbauer.wizard.common.messages.server;
exports eu.jonahbauer.wizard.common.model;
exports eu.jonahbauer.wizard.common.util;
opens eu.jonahbauer.wizard.common.messages.client to com.fasterxml.jackson.databind;
opens eu.jonahbauer.wizard.common.messages.data to com.fasterxml.jackson.databind;
opens eu.jonahbauer.wizard.common.messages.observer to com.fasterxml.jackson.databind;
opens eu.jonahbauer.wizard.common.messages.player to com.fasterxml.jackson.databind;
opens eu.jonahbauer.wizard.common.messages.server to com.fasterxml.jackson.databind;
requires com.fasterxml.jackson.databind;
requires com.fasterxml.jackson.module.paramnames;
requires static lombok;
requires static org.jetbrains.annotations;
}

@ -1,72 +0,0 @@
package eu.jonahbauer.wizard.core;
import eu.jonahbauer.wizard.common.messages.player.PickTrumpMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayCardMessage;
import eu.jonahbauer.wizard.common.messages.player.PredictMessage;
import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.machine.Game;
import eu.jonahbauer.wizard.core.messages.Observer;
import eu.jonahbauer.wizard.core.model.GameConfiguration;
import eu.jonahbauer.wizard.core.model.Configurations;
import java.util.List;
import java.util.Scanner;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CLI {
public static void main(String[] args) {
GameConfiguration config = Configurations.DEFAULT;
Observer observer = (player, msg) -> System.out.println(msg);
Game game = new Game(config, observer);
var players = List.of(
UUID.randomUUID(),
UUID.randomUUID(),
UUID.randomUUID(),
UUID.randomUUID()
);
game.start(players);
Scanner scanner = new Scanner(System.in);
Pattern pattern = Pattern.compile("(\\d) ([a-z]+) (.*)");
while (scanner.hasNextLine()) {
try {
Matcher matcher = pattern.matcher(scanner.nextLine());
if (!matcher.find()) {
System.err.println("Format is \"(\\d) ([a-z]+) (.*)\"");
continue;
}
String player = matcher.group(1);
String command = matcher.group(2);
String param = matcher.group(3);
int id = Integer.parseInt(player);
if (id > players.size()) {
System.err.println("ID must be between 0 and " + (players.size() - 1));
continue;
}
switch (command) {
case "predict" -> {
int prediction = Integer.parseInt(param);
game.onMessage(players.get(id), new PredictMessage(prediction));
}
case "play" -> {
Card card = Card.valueOf(param);
game.onMessage(players.get(id), new PlayCardMessage(card));
}
case "trump" -> {
Card.Suit suit = Card.Suit.valueOf(param);
game.onMessage(players.get(id), new PickTrumpMessage(suit));
}
default -> System.err.println("Unknown command: " + command);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
}

@ -1,18 +1,22 @@
package eu.jonahbauer.wizard.core.machine; package eu.jonahbauer.wizard.core;
import eu.jonahbauer.wizard.common.machine.TimeoutContext; import eu.jonahbauer.wizard.common.machine.TimeoutContext;
import eu.jonahbauer.wizard.common.messages.observer.ObserverMessage; import eu.jonahbauer.wizard.common.messages.observer.ObserverMessage;
import eu.jonahbauer.wizard.common.messages.observer.StateMessage; import eu.jonahbauer.wizard.common.messages.observer.StateMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage; import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import eu.jonahbauer.wizard.core.machine.states.TransientState; import eu.jonahbauer.wizard.common.model.Configuration;
import eu.jonahbauer.wizard.core.machine.states.game.Created; import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.core.machine.states.game.Error; import eu.jonahbauer.wizard.core.states.TransientState;
import eu.jonahbauer.wizard.core.messages.Observer; import eu.jonahbauer.wizard.core.states.game.Created;
import eu.jonahbauer.wizard.core.states.game.Error;
import eu.jonahbauer.wizard.core.model.Configurations;
import eu.jonahbauer.wizard.core.model.GameConfiguration; import eu.jonahbauer.wizard.core.model.GameConfiguration;
import eu.jonahbauer.wizard.core.util.Util; import eu.jonahbauer.wizard.common.util.StringUtil;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.Blocking; import org.jetbrains.annotations.Blocking;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.annotations.VisibleForTesting;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
@ -30,20 +34,25 @@ public final class Game extends TimeoutContext<GameState, Game> {
private final CompletableFuture<Void> future = new CompletableFuture<>(); private final CompletableFuture<Void> future = new CompletableFuture<>();
public Game(GameConfiguration config, Observer observer) { private Game(Random random, Configuration config, long timeout, long syncTimeout, Observer observer) {
super(new Created()); super(new Created());
this.random = new Random(); this.random = random;
this.config = config; this.config = Configurations.get(config).withTimeout(timeout).withSyncTimeout(syncTimeout);
this.observer = observer; this.observer = observer;
} }
public Game(long seed, GameConfiguration config, Observer observer) { public Game(Configuration config, long timeout, long syncTimeout, Observer observer) {
super(new Created()); this(new Random(), config, timeout, syncTimeout, observer);
this.random = new Random(seed); }
this.config = config;
this.observer = observer; @TestOnly
public Game(long seed, Configuration config, long timeout, long syncTimeout, Observer observer) {
this(new Random(seed), config, timeout, syncTimeout, observer);
} }
@TestOnly
@VisibleForTesting
@SuppressWarnings("ClassEscapesDefinedScope")
public void resume(GameState state) { public void resume(GameState state) {
transition(new Created(), state); transition(new Created(), state);
} }
@ -56,10 +65,17 @@ public final class Game extends TimeoutContext<GameState, Game> {
execute(s -> s.onMessage(this, player, message)); execute(s -> s.onMessage(this, player, message));
} }
public void onMessage(UUID player, PlayerMessage message, Runnable preHandleMessage) {
execute(s -> {
preHandleMessage.run();
return s.onMessage(this, player, message);
});
}
@Override @Override
protected void onTransition(GameState from, GameState to) { protected void onTransition(GameState from, GameState to) {
if (!(to instanceof TransientState)) { if (!(to instanceof TransientState)) {
notify(new StateMessage(to != null ? Util.toSnakeCase(to.getClass().getSimpleName()) : "null")); notify(new StateMessage(to != null ? StringUtil.toSnakeCase(to.getClass().getSimpleName()) : "null"));
} }
} }

@ -1,4 +1,4 @@
package eu.jonahbauer.wizard.core.messages; package eu.jonahbauer.wizard.core;
import eu.jonahbauer.wizard.common.messages.observer.ObserverMessage; import eu.jonahbauer.wizard.common.messages.observer.ObserverMessage;

@ -1,4 +0,0 @@
package eu.jonahbauer.wizard.core.machine.states;
public interface TransientState {
}

@ -1,22 +0,0 @@
package eu.jonahbauer.wizard.core.machine.states.game;
import eu.jonahbauer.wizard.core.machine.Game;
import eu.jonahbauer.wizard.core.machine.states.GameData;
import eu.jonahbauer.wizard.core.machine.GameState;
import eu.jonahbauer.wizard.core.machine.states.round.StartingRound;
import java.util.Optional;
import static eu.jonahbauer.wizard.core.machine.states.GameData.PLAYERS;
public final class Starting extends GameState {
public Starting(GameData data) {
super(data.require(PLAYERS));
}
@Override
public Optional<GameState> onEnter(Game game) {
return transition(new StartingRound(getData()));
}
}

@ -1,7 +1,7 @@
package eu.jonahbauer.wizard.core.model.card; package eu.jonahbauer.wizard.core.model.card;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.util.Pair; import eu.jonahbauer.wizard.common.util.Pair;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import java.util.Comparator; import java.util.Comparator;

@ -1,7 +1,7 @@
package eu.jonahbauer.wizard.core.model.card; package eu.jonahbauer.wizard.core.model.card;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.util.Pair; import eu.jonahbauer.wizard.common.util.Pair;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;

@ -1,7 +1,7 @@
package eu.jonahbauer.wizard.core.model.card; package eu.jonahbauer.wizard.core.model.card;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.util.Pair; import eu.jonahbauer.wizard.common.util.Pair;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;

@ -1,7 +1,7 @@
package eu.jonahbauer.wizard.core.model.card; package eu.jonahbauer.wizard.core.model.card;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.util.Pair; import eu.jonahbauer.wizard.common.util.Pair;
import lombok.Getter; import lombok.Getter;
import java.util.List; import java.util.List;

@ -1,7 +1,7 @@
package eu.jonahbauer.wizard.core.model.card; package eu.jonahbauer.wizard.core.model.card;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.util.Pair; import eu.jonahbauer.wizard.common.util.Pair;
import lombok.Getter; import lombok.Getter;
import java.util.List; import java.util.List;

@ -1,7 +1,7 @@
package eu.jonahbauer.wizard.core.model.card; package eu.jonahbauer.wizard.core.model.card;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.util.Pair; import eu.jonahbauer.wizard.common.util.Pair;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;

@ -1,7 +1,7 @@
package eu.jonahbauer.wizard.core.model.card; package eu.jonahbauer.wizard.core.model.card;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.util.Pair; import eu.jonahbauer.wizard.common.util.Pair;
import lombok.Getter; import lombok.Getter;
import java.util.List; import java.util.List;

@ -1,7 +1,7 @@
package eu.jonahbauer.wizard.core.machine.states; package eu.jonahbauer.wizard.core.states;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.util.Pair; import eu.jonahbauer.wizard.common.util.Pair;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;

@ -1,10 +1,9 @@
package eu.jonahbauer.wizard.core.machine; package eu.jonahbauer.wizard.core.states;
import eu.jonahbauer.wizard.common.machine.TimeoutState; import eu.jonahbauer.wizard.common.machine.TimeoutState;
import eu.jonahbauer.wizard.common.messages.player.ContinueMessage; import eu.jonahbauer.wizard.common.messages.player.ContinueMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage; import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.states.SyncState;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.Unmodifiable; import org.jetbrains.annotations.Unmodifiable;
@ -13,8 +12,8 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.function.Function; import java.util.function.Function;
import static eu.jonahbauer.wizard.core.machine.states.GameData.CURRENT_PLAYER; import static eu.jonahbauer.wizard.core.states.GameData.CURRENT_PLAYER;
import static eu.jonahbauer.wizard.core.machine.states.GameData.PLAYERS; import static eu.jonahbauer.wizard.core.states.GameData.PLAYERS;
@Unmodifiable @Unmodifiable
public abstract class GameState implements TimeoutState<GameState, Game> { public abstract class GameState implements TimeoutState<GameState, Game> {

@ -1,4 +1,4 @@
package eu.jonahbauer.wizard.core.machine.states; package eu.jonahbauer.wizard.core.states;
public class InvalidDataException extends RuntimeException { public class InvalidDataException extends RuntimeException {
public InvalidDataException(String message) { public InvalidDataException(String message) {

@ -1,11 +1,10 @@
package eu.jonahbauer.wizard.core.machine.states; package eu.jonahbauer.wizard.core.states;
import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage; import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage;
import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage; import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage;
import eu.jonahbauer.wizard.common.messages.player.ContinueMessage; import eu.jonahbauer.wizard.common.messages.player.ContinueMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage; import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.GameState;
import java.util.HashSet; import java.util.HashSet;
import java.util.Optional; import java.util.Optional;
@ -14,7 +13,7 @@ import java.util.UUID;
import java.util.function.Function; import java.util.function.Function;
import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.SYNC; import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.SYNC;
import static eu.jonahbauer.wizard.core.machine.states.GameData.PLAYERS; import static eu.jonahbauer.wizard.core.states.GameData.PLAYERS;
public final class SyncState extends GameState implements TransientState { public final class SyncState extends GameState implements TransientState {
private final transient Set<UUID> ready = new HashSet<>(); private final transient Set<UUID> ready = new HashSet<>();

@ -0,0 +1,4 @@
package eu.jonahbauer.wizard.core.states;
public interface TransientState {
}

@ -1,8 +1,8 @@
package eu.jonahbauer.wizard.core.machine.states.game; package eu.jonahbauer.wizard.core.states.game;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;

@ -1,7 +1,7 @@
package eu.jonahbauer.wizard.core.machine.states.game; package eu.jonahbauer.wizard.core.states.game;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import lombok.Getter; import lombok.Getter;
@Getter @Getter

@ -1,8 +1,8 @@
package eu.jonahbauer.wizard.core.machine.states.game; package eu.jonahbauer.wizard.core.states.game;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import java.util.Optional; import java.util.Optional;

@ -1,13 +1,13 @@
package eu.jonahbauer.wizard.core.machine.states.game; package eu.jonahbauer.wizard.core.states.game;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.common.messages.observer.ScoreMessage; import eu.jonahbauer.wizard.common.messages.observer.ScoreMessage;
import java.util.Optional; import java.util.Optional;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
public final class Finishing extends GameState { public final class Finishing extends GameState {

@ -0,0 +1,22 @@
package eu.jonahbauer.wizard.core.states.game;
import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.core.states.round.StartingRound;
import java.util.Optional;
import static eu.jonahbauer.wizard.core.states.GameData.PLAYERS;
public final class Starting extends GameState {
public Starting(GameData data) {
super(data.require(PLAYERS));
}
@Override
public Optional<GameState> onEnter(Game game) {
return transition(new StartingRound(getData()));
}
}

@ -1,14 +1,14 @@
package eu.jonahbauer.wizard.core.machine.states.round; package eu.jonahbauer.wizard.core.states.round;
import eu.jonahbauer.wizard.common.messages.observer.PredictionMessage; import eu.jonahbauer.wizard.common.messages.observer.PredictionMessage;
import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage; import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage;
import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage; import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage; import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import eu.jonahbauer.wizard.common.messages.player.PredictMessage; import eu.jonahbauer.wizard.common.messages.player.PredictMessage;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.core.machine.states.InvalidDataException; import eu.jonahbauer.wizard.core.states.InvalidDataException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -16,7 +16,7 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.CHANGE_PREDICTION; import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.CHANGE_PREDICTION;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
public final class ChangingPrediction extends RoundState { public final class ChangingPrediction extends RoundState {
private transient final int oldPrediction; private transient final int oldPrediction;

@ -1,15 +1,15 @@
package eu.jonahbauer.wizard.core.machine.states.round; package eu.jonahbauer.wizard.core.states.round;
import eu.jonahbauer.wizard.common.messages.observer.HandMessage; import eu.jonahbauer.wizard.common.messages.observer.HandMessage;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.core.model.deck.Deck; import eu.jonahbauer.wizard.core.model.deck.Deck;
import java.util.*; import java.util.*;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
public final class Dealing extends RoundState { public final class Dealing extends RoundState {

@ -1,15 +1,15 @@
package eu.jonahbauer.wizard.core.machine.states.round; package eu.jonahbauer.wizard.core.states.round;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.common.messages.observer.TrumpMessage; import eu.jonahbauer.wizard.common.messages.observer.TrumpMessage;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.core.model.card.GameCards; import eu.jonahbauer.wizard.core.model.card.GameCards;
import java.util.*; import java.util.*;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
public final class DeterminingTrump extends RoundState { public final class DeterminingTrump extends RoundState {

@ -1,4 +1,4 @@
package eu.jonahbauer.wizard.core.machine.states.round; package eu.jonahbauer.wizard.core.states.round;
import eu.jonahbauer.wizard.common.messages.observer.HandMessage; import eu.jonahbauer.wizard.common.messages.observer.HandMessage;
import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage; import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage;
@ -7,17 +7,17 @@ import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage;
import eu.jonahbauer.wizard.common.messages.player.PickTrumpMessage; import eu.jonahbauer.wizard.common.messages.player.PickTrumpMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage; import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.states.TransientState; import eu.jonahbauer.wizard.core.states.TransientState;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.*; import java.util.*;
import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.PICK_TRUMP; 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.states.GameData.*;
import static eu.jonahbauer.wizard.core.machine.states.GameData.TRUMP_CARD; import static eu.jonahbauer.wizard.core.states.GameData.TRUMP_CARD;
public final class DeterminingTrumpUserInput extends RoundState implements TransientState { public final class DeterminingTrumpUserInput extends RoundState implements TransientState {
private final transient UUID player; private final transient UUID player;

@ -1,9 +1,9 @@
package eu.jonahbauer.wizard.core.machine.states.round; package eu.jonahbauer.wizard.core.states.round;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.core.machine.states.game.Finishing; import eu.jonahbauer.wizard.core.states.game.Finishing;
import eu.jonahbauer.wizard.common.messages.observer.ScoreMessage; import eu.jonahbauer.wizard.common.messages.observer.ScoreMessage;
import java.util.HashMap; import java.util.HashMap;
@ -11,7 +11,7 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
public final class FinishingRound extends RoundState { public final class FinishingRound extends RoundState {

@ -1,10 +1,10 @@
package eu.jonahbauer.wizard.core.machine.states.round; package eu.jonahbauer.wizard.core.states.round;
import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage; import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.core.machine.states.trick.StartingTrick; import eu.jonahbauer.wizard.core.states.trick.StartingTrick;
import eu.jonahbauer.wizard.common.messages.observer.PredictionMessage; import eu.jonahbauer.wizard.common.messages.observer.PredictionMessage;
import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage; import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage; import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
@ -16,7 +16,7 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.MAKE_PREDICTION; import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.MAKE_PREDICTION;
@Getter @Getter

@ -1,11 +1,11 @@
package eu.jonahbauer.wizard.core.machine.states.round; package eu.jonahbauer.wizard.core.states.round;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import java.util.UUID; import java.util.UUID;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
public abstract class RoundState extends GameState { public abstract class RoundState extends GameState {
public static GameData requirements(GameData data) { public static GameData requirements(GameData data) {

@ -1,8 +1,8 @@
package eu.jonahbauer.wizard.core.machine.states.round; package eu.jonahbauer.wizard.core.states.round;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import java.util.Optional; import java.util.Optional;

@ -1,19 +1,19 @@
package eu.jonahbauer.wizard.core.machine.states.trick; package eu.jonahbauer.wizard.core.states.trick;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.core.machine.states.InvalidDataException; import eu.jonahbauer.wizard.core.states.InvalidDataException;
import eu.jonahbauer.wizard.core.machine.states.round.ChangingPrediction; import eu.jonahbauer.wizard.core.states.round.ChangingPrediction;
import eu.jonahbauer.wizard.core.machine.states.round.FinishingRound; import eu.jonahbauer.wizard.core.states.round.FinishingRound;
import eu.jonahbauer.wizard.common.messages.observer.TrickMessage; import eu.jonahbauer.wizard.common.messages.observer.TrickMessage;
import eu.jonahbauer.wizard.core.model.card.*; import eu.jonahbauer.wizard.core.model.card.*;
import eu.jonahbauer.wizard.core.util.Pair; import eu.jonahbauer.wizard.common.util.Pair;
import java.util.*; import java.util.*;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
public final class FinishingTrick extends TrickState { public final class FinishingTrick extends TrickState {

@ -1,4 +1,4 @@
package eu.jonahbauer.wizard.core.machine.states.trick; package eu.jonahbauer.wizard.core.states.trick;
import eu.jonahbauer.wizard.common.messages.observer.HandMessage; import eu.jonahbauer.wizard.common.messages.observer.HandMessage;
import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage; import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage;
@ -6,15 +6,15 @@ import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage;
import eu.jonahbauer.wizard.common.messages.player.JuggleMessage; import eu.jonahbauer.wizard.common.messages.player.JuggleMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage; import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.*; import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.*;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
public final class Juggling extends TrickState { public final class Juggling extends TrickState {
private final transient Map<UUID, Card> juggledCards = new ConcurrentHashMap<>(); private final transient Map<UUID, Card> juggledCards = new ConcurrentHashMap<>();

@ -1,22 +1,22 @@
package eu.jonahbauer.wizard.core.machine.states.trick; package eu.jonahbauer.wizard.core.states.trick;
import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage; import eu.jonahbauer.wizard.common.messages.observer.TimeoutMessage;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.core.machine.states.InvalidDataException; import eu.jonahbauer.wizard.core.states.InvalidDataException;
import eu.jonahbauer.wizard.common.messages.observer.CardMessage; import eu.jonahbauer.wizard.common.messages.observer.CardMessage;
import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage; import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayCardMessage; import eu.jonahbauer.wizard.common.messages.player.PlayCardMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage; import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import eu.jonahbauer.wizard.core.model.card.GameCards; import eu.jonahbauer.wizard.core.model.card.GameCards;
import eu.jonahbauer.wizard.core.util.Pair; import eu.jonahbauer.wizard.common.util.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.*; import java.util.*;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.PLAY_CARD; import static eu.jonahbauer.wizard.common.messages.observer.UserInputMessage.Action.PLAY_CARD;
public final class PlayingCard extends TrickState { public final class PlayingCard extends TrickState {

@ -1,8 +1,8 @@
package eu.jonahbauer.wizard.core.machine.states.trick; package eu.jonahbauer.wizard.core.states.trick;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.GameState; import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import java.util.Optional; import java.util.Optional;

@ -1,9 +1,9 @@
package eu.jonahbauer.wizard.core.machine.states.trick; package eu.jonahbauer.wizard.core.states.trick;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.states.round.RoundState; import eu.jonahbauer.wizard.core.states.round.RoundState;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
public abstract class TrickState extends RoundState { public abstract class TrickState extends RoundState {
public static GameData requirements(GameData data) { public static GameData requirements(GameData data) {

@ -0,0 +1,8 @@
module eu.jonahbauer.wizard.core {
exports eu.jonahbauer.wizard.core;
requires eu.jonahbauer.wizard.common;
requires static lombok;
requires static org.jetbrains.annotations;
}

@ -1,6 +1,7 @@
package eu.jonahbauer.wizard.core.machine; package eu.jonahbauer.wizard.core;
import eu.jonahbauer.wizard.core.model.Configurations; import eu.jonahbauer.wizard.common.model.Configuration;
import eu.jonahbauer.wizard.core.Game;
import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.RepetitionInfo; import org.junit.jupiter.api.RepetitionInfo;
@ -13,7 +14,7 @@ public class GameTest {
public void runDefault(RepetitionInfo repetitionInfo) throws InterruptedException, ExecutionException { public void runDefault(RepetitionInfo repetitionInfo) throws InterruptedException, ExecutionException {
Game game = new Game( Game game = new Game(
repetitionInfo.getCurrentRepetition(), repetitionInfo.getCurrentRepetition(),
Configurations.DEFAULT.withTimeout(0).withSyncTimeout(0), Configuration.DEFAULT, 0, 0,
(player, msg) -> System.out.println(msg) (player, msg) -> System.out.println(msg)
); );
var players = List.of( var players = List.of(
@ -31,7 +32,7 @@ public class GameTest {
public void runAnniversary2016(RepetitionInfo repetitionInfo) throws InterruptedException, ExecutionException { public void runAnniversary2016(RepetitionInfo repetitionInfo) throws InterruptedException, ExecutionException {
Game game = new Game( Game game = new Game(
repetitionInfo.getCurrentRepetition(), repetitionInfo.getCurrentRepetition(),
Configurations.ANNIVERSARY_2016.withTimeout(0).withSyncTimeout(0), Configuration.ANNIVERSARY_2016, 0, 0,
(player, msg) -> System.out.println(msg) (player, msg) -> System.out.println(msg)
); );
var players = List.of( var players = List.of(
@ -49,7 +50,7 @@ public class GameTest {
public void runAnniversary2021(RepetitionInfo repetitionInfo) throws InterruptedException, ExecutionException { public void runAnniversary2021(RepetitionInfo repetitionInfo) throws InterruptedException, ExecutionException {
Game game = new Game( Game game = new Game(
repetitionInfo.getCurrentRepetition(), repetitionInfo.getCurrentRepetition(),
Configurations.ANNIVERSARY_2021.withTimeout(0).withSyncTimeout(0), Configuration.ANNIVERSARY_2021, 0, 0,
(player, msg) -> System.out.println(msg) (player, msg) -> System.out.println(msg)
); );
var players = List.of( var players = List.of(

@ -1,6 +1,6 @@
package eu.jonahbauer.wizard.core.machine; package eu.jonahbauer.wizard.core;
import eu.jonahbauer.wizard.core.machine.states.game.Finished; import eu.jonahbauer.wizard.core.states.game.Finished;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.stubbing.Answer; import org.mockito.stubbing.Answer;

@ -1,11 +1,11 @@
package eu.jonahbauer.wizard.core.machine; package eu.jonahbauer.wizard.core;
import eu.jonahbauer.wizard.common.messages.observer.ObserverMessage; import eu.jonahbauer.wizard.common.messages.observer.ObserverMessage;
import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage; import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage;
import eu.jonahbauer.wizard.common.messages.player.*; import eu.jonahbauer.wizard.common.messages.player.*;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.messages.Observer; import eu.jonahbauer.wizard.core.states.GameState;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.Setter; import lombok.Setter;

@ -1,7 +1,7 @@
package eu.jonahbauer.wizard.core.model.card; package eu.jonahbauer.wizard.core.model.card;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.util.Pair; import eu.jonahbauer.wizard.common.util.Pair;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.List; import java.util.List;

@ -1,6 +1,5 @@
package eu.jonahbauer.wizard.core.machine.states; package eu.jonahbauer.wizard.core.states;
import eu.jonahbauer.wizard.core.machine.GameState;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.HashSet; import java.util.HashSet;

@ -1,17 +1,16 @@
package eu.jonahbauer.wizard.core.machine.states.round; package eu.jonahbauer.wizard.core.states.round;
import eu.jonahbauer.wizard.common.messages.observer.HandMessage; import eu.jonahbauer.wizard.common.messages.observer.HandMessage;
import eu.jonahbauer.wizard.common.messages.observer.StateMessage; import eu.jonahbauer.wizard.common.messages.observer.StateMessage;
import eu.jonahbauer.wizard.common.messages.observer.TrumpMessage; import eu.jonahbauer.wizard.common.messages.observer.TrumpMessage;
import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage; import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.common.model.Configuration;
import eu.jonahbauer.wizard.core.machine.MessageQueue; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.MessageQueue;
import eu.jonahbauer.wizard.core.machine.states.SyncState; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.states.game.Finished; import eu.jonahbauer.wizard.core.states.SyncState;
import eu.jonahbauer.wizard.core.model.GameConfiguration; import eu.jonahbauer.wizard.core.states.game.Finished;
import eu.jonahbauer.wizard.core.model.Configurations;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.InOrder; import org.mockito.InOrder;
@ -20,9 +19,9 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import static eu.jonahbauer.wizard.core.machine.GameTestUtils.doFinish; import static eu.jonahbauer.wizard.core.GameTestUtils.doFinish;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
import static eu.jonahbauer.wizard.core.machine.states.GameData.TypedValue.entry; import static eu.jonahbauer.wizard.core.states.GameData.TypedValue.entry;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
@ -36,8 +35,8 @@ public class DeterminingTrumpTest {
@SneakyThrows @SneakyThrows
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
private Game performTest(GameConfiguration configuration, int round, Map<UUID, List<Card>> hands, Card trumpCard, MessageQueue queue) { private Game performTest(Configuration configuration, int round, Map<UUID, List<Card>> hands, Card trumpCard, MessageQueue queue) {
Game game = spy(new Game(configuration, queue)); Game game = spy(new Game(configuration, 10 * 60 * 1000, 10 * 60 * 1000, queue));
doFinish().when(game).transition(argThat(argument -> argument instanceof SyncState && argument.getData().has(TRUMP_SUIT))); doFinish().when(game).transition(argThat(argument -> argument instanceof SyncState && argument.getData().has(TRUMP_SUIT)));
queue.setGame(game); queue.setGame(game);
@ -70,7 +69,7 @@ public class DeterminingTrumpTest {
// play cards in given order // play cards in given order
MessageQueue queue = new MessageQueue(); MessageQueue queue = new MessageQueue();
Game game = performTest(Configurations.ANNIVERSARY_2021, 0, hands, Card.YELLOW_1, queue); Game game = performTest(Configuration.ANNIVERSARY_2021, 0, hands, Card.YELLOW_1, queue);
// validate messages // validate messages
InOrder order = inOrder(game); InOrder order = inOrder(game);
@ -95,7 +94,7 @@ public class DeterminingTrumpTest {
MessageQueue queue = new MessageQueue() MessageQueue queue = new MessageQueue()
.sync(players); .sync(players);
Game game = performTest(Configurations.ANNIVERSARY_2021, 0, hands, Card.GREEN_JESTER, queue); Game game = performTest(Configuration.ANNIVERSARY_2021, 0, hands, Card.GREEN_JESTER, queue);
// validate messages // validate messages
InOrder order = inOrder(game); InOrder order = inOrder(game);
@ -121,7 +120,7 @@ public class DeterminingTrumpTest {
.sync(players) .sync(players)
.addPickTrump(players[0], Card.Suit.GREEN); .addPickTrump(players[0], Card.Suit.GREEN);
Game game = performTest(Configurations.ANNIVERSARY_2021, 0, hands, Card.BLUE_WIZARD, queue); Game game = performTest(Configuration.ANNIVERSARY_2021, 0, hands, Card.BLUE_WIZARD, queue);
// validate messages // validate messages
InOrder order = inOrder(game); InOrder order = inOrder(game);
@ -149,7 +148,7 @@ public class DeterminingTrumpTest {
.sync(players) .sync(players)
.addPickTrump(players[3], Card.Suit.YELLOW); .addPickTrump(players[3], Card.Suit.YELLOW);
Game game = performTest(Configurations.ANNIVERSARY_2021, 0, hands, Card.GREEN_1, queue); Game game = performTest(Configuration.ANNIVERSARY_2021, 0, hands, Card.GREEN_1, queue);
// validate messages // validate messages
InOrder order = inOrder(game); InOrder order = inOrder(game);

@ -1,17 +1,16 @@
package eu.jonahbauer.wizard.core.machine.states.round; package eu.jonahbauer.wizard.core.states.round;
import eu.jonahbauer.wizard.common.messages.observer.PredictionMessage; import eu.jonahbauer.wizard.common.messages.observer.PredictionMessage;
import eu.jonahbauer.wizard.common.messages.observer.StateMessage; import eu.jonahbauer.wizard.common.messages.observer.StateMessage;
import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage; import eu.jonahbauer.wizard.common.messages.observer.UserInputMessage;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.common.model.Configuration;
import eu.jonahbauer.wizard.core.machine.GameTestUtils; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.MessageQueue; import eu.jonahbauer.wizard.core.GameTestUtils;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.MessageQueue;
import eu.jonahbauer.wizard.core.machine.states.game.Finished; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.machine.states.trick.StartingTrick; import eu.jonahbauer.wizard.core.states.game.Finished;
import eu.jonahbauer.wizard.core.model.GameConfiguration; import eu.jonahbauer.wizard.core.states.trick.StartingTrick;
import eu.jonahbauer.wizard.core.model.Configurations;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.InOrder; import org.mockito.InOrder;
@ -21,9 +20,9 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import static eu.jonahbauer.wizard.core.machine.GameTestUtils.doFinish; import static eu.jonahbauer.wizard.core.GameTestUtils.doFinish;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
import static eu.jonahbauer.wizard.core.machine.states.GameData.TypedValue.entry; import static eu.jonahbauer.wizard.core.states.GameData.TypedValue.entry;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
@ -37,7 +36,7 @@ public class PredictingTest {
@SneakyThrows @SneakyThrows
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
private Game performTest(GameConfiguration configuration, int round, MessageQueue queue) { private Game performTest(Configuration configuration, int round, MessageQueue queue) {
Map<UUID, List<Card>> hands = Map.of( Map<UUID, List<Card>> hands = Map.of(
players[0], Collections.nCopies(round + 1, Card.HIDDEN), players[0], Collections.nCopies(round + 1, Card.HIDDEN),
players[1], Collections.nCopies(round + 1, Card.HIDDEN), players[1], Collections.nCopies(round + 1, Card.HIDDEN),
@ -45,7 +44,7 @@ public class PredictingTest {
players[3], Collections.nCopies(round + 1, Card.HIDDEN) players[3], Collections.nCopies(round + 1, Card.HIDDEN)
); );
Game game = spy(new Game(configuration, queue)); Game game = spy(new Game(configuration, 10 * 60 * 1000, 10 * 60 * 1000, queue));
doFinish().when(game).transition(any(StartingTrick.class)); doFinish().when(game).transition(any(StartingTrick.class));
queue.setGame(game); queue.setGame(game);
@ -77,7 +76,7 @@ public class PredictingTest {
.addPrediction(players[2], 3) .addPrediction(players[2], 3)
.addPrediction(players[3], 0); .addPrediction(players[3], 0);
Game game = performTest(Configurations.ANNIVERSARY_2021, 3, queue); Game game = performTest(Configuration.ANNIVERSARY_2021, 3, queue);
// validate messages // validate messages
InOrder order = inOrder(game); InOrder order = inOrder(game);
@ -119,7 +118,7 @@ public class PredictingTest {
.addPrediction(players[3], 0) .addPrediction(players[3], 0)
.end(); .end();
Game game = performTest(Configurations.ANNIVERSARY_2021, 3, queue); Game game = performTest(Configuration.ANNIVERSARY_2021, 3, queue);
// validate messages // validate messages
InOrder order = inOrder(game); InOrder order = inOrder(game);
@ -153,7 +152,7 @@ public class PredictingTest {
.addPrediction(players[3], 0) .addPrediction(players[3], 0)
.end(); .end();
Game game = performTest(Configurations.ANNIVERSARY_2021_PM1, 3, queue); Game game = performTest(Configuration.ANNIVERSARY_2021_PM1, 3, queue);
// validate messages // validate messages
InOrder order = inOrder(game); InOrder order = inOrder(game);

@ -1,13 +1,12 @@
package eu.jonahbauer.wizard.core.machine.states.round; package eu.jonahbauer.wizard.core.states.round;
import eu.jonahbauer.wizard.common.messages.observer.*; import eu.jonahbauer.wizard.common.messages.observer.*;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.common.model.Configuration;
import eu.jonahbauer.wizard.core.machine.MessageQueue; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.MessageQueue;
import eu.jonahbauer.wizard.core.machine.states.game.Finished; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.model.Configurations; import eu.jonahbauer.wizard.core.states.game.Finished;
import eu.jonahbauer.wizard.core.model.GameConfiguration;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.InOrder; import org.mockito.InOrder;
@ -17,9 +16,9 @@ import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import static eu.jonahbauer.wizard.core.machine.GameTestUtils.finish; import static eu.jonahbauer.wizard.core.GameTestUtils.finish;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
import static eu.jonahbauer.wizard.core.machine.states.GameData.TypedValue.entry; import static eu.jonahbauer.wizard.core.states.GameData.TypedValue.entry;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
@ -32,8 +31,8 @@ public class RoundTest {
}; };
@SneakyThrows @SneakyThrows
private Game performTest(long seed, GameConfiguration configuration, int round, MessageQueue queue) { private Game performTest(long seed, Configuration configuration, int round, MessageQueue queue) {
Game game = spy(new Game(seed, configuration, queue)); Game game = spy(new Game(seed, configuration, 10 * 60 * 1000, 10 * 60 * 1000, queue));
doCallRealMethod().doAnswer(finish()).when(game).transition(any(StartingRound.class)); doCallRealMethod().doAnswer(finish()).when(game).transition(any(StartingRound.class));
queue.setGame(game); queue.setGame(game);
@ -106,7 +105,7 @@ public class RoundTest {
.addCard(players[2], Card.BLUE_6); .addCard(players[2], Card.BLUE_6);
int round = 6; int round = 6;
Game game = performTest(0L, Configurations.DEFAULT, round, queue); Game game = performTest(0L, Configuration.DEFAULT, round, queue);
game.await(); game.await();
InOrder order = inOrder(game); InOrder order = inOrder(game);
@ -232,7 +231,7 @@ public class RoundTest {
.end(); .end();
int round = 6; int round = 6;
Game game = performTest(227L, Configurations.ANNIVERSARY_2021_PM1, round, queue); Game game = performTest(227L, Configuration.ANNIVERSARY_2021_PM1, round, queue);
game.await(); game.await();
InOrder order = inOrder(game); InOrder order = inOrder(game);

@ -1,14 +1,13 @@
package eu.jonahbauer.wizard.core.machine.states.trick; package eu.jonahbauer.wizard.core.states.trick;
import eu.jonahbauer.wizard.common.messages.observer.*; import eu.jonahbauer.wizard.common.messages.observer.*;
import eu.jonahbauer.wizard.common.model.Card; import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.common.model.Configuration;
import eu.jonahbauer.wizard.core.machine.GameTestUtils; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.machine.MessageQueue; import eu.jonahbauer.wizard.core.GameTestUtils;
import eu.jonahbauer.wizard.core.machine.states.GameData; import eu.jonahbauer.wizard.core.MessageQueue;
import eu.jonahbauer.wizard.core.machine.states.round.FinishingRound; import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.model.GameConfiguration; import eu.jonahbauer.wizard.core.states.round.FinishingRound;
import eu.jonahbauer.wizard.core.model.Configurations;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.InOrder; import org.mockito.InOrder;
@ -17,10 +16,10 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import static eu.jonahbauer.wizard.core.machine.GameTestUtils.doFinish; import static eu.jonahbauer.wizard.core.GameTestUtils.doFinish;
import static eu.jonahbauer.wizard.core.machine.GameTestUtils.finish; import static eu.jonahbauer.wizard.core.GameTestUtils.finish;
import static eu.jonahbauer.wizard.core.machine.states.GameData.*; import static eu.jonahbauer.wizard.core.states.GameData.*;
import static eu.jonahbauer.wizard.core.machine.states.GameData.TypedValue.entry; import static eu.jonahbauer.wizard.core.states.GameData.TypedValue.entry;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
@ -35,8 +34,8 @@ public class TrickTest {
@SneakyThrows @SneakyThrows
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
private Game performTest(GameConfiguration configuration, int round, int trick, Map<UUID, List<Card>> hands, Card.Suit trump, MessageQueue queue) { private Game performTest(Configuration configuration, int round, int trick, Map<UUID, List<Card>> hands, Card.Suit trump, MessageQueue queue) {
Game game = spy(new Game(configuration, queue)); Game game = spy(new Game(configuration, 10 * 60 * 1000, 10 * 60 * 1000, queue));
doCallRealMethod().doAnswer(finish()).when(game).transition(any(StartingTrick.class)); doCallRealMethod().doAnswer(finish()).when(game).transition(any(StartingTrick.class));
doFinish().when(game).transition(any(FinishingRound.class)); doFinish().when(game).transition(any(FinishingRound.class));
queue.setGame(game); queue.setGame(game);
@ -75,7 +74,7 @@ public class TrickTest {
.sync(players) .sync(players)
.addCards(List.of(players), hands, 0); .addCards(List.of(players), hands, 0);
Game game = performTest(Configurations.DEFAULT, 0, 0, hands, Card.Suit.BLUE, queue); Game game = performTest(Configuration.DEFAULT, 0, 0, hands, Card.Suit.BLUE, queue);
// validate messages // validate messages
InOrder order = inOrder(game); InOrder order = inOrder(game);
@ -116,7 +115,7 @@ public class TrickTest {
.addCard(players[3], Card.BLUE_1) .addCard(players[3], Card.BLUE_1)
.end(); .end();
Game game = performTest(Configurations.DEFAULT, 0, 0, hands, Card.Suit.BLUE, queue); Game game = performTest(Configuration.DEFAULT, 0, 0, hands, Card.Suit.BLUE, queue);
// validate messages // validate messages
InOrder order = inOrder(game); InOrder order = inOrder(game);
@ -159,7 +158,7 @@ public class TrickTest {
.addCard(players[3], Card.BLUE_1) .addCard(players[3], Card.BLUE_1)
.addChangePrediction(players[2], 1); .addChangePrediction(players[2], 1);
Game game = performTest(Configurations.ANNIVERSARY_2021, 0, 0, hands, Card.Suit.GREEN, queue); Game game = performTest(Configuration.ANNIVERSARY_2021, 0, 0, hands, Card.Suit.GREEN, queue);
// validate messages // validate messages
InOrder order = inOrder(game); InOrder order = inOrder(game);
@ -203,7 +202,7 @@ public class TrickTest {
.addJuggle(players[3], Card.BLUE_1) .addJuggle(players[3], Card.BLUE_1)
.end(); .end();
Game game = performTest(Configurations.ANNIVERSARY_2021, 1, 0, hands, Card.Suit.YELLOW, queue); Game game = performTest(Configuration.ANNIVERSARY_2021, 1, 0, hands, Card.Suit.YELLOW, queue);
// validate messages // validate messages
InOrder order = inOrder(game); InOrder order = inOrder(game);
@ -248,7 +247,7 @@ public class TrickTest {
.addCard(players[2], Card.GREEN_1) .addCard(players[2], Card.GREEN_1)
.addCard(players[3], Card.BLUE_1); .addCard(players[3], Card.BLUE_1);
Game game = performTest(Configurations.DEFAULT, 0, 0, hands, Card.Suit.BLUE, queue); Game game = performTest(Configuration.DEFAULT, 0, 0, hands, Card.Suit.BLUE, queue);
// validate messages // validate messages
InOrder order = inOrder(game); InOrder order = inOrder(game);
@ -290,7 +289,7 @@ public class TrickTest {
.addCard(players[2], Card.GREEN_WIZARD) .addCard(players[2], Card.GREEN_WIZARD)
.addCard(players[3], Card.BLUE_1); .addCard(players[3], Card.BLUE_1);
Game game = performTest(Configurations.DEFAULT, 0, 0, hands, Card.Suit.BLUE, queue); Game game = performTest(Configuration.DEFAULT, 0, 0, hands, Card.Suit.BLUE, queue);
// validate messages // validate messages
InOrder order = inOrder(game); InOrder order = inOrder(game);

@ -8,10 +8,9 @@ import eu.jonahbauer.wizard.common.messages.player.ContinueMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage; import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import eu.jonahbauer.wizard.common.messages.server.*; import eu.jonahbauer.wizard.common.messages.server.*;
import eu.jonahbauer.wizard.common.model.Configuration; import eu.jonahbauer.wizard.common.model.Configuration;
import eu.jonahbauer.wizard.core.machine.Game; import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.messages.Observer; import eu.jonahbauer.wizard.core.Observer;
import eu.jonahbauer.wizard.core.model.Configurations; import eu.jonahbauer.wizard.common.util.Pair;
import eu.jonahbauer.wizard.core.util.Pair;
import eu.jonahbauer.wizard.server.machine.Player; import eu.jonahbauer.wizard.server.machine.Player;
import eu.jonahbauer.wizard.server.management.SessionMBean; import eu.jonahbauer.wizard.server.management.SessionMBean;
import lombok.AccessLevel; import lombok.AccessLevel;
@ -169,11 +168,7 @@ public class Session implements Observer, SessionMBean {
throw new NackException(NackMessage.GAME_NOT_YET_STARTED, "Game hat not yet started."); throw new NackException(NackMessage.GAME_NOT_YET_STARTED, "Game hat not yet started.");
} else { } else {
try { try {
game.execute(s -> { game.onMessage(uuid, message, player::buffer);
// start buffering while game is locked
player.buffer();
return s.onMessage(game, uuid, message);
});
player.send(new AckMessage()); player.send(new AckMessage());
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
throw new NackException(NackMessage.ILLEGAL_STATE, e.getMessage()); throw new NackException(NackMessage.ILLEGAL_STATE, e.getMessage());
@ -186,7 +181,7 @@ public class Session implements Observer, SessionMBean {
protected void startGame() { protected void startGame() {
notifyPlayers(new StartingGameMessage()); notifyPlayers(new StartingGameMessage());
messages.add(Pair.of(null, new StartingGameMessage())); messages.add(Pair.of(null, new StartingGameMessage()));
game = new Game(Configurations.get(configuration).withTimeout(timeout), this); game = new Game(configuration, timeout, 10 * 60 * 1000, this);
game.start(List.copyOf(players.keySet())); game.start(List.copyOf(players.keySet()));
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
while (true) { while (true) {

Loading…
Cancel
Save