bugfixes in server and cli-client
This commit is contained in:
parent
ce739933cb
commit
e222ef6ce6
@ -85,4 +85,18 @@ object JavaWebSocket {
|
|||||||
const val version = "1.5.2"
|
const val version = "1.5.2"
|
||||||
const val group = "org.java-websocket"
|
const val group = "org.java-websocket"
|
||||||
const val id = "$group:Java-WebSocket:$version"
|
const val id = "$group:Java-WebSocket:$version"
|
||||||
|
}
|
||||||
|
|
||||||
|
object SpringBoot {
|
||||||
|
const val version = "2.5.6"
|
||||||
|
const val group = "org.springframework.boot"
|
||||||
|
const val plugin = group
|
||||||
|
const val starterWebsocket = "$group:spring-boot-starter-websocket"
|
||||||
|
const val starterTomcat = "$group:spring-boot-starter-tomcat"
|
||||||
|
const val starterLog4j2 = "$group:spring-boot-starter-log4j2"
|
||||||
|
}
|
||||||
|
|
||||||
|
object SpringDependencyManagement {
|
||||||
|
const val version = "1.0.11.RELEASE"
|
||||||
|
const val plugin = "io.spring.dependency-management"
|
||||||
}
|
}
|
@ -25,7 +25,14 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
import static picocli.CommandLine.*;
|
||||||
|
|
||||||
|
@Command
|
||||||
public class Client extends TimeoutContext<ClientState, Client> implements Runnable {
|
public class Client extends TimeoutContext<ClientState, Client> implements Runnable {
|
||||||
|
@Option(names = "-v")
|
||||||
|
@Getter
|
||||||
|
private boolean verbose;
|
||||||
|
|
||||||
private LineReader reader;
|
private LineReader reader;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ -39,7 +46,7 @@ public class Client extends TimeoutContext<ClientState, Client> implements Runna
|
|||||||
private CommandSpec spec;
|
private CommandSpec spec;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
new Client().run();
|
new CommandLine(new Client()).execute(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Client() {
|
public Client() {
|
||||||
@ -126,6 +133,9 @@ public class Client extends TimeoutContext<ClientState, Client> implements Runna
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onMessage(ServerMessage message) {
|
public void onMessage(ServerMessage message) {
|
||||||
|
if (verbose) {
|
||||||
|
println(message.toString());
|
||||||
|
}
|
||||||
execute(s -> s.onMessage(this, message));
|
execute(s -> s.onMessage(this, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +249,7 @@ public class Client extends TimeoutContext<ClientState, Client> implements Runna
|
|||||||
Exception exception = exceptionRef.get();
|
Exception exception = exceptionRef.get();
|
||||||
if (exception == null) {
|
if (exception == null) {
|
||||||
Object result;
|
Object result;
|
||||||
CommandLine.ParseResult parseResult = commandLine.getParseResult();
|
ParseResult parseResult = commandLine.getParseResult();
|
||||||
if (parseResult.subcommand() != null) {
|
if (parseResult.subcommand() != null) {
|
||||||
CommandLine sub = parseResult.subcommand().commandSpec().commandLine();
|
CommandLine sub = parseResult.subcommand().commandSpec().commandLine();
|
||||||
result = sub.getExecutionResult();
|
result = sub.getExecutionResult();
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
package eu.jonahbauer.wizard.client.cli.commands;
|
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.AwaitingAcknowledgement;
|
|
||||||
import eu.jonahbauer.wizard.client.cli.state.Game;
|
import eu.jonahbauer.wizard.client.cli.state.Game;
|
||||||
import eu.jonahbauer.wizard.client.cli.state.Menu;
|
|
||||||
import eu.jonahbauer.wizard.common.messages.client.InteractionMessage;
|
import eu.jonahbauer.wizard.common.messages.client.InteractionMessage;
|
||||||
import eu.jonahbauer.wizard.common.messages.player.JuggleMessage;
|
import eu.jonahbauer.wizard.common.messages.player.JuggleMessage;
|
||||||
import eu.jonahbauer.wizard.common.messages.player.PickTrumpMessage;
|
import eu.jonahbauer.wizard.common.messages.player.PickTrumpMessage;
|
||||||
import eu.jonahbauer.wizard.common.messages.player.PlayCardMessage;
|
import eu.jonahbauer.wizard.common.messages.player.PlayCardMessage;
|
||||||
import eu.jonahbauer.wizard.common.messages.player.PredictMessage;
|
import eu.jonahbauer.wizard.common.messages.player.PredictMessage;
|
||||||
import eu.jonahbauer.wizard.common.messages.server.NackMessage;
|
|
||||||
import eu.jonahbauer.wizard.common.model.Card;
|
import eu.jonahbauer.wizard.common.model.Card;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -21,60 +18,41 @@ import static picocli.CommandLine.*;
|
|||||||
@Command(name = "\b", subcommands = {HelpCommand.class, QuitCommand.class, ShowCommand.class})
|
@Command(name = "\b", subcommands = {HelpCommand.class, QuitCommand.class, ShowCommand.class})
|
||||||
public class GameCommand {
|
public class GameCommand {
|
||||||
private final Client client;
|
private final Client client;
|
||||||
private final Game game;
|
|
||||||
|
|
||||||
public GameCommand(Client client, Game game) {
|
public GameCommand(Client client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.game = game;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command(name = "play")
|
@Command(name = "play")
|
||||||
public AwaitingAcknowledgement play(
|
public void play(
|
||||||
@Parameters(index = "0", paramLabel = "<card>", completionCandidates = HandCompletion.class) Card card
|
@Parameters(index = "0", paramLabel = "<card>", completionCandidates = HandCompletion.class) Card card
|
||||||
) {
|
) {
|
||||||
this.client.send(new InteractionMessage(new PlayCardMessage(card)));
|
this.client.send(new InteractionMessage(new PlayCardMessage(card)));
|
||||||
return awaitAcknowledgement();
|
this.client.waitForReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command(name = "predict")
|
@Command(name = "predict")
|
||||||
public AwaitingAcknowledgement predict(
|
public void predict(
|
||||||
@Parameters(index = "0", paramLabel = "<prediction>") int prediction
|
@Parameters(index = "0", paramLabel = "<prediction>") int prediction
|
||||||
) {
|
) {
|
||||||
this.client.send(new InteractionMessage(new PredictMessage(prediction)));
|
this.client.send(new InteractionMessage(new PredictMessage(prediction)));
|
||||||
return awaitAcknowledgement();
|
this.client.waitForReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command(name = "trump")
|
@Command(name = "trump")
|
||||||
public AwaitingAcknowledgement trump(
|
public void trump(
|
||||||
@Parameters(index = "0", paramLabel = "<suit>") Card.Suit suit
|
@Parameters(index = "0", paramLabel = "<suit>") Card.Suit suit
|
||||||
) {
|
) {
|
||||||
this.client.send(new InteractionMessage(new PickTrumpMessage(suit)));
|
this.client.send(new InteractionMessage(new PickTrumpMessage(suit)));
|
||||||
return awaitAcknowledgement();
|
this.client.waitForReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command(name = "juggle")
|
@Command(name = "juggle")
|
||||||
public AwaitingAcknowledgement juggle(
|
public void juggle(
|
||||||
@Parameters(index = "0", paramLabel = "<card>", completionCandidates = JuggleCompletion.class) Card card
|
@Parameters(index = "0", paramLabel = "<card>", completionCandidates = JuggleCompletion.class) Card card
|
||||||
) {
|
) {
|
||||||
this.client.send(new InteractionMessage(new JuggleMessage(card)));
|
this.client.send(new InteractionMessage(new JuggleMessage(card)));
|
||||||
return awaitAcknowledgement();
|
this.client.waitForReady();
|
||||||
}
|
|
||||||
|
|
||||||
private AwaitingAcknowledgement awaitAcknowledgement() {
|
|
||||||
return new AwaitingAcknowledgement(
|
|
||||||
() -> game,
|
|
||||||
message -> {
|
|
||||||
if (message instanceof NackMessage nack) {
|
|
||||||
int code = nack.getCode();
|
|
||||||
if (code == NackMessage.ILLEGAL_ARGUMENT || code == NackMessage.ILLEGAL_STATE) {
|
|
||||||
client.println("Error: " + nack.getMessage());
|
|
||||||
return game;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.println("Fatal: Unexpected message " + message + ". Returning to menu.");
|
|
||||||
return new Menu();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class HandCompletion implements Iterable<String> {
|
public static class HandCompletion implements Iterable<String> {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package eu.jonahbauer.wizard.client.cli.commands;
|
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.AwaitingAcknowledgement;
|
|
||||||
import eu.jonahbauer.wizard.client.cli.state.AwaitingJoinLobby;
|
import eu.jonahbauer.wizard.client.cli.state.AwaitingJoinLobby;
|
||||||
import eu.jonahbauer.wizard.client.cli.state.Session;
|
import eu.jonahbauer.wizard.client.cli.state.Session;
|
||||||
import eu.jonahbauer.wizard.common.messages.client.LeaveSessionMessage;
|
import eu.jonahbauer.wizard.common.messages.client.LeaveSessionMessage;
|
||||||
@ -20,13 +19,12 @@ public class SessionCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Command(name = "ready")
|
@Command(name = "ready")
|
||||||
public AwaitingAcknowledgement ready(
|
public void ready(
|
||||||
@Parameters(index = "0", paramLabel = "<ready>", defaultValue = "true") boolean ready
|
@Parameters(index = "0", paramLabel = "<ready>", defaultValue = "true") boolean ready
|
||||||
) {
|
) {
|
||||||
|
session.setNextReady(ready);
|
||||||
client.send(new ReadyMessage(ready));
|
client.send(new ReadyMessage(ready));
|
||||||
return new AwaitingAcknowledgement(
|
client.waitForReady();
|
||||||
() -> new Session(session.getSelf(), session.getSession(), ready, session.getPlayers())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command(name = "leave", description = "Leaves the current session and returns to the lobby")
|
@Command(name = "leave", description = "Leaves the current session and returns to the lobby")
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
package eu.jonahbauer.wizard.client.cli.state;
|
|
||||||
|
|
||||||
import eu.jonahbauer.wizard.client.cli.Client;
|
|
||||||
import eu.jonahbauer.wizard.common.messages.server.AckMessage;
|
|
||||||
import eu.jonahbauer.wizard.common.messages.server.Response;
|
|
||||||
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public final class AwaitingAcknowledgement extends Awaiting {
|
|
||||||
private final Supplier<ClientState> success;
|
|
||||||
private final Function<ServerMessage, ClientState> failure;
|
|
||||||
|
|
||||||
public AwaitingAcknowledgement(Supplier<ClientState> success, Function<ServerMessage, ClientState> failure) {
|
|
||||||
this.success = success;
|
|
||||||
this.failure = failure;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AwaitingAcknowledgement(Supplier<ClientState> success) {
|
|
||||||
this.success = success;
|
|
||||||
this.failure = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<ClientState> onEnter(Client client) {
|
|
||||||
client.println("Waiting for acknowledgment...");
|
|
||||||
return super.onEnter(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<ClientState> onMessage(Client client, ServerMessage message) {
|
|
||||||
if (message instanceof AckMessage) {
|
|
||||||
return Optional.of(success.get());
|
|
||||||
} else if (failure != null) {
|
|
||||||
return Optional.of(failure.apply(message));
|
|
||||||
} else {
|
|
||||||
return super.onMessage(client, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +1,7 @@
|
|||||||
package eu.jonahbauer.wizard.client.cli.state;
|
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.common.messages.server.NackMessage;
|
import eu.jonahbauer.wizard.common.messages.server.*;
|
||||||
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
|
|
||||||
import eu.jonahbauer.wizard.common.messages.server.SessionJoinedMessage;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -28,6 +26,9 @@ public final class AwaitingJoinSession extends Awaiting {
|
|||||||
default -> { return super.onMessage(client, message); }
|
default -> { return super.onMessage(client, message); }
|
||||||
}
|
}
|
||||||
return Optional.of(new AwaitingJoinLobby());
|
return Optional.of(new AwaitingJoinLobby());
|
||||||
|
} else if (message instanceof SessionModifiedMessage || message instanceof SessionRemovedMessage) {
|
||||||
|
// drop
|
||||||
|
return Optional.empty();
|
||||||
} else {
|
} else {
|
||||||
return super.onMessage(client, message);
|
return super.onMessage(client, message);
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,9 @@ public abstract class BaseState implements ClientState {
|
|||||||
protected static Optional<ClientState> unexpectedMessage(Client client, ServerMessage message) {
|
protected static Optional<ClientState> unexpectedMessage(Client client, ServerMessage message) {
|
||||||
// return to menu on unexpected message
|
// return to menu on unexpected message
|
||||||
client.println("Fatal: Unexpected message " + message + ". Returning to menu.");
|
client.println("Fatal: Unexpected message " + message + ". Returning to menu.");
|
||||||
|
if (client.isVerbose()) {
|
||||||
|
new Exception().printStackTrace();
|
||||||
|
}
|
||||||
return Optional.of(new Menu());
|
return Optional.of(new Menu());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,9 @@ import eu.jonahbauer.wizard.client.cli.commands.GameCommand;
|
|||||||
import eu.jonahbauer.wizard.client.cli.util.Pair;
|
import eu.jonahbauer.wizard.client.cli.util.Pair;
|
||||||
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.*;
|
||||||
|
import eu.jonahbauer.wizard.common.messages.server.AckMessage;
|
||||||
import eu.jonahbauer.wizard.common.messages.server.GameMessage;
|
import eu.jonahbauer.wizard.common.messages.server.GameMessage;
|
||||||
|
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 lombok.Getter;
|
import lombok.Getter;
|
||||||
@ -149,6 +151,18 @@ public final class Game extends BaseState {
|
|||||||
throw new AssertionError("Unknown observer message " + observerMessage.getClass().getSimpleName() + "");
|
throw new AssertionError("Unknown observer message " + observerMessage.getClass().getSimpleName() + "");
|
||||||
}
|
}
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
} else if (message instanceof NackMessage nack) {
|
||||||
|
int code = nack.getCode();
|
||||||
|
if (code == NackMessage.ILLEGAL_ARGUMENT || code == NackMessage.ILLEGAL_STATE) {
|
||||||
|
client.println("Error: " + nack.getMessage());
|
||||||
|
client.ready();
|
||||||
|
return Optional.empty();
|
||||||
|
} else {
|
||||||
|
return unexpectedMessage(client, message);
|
||||||
|
}
|
||||||
|
} else if (message instanceof AckMessage) {
|
||||||
|
client.ready();
|
||||||
|
return Optional.empty();
|
||||||
} else {
|
} else {
|
||||||
return unexpectedMessage(client, message);
|
return unexpectedMessage(client, message);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,9 @@ public final class Menu extends BaseState {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<ClientState> onMessage(Client client, ServerMessage message) {
|
public Optional<ClientState> onMessage(Client client, ServerMessage message) {
|
||||||
throw new AssertionError("Received a ServerMessage while not connected.");
|
// it is possible that there are messages still queued after
|
||||||
|
// returning to the menu as a result of a previous message
|
||||||
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -5,6 +5,7 @@ import eu.jonahbauer.wizard.client.cli.commands.SessionCommand;
|
|||||||
import eu.jonahbauer.wizard.common.messages.data.PlayerData;
|
import eu.jonahbauer.wizard.common.messages.data.PlayerData;
|
||||||
import eu.jonahbauer.wizard.common.messages.server.*;
|
import eu.jonahbauer.wizard.common.messages.server.*;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import picocli.CommandLine.Model.CommandSpec;
|
import picocli.CommandLine.Model.CommandSpec;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -19,9 +20,12 @@ public final class Session extends BaseState {
|
|||||||
|
|
||||||
private final UUID self;
|
private final UUID self;
|
||||||
private final UUID session;
|
private final UUID session;
|
||||||
private final boolean ready;
|
|
||||||
private final Map<UUID, PlayerData> players = new HashMap<>();
|
private final Map<UUID, PlayerData> players = new HashMap<>();
|
||||||
|
|
||||||
|
private boolean ready;
|
||||||
|
@Setter
|
||||||
|
private Boolean nextReady;
|
||||||
|
|
||||||
public Session(SessionJoinedMessage joined) {
|
public Session(SessionJoinedMessage joined) {
|
||||||
this.self = joined.getPlayer();
|
this.self = joined.getPlayer();
|
||||||
this.session = joined.getSession();
|
this.session = joined.getSession();
|
||||||
@ -68,6 +72,16 @@ public final class Session extends BaseState {
|
|||||||
session,
|
session,
|
||||||
players.values().stream().collect(Collectors.toMap(PlayerData::getUuid, PlayerData::getName))
|
players.values().stream().collect(Collectors.toMap(PlayerData::getUuid, PlayerData::getName))
|
||||||
));
|
));
|
||||||
|
} else if (nextReady != null && message instanceof NackMessage nack) {
|
||||||
|
client.println("Error: " + nack.getMessage());
|
||||||
|
nextReady = null;
|
||||||
|
client.ready();
|
||||||
|
return Optional.empty();
|
||||||
|
} else if (nextReady != null && message instanceof AckMessage) {
|
||||||
|
ready = nextReady;
|
||||||
|
nextReady = null;
|
||||||
|
client.ready();
|
||||||
|
return Optional.empty();
|
||||||
} else {
|
} else {
|
||||||
return unexpectedMessage(client, message);
|
return unexpectedMessage(client, message);
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("org.springframework.boot").version("2.5.6")
|
id(SpringBoot.plugin) version SpringBoot.version
|
||||||
//id("io.spring.dependency-management").version("1.0.7-RELEASE")
|
id(SpringDependencyManagement.plugin) version SpringDependencyManagement.version
|
||||||
id("java")
|
id("java")
|
||||||
}
|
id("war")
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":wizard-core"))
|
implementation(project(":wizard-core"))
|
||||||
implementation(project(":wizard-common"))
|
implementation(project(":wizard-common"))
|
||||||
implementation("org.springframework.boot:spring-boot-starter-websocket:2.5.6")
|
implementation(SpringBoot.starterWebsocket) {
|
||||||
|
exclude(group = SpringBoot.group, module = "spring-boot-starter-logging")
|
||||||
|
}
|
||||||
|
implementation(SpringBoot.starterLog4j2)
|
||||||
|
providedRuntime(SpringBoot.starterTomcat)
|
||||||
}
|
}
|
||||||
|
@ -9,19 +9,23 @@ import eu.jonahbauer.wizard.common.model.Configuration;
|
|||||||
import eu.jonahbauer.wizard.core.machine.Game;
|
import eu.jonahbauer.wizard.core.machine.Game;
|
||||||
import eu.jonahbauer.wizard.core.messages.Observer;
|
import eu.jonahbauer.wizard.core.messages.Observer;
|
||||||
import eu.jonahbauer.wizard.core.model.Configurations;
|
import eu.jonahbauer.wizard.core.model.Configurations;
|
||||||
import eu.jonahbauer.wizard.core.model.GameConfiguration;
|
|
||||||
import eu.jonahbauer.wizard.server.machine.Player;
|
import eu.jonahbauer.wizard.server.machine.Player;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
|
@Log4j2
|
||||||
@EqualsAndHashCode(of = "uuid")
|
@EqualsAndHashCode(of = "uuid")
|
||||||
public class Session implements Observer {
|
public class Session implements Observer {
|
||||||
private static final int MIN_PLAYERS = 3;
|
private static final int MIN_PLAYERS = 3;
|
||||||
@ -46,7 +50,7 @@ public class Session implements Observer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Associates the given player with this session, removes him from the lobby, notifies all other players in the
|
* Associates the given player with this session and notifies all other players in the
|
||||||
* session with a {@link PlayerJoinedMessage}, the joining player with a {@link SessionJoinedMessage} and all
|
* session with a {@link PlayerJoinedMessage}, the joining player with a {@link SessionJoinedMessage} and all
|
||||||
* players in the lobby with a {@link SessionModifiedMessage}.
|
* players in the lobby with a {@link SessionModifiedMessage}.
|
||||||
*
|
*
|
||||||
@ -55,18 +59,19 @@ public class Session implements Observer {
|
|||||||
* @return the players uuid
|
* @return the players uuid
|
||||||
*/
|
*/
|
||||||
public synchronized UUID join(Player player, String name) {
|
public synchronized UUID join(Player player, String name) {
|
||||||
if (players.size() == MAX_PLAYERS) {
|
if (game != null) {
|
||||||
|
throw new NackException(NackMessage.GAME_ALREADY_STARTED, "Game has already started.");
|
||||||
|
} else if (players.size() == MAX_PLAYERS) {
|
||||||
throw new NackException(NackMessage.SESSION_FULL, "Session is full.");
|
throw new NackException(NackMessage.SESSION_FULL, "Session is full.");
|
||||||
} else if (players.values().stream().anyMatch(p -> p.getName().equalsIgnoreCase(name))) {
|
} else if (players.values().stream().anyMatch(p -> p.getName().equalsIgnoreCase(name))) {
|
||||||
throw new NackException(NackMessage.NAME_TAKEN, "Name is already taken.");
|
throw new NackException(NackMessage.NAME_TAKEN, "Name is already taken.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Lobby.getInstance().leave(player);
|
|
||||||
|
|
||||||
SessionPlayer sessionPlayer;
|
SessionPlayer sessionPlayer;
|
||||||
do {
|
do {
|
||||||
sessionPlayer = new SessionPlayer(UUID.randomUUID(), name, player);
|
sessionPlayer = new SessionPlayer(UUID.randomUUID(), name);
|
||||||
} while (players.putIfAbsent(sessionPlayer.getUuid(), sessionPlayer) != null);
|
} while (players.putIfAbsent(sessionPlayer.getUuid(), sessionPlayer) != null);
|
||||||
|
sessionPlayer.setPlayer(player);
|
||||||
|
|
||||||
notifyJoined(sessionPlayer.toData());
|
notifyJoined(sessionPlayer.toData());
|
||||||
Lobby.getInstance().notifyPlayers(new SessionModifiedMessage(toData()));
|
Lobby.getInstance().notifyPlayers(new SessionModifiedMessage(toData()));
|
||||||
@ -75,54 +80,120 @@ public class Session implements Observer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void leave(UUID player) {
|
public synchronized void leave(UUID player) {
|
||||||
if (players.remove(player) != null) {
|
if (game == null) {
|
||||||
if (players.size() == 0) {
|
if (players.remove(player) != null) {
|
||||||
Lobby.getInstance().removeSession(uuid);
|
if (players.size() == 0) {
|
||||||
} else {
|
Lobby.getInstance().removeSession(uuid);
|
||||||
notifyPlayers(new PlayerLeftMessage(player));
|
} else {
|
||||||
Lobby.getInstance().notifyPlayers(new SessionModifiedMessage(toData()));
|
notifyPlayers(new PlayerLeftMessage(player));
|
||||||
|
Lobby.getInstance().notifyPlayers(new SessionModifiedMessage(toData()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var sessionPlayer = players.get(player);
|
||||||
|
if (sessionPlayer != null) {
|
||||||
|
sessionPlayer.setPlayer(null);
|
||||||
|
if (players.values().stream().noneMatch(SessionPlayer::isConnected)) {
|
||||||
|
Lobby.getInstance().removeSession(uuid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void ready(UUID player, boolean ready) {
|
public synchronized void ready(UUID uuid, boolean ready) {
|
||||||
var sessionPlayer = players.get(player);
|
var player = players.get(uuid);
|
||||||
if (sessionPlayer == null) {
|
if (player == null) {
|
||||||
throw new NackException(NackMessage.PLAYER_NOT_FOUND, "Who are you?");
|
throw new NackException(NackMessage.PLAYER_NOT_FOUND, "Who are you?");
|
||||||
|
} else if (game != null) {
|
||||||
|
throw new NackException(NackMessage.GAME_ALREADY_STARTED, "Game has already started.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sessionPlayer.isReady() != ready) {
|
player.send(new AckMessage());
|
||||||
sessionPlayer.setReady(ready);
|
if (player.isReady() != ready) {
|
||||||
sessionPlayer.getPlayer().send(new AckMessage());
|
player.setReady(ready);
|
||||||
notifyPlayers(new PlayerModifiedMessage(sessionPlayer.toData()));
|
notifyPlayers(new PlayerModifiedMessage(player.toData()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (players.size() >= MIN_PLAYERS && players.values().stream().allMatch(SessionPlayer::isReady)) {
|
if (players.size() >= MIN_PLAYERS && players.values().stream().allMatch(SessionPlayer::isReady)) {
|
||||||
game = new Game(Configurations.get(configuration), this);
|
startGame();
|
||||||
notifyPlayers(new StartingGameMessage());
|
|
||||||
game.start(players.keySet().stream().toList());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forwards the message sent by the player to the game.
|
||||||
|
*
|
||||||
|
* @param uuid the player
|
||||||
|
* @param message the players message
|
||||||
|
*/
|
||||||
|
public synchronized void handlePlayerMessage(UUID uuid, PlayerMessage message) {
|
||||||
|
var player = players.get(uuid);
|
||||||
|
if (player == null) {
|
||||||
|
throw new NackException(NackMessage.PLAYER_NOT_FOUND, "Who are you?");
|
||||||
|
} else if (game == null) {
|
||||||
|
throw new NackException(NackMessage.GAME_NOT_YET_STARTED, "Game hat not yet started.");
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
game.execute(s -> {
|
||||||
|
// start buffering while game is locked
|
||||||
|
player.buffer();
|
||||||
|
return s.onMessage(game, uuid, message);
|
||||||
|
});
|
||||||
|
player.send(new AckMessage());
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
throw new NackException(NackMessage.ILLEGAL_STATE, e.getMessage());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new NackException(NackMessage.ILLEGAL_ARGUMENT, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startGame() {
|
||||||
|
notifyPlayers(new StartingGameMessage());
|
||||||
|
game = new Game(Configurations.get(configuration).withTimeout(timeout), this);
|
||||||
|
game.start(List.copyOf(players.keySet()));
|
||||||
|
CompletableFuture.runAsync(() -> {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
game.await();
|
||||||
|
break;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// ignored
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
log.warn("Game completed with exception.", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
players.forEach((id, player) -> player.setReady(false));
|
||||||
|
synchronized (this) {
|
||||||
|
game = null;
|
||||||
|
for (SessionPlayer player : List.copyOf(players.values())) {
|
||||||
|
if (!player.isConnected()) {
|
||||||
|
leave(player.getUuid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyJoined(PlayerData joined) {
|
private void notifyJoined(PlayerData joined) {
|
||||||
var message = new PlayerJoinedMessage(joined);
|
var message = new PlayerJoinedMessage(joined);
|
||||||
for (SessionPlayer player : players.values()) {
|
for (SessionPlayer player : players.values()) {
|
||||||
if (player.getUuid().equals(joined.getUuid())) {
|
if (player.getUuid().equals(joined.getUuid())) {
|
||||||
player.getPlayer().send(new SessionJoinedMessage(
|
player.send(new SessionJoinedMessage(
|
||||||
getUuid(),
|
getUuid(),
|
||||||
player.getUuid(),
|
player.getUuid(),
|
||||||
players.values().stream().map(SessionPlayer::toData).toList(),
|
players.values().stream().map(SessionPlayer::toData).toList(),
|
||||||
player.getSecret()
|
player.getSecret()
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
player.getPlayer().send(message);
|
player.send(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyPlayers(ServerMessage message) {
|
private void notifyPlayers(ServerMessage message) {
|
||||||
for (SessionPlayer player : players.values()) {
|
for (SessionPlayer player : players.values()) {
|
||||||
player.getPlayer().send(message);
|
player.send(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,16 +201,6 @@ public class Session implements Observer {
|
|||||||
return new SessionData(uuid, name, players.size(), configuration);
|
return new SessionData(uuid, name, players.size(), configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Forwards the message sent by the player to the game.
|
|
||||||
*
|
|
||||||
* @param player the player
|
|
||||||
* @param message the players message
|
|
||||||
*/
|
|
||||||
public void handlePlayerMessage(UUID player, PlayerMessage message) {
|
|
||||||
game.onMessage(player, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notify(ObserverMessage message) {
|
public void notify(ObserverMessage message) {
|
||||||
notifyPlayers(new GameMessage(message));
|
notifyPlayers(new GameMessage(message));
|
||||||
@ -147,7 +208,7 @@ public class Session implements Observer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notify(UUID player, ObserverMessage message) {
|
public void notify(UUID player, ObserverMessage message) {
|
||||||
players.get(player).getPlayer().send(new GameMessage(message));
|
players.get(player).send(new GameMessage(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ -155,8 +216,8 @@ public class Session implements Observer {
|
|||||||
private static class SessionPlayer {
|
private static class SessionPlayer {
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final Player player;
|
|
||||||
private final String secret = generateSecret();
|
private final String secret = generateSecret();
|
||||||
|
private Player player;
|
||||||
private boolean ready;
|
private boolean ready;
|
||||||
|
|
||||||
private static String generateSecret() {
|
private static String generateSecret() {
|
||||||
@ -169,5 +230,21 @@ public class Session implements Observer {
|
|||||||
public PlayerData toData() {
|
public PlayerData toData() {
|
||||||
return new PlayerData(uuid, name, ready);
|
return new PlayerData(uuid, name, ready);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void send(ServerMessage message) {
|
||||||
|
if (player != null) {
|
||||||
|
player.send(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buffer() {
|
||||||
|
if (player != null) {
|
||||||
|
player.buffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected() {
|
||||||
|
return player != null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,18 +3,18 @@ package eu.jonahbauer.wizard.server.machine;
|
|||||||
import eu.jonahbauer.wizard.common.machine.State;
|
import eu.jonahbauer.wizard.common.machine.State;
|
||||||
import eu.jonahbauer.wizard.common.messages.client.ClientMessage;
|
import eu.jonahbauer.wizard.common.messages.client.ClientMessage;
|
||||||
import eu.jonahbauer.wizard.common.messages.server.NackMessage;
|
import eu.jonahbauer.wizard.common.messages.server.NackMessage;
|
||||||
|
import eu.jonahbauer.wizard.server.NackException;
|
||||||
import org.springframework.web.socket.CloseStatus;
|
import org.springframework.web.socket.CloseStatus;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public interface ClientState extends State<ClientState, Player> {
|
public interface ClientState extends State<ClientState, Player> {
|
||||||
default Optional<ClientState> onOpen(Player player) {
|
default Optional<ClientState> onOpen(Player player) {
|
||||||
throw new IllegalStateException(); // TODO nachdenken
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
default Optional<ClientState> onMessage(Player player, ClientMessage message) {
|
default Optional<ClientState> onMessage(Player player, ClientMessage message) {
|
||||||
player.send(new NackMessage(NackMessage.BAD_REQUEST, "Unexpected message."));
|
throw new NackException(NackMessage.UNEXPECTED_MESSAGE, "Don't know what to do with " + message + ".");
|
||||||
return Optional.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<ClientState> onClose(Player player, CloseStatus status);
|
Optional<ClientState> onClose(Player player, CloseStatus status);
|
||||||
|
@ -2,17 +2,20 @@ package eu.jonahbauer.wizard.server.machine;
|
|||||||
|
|
||||||
import eu.jonahbauer.wizard.common.machine.Context;
|
import eu.jonahbauer.wizard.common.machine.Context;
|
||||||
import eu.jonahbauer.wizard.common.messages.client.ClientMessage;
|
import eu.jonahbauer.wizard.common.messages.client.ClientMessage;
|
||||||
import eu.jonahbauer.wizard.common.messages.server.NackMessage;
|
import eu.jonahbauer.wizard.common.messages.server.Response;
|
||||||
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
|
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
|
||||||
import eu.jonahbauer.wizard.server.NackException;
|
|
||||||
import eu.jonahbauer.wizard.server.machine.states.CreatedState;
|
import eu.jonahbauer.wizard.server.machine.states.CreatedState;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.springframework.web.socket.CloseStatus;
|
import org.springframework.web.socket.CloseStatus;
|
||||||
import org.springframework.web.socket.TextMessage;
|
import org.springframework.web.socket.TextMessage;
|
||||||
import org.springframework.web.socket.WebSocketSession;
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class Player extends Context<ClientState, Player> {
|
public class Player extends Context<ClientState, Player> {
|
||||||
private final WebSocketSession session;
|
private final WebSocketSession session;
|
||||||
|
private final ArrayList<ServerMessage> buffer = new ArrayList<>();
|
||||||
|
private Class<?> shouldBuffer = null;
|
||||||
|
|
||||||
public Player(WebSocketSession session) {
|
public Player(WebSocketSession session) {
|
||||||
super(new CreatedState());
|
super(new CreatedState());
|
||||||
@ -29,22 +32,32 @@ public class Player extends Context<ClientState, Player> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onMessage(ClientMessage message) {
|
public void onMessage(ClientMessage message) {
|
||||||
|
execute(s -> s.onMessage(this, message));
|
||||||
try {
|
|
||||||
execute(s -> s.onMessage(this, message));
|
|
||||||
} catch (NackException e) {
|
|
||||||
send(new NackMessage(e.getCode(), e.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onClose(CloseStatus status) {
|
public void onClose(CloseStatus status) {
|
||||||
execute(s -> s.onClose(this, status));
|
execute(s -> s.onClose(this, status));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void buffer() {
|
||||||
|
shouldBuffer = Response.class;
|
||||||
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void send(ServerMessage message) {
|
public void send(ServerMessage message) {
|
||||||
synchronized (session) {
|
synchronized (session) {
|
||||||
session.sendMessage(new TextMessage(message.toString()));
|
if (shouldBuffer != null && shouldBuffer.isInstance(message)) {
|
||||||
|
session.sendMessage(new TextMessage(message.toString()));
|
||||||
|
shouldBuffer = null;
|
||||||
|
for (ServerMessage serverMessage : buffer) {
|
||||||
|
session.sendMessage(new TextMessage(serverMessage.toString()));
|
||||||
|
}
|
||||||
|
buffer.clear();
|
||||||
|
} else if (shouldBuffer != null) {
|
||||||
|
buffer.add(message);
|
||||||
|
} else {
|
||||||
|
session.sendMessage(new TextMessage(message.toString()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
package eu.jonahbauer.wizard.server.machine.states;
|
|
||||||
|
|
||||||
import eu.jonahbauer.wizard.common.messages.client.ClientMessage;
|
|
||||||
import eu.jonahbauer.wizard.common.messages.client.LeaveSessionMessage;
|
|
||||||
import eu.jonahbauer.wizard.common.messages.server.NackMessage;
|
|
||||||
import eu.jonahbauer.wizard.common.messages.server.StartingGameMessage;
|
|
||||||
import eu.jonahbauer.wizard.server.machine.ClientState;
|
|
||||||
import eu.jonahbauer.wizard.server.machine.Player;
|
|
||||||
import org.springframework.web.socket.CloseStatus;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class InGame implements ClientState {
|
|
||||||
@Override
|
|
||||||
public Optional<ClientState> onEnter(Player context) {
|
|
||||||
context.send(new StartingGameMessage());
|
|
||||||
|
|
||||||
return ClientState.super.onEnter(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onExit(Player context) {
|
|
||||||
ClientState.super.onExit(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<ClientState> onOpen(Player player) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<ClientState> onMessage(Player player, ClientMessage message) {
|
|
||||||
if(message instanceof LeaveSessionMessage) {
|
|
||||||
//?
|
|
||||||
return Optional.empty();
|
|
||||||
} else {
|
|
||||||
player.send(new NackMessage(0, "Error: Invalid Message!"));
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<ClientState> onClose(Player player, CloseStatus status) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
@ -23,16 +23,33 @@ public class LobbyState implements ClientState {
|
|||||||
public Optional<ClientState> onMessage(Player player, ClientMessage message) {
|
public Optional<ClientState> onMessage(Player player, ClientMessage message) {
|
||||||
if (message instanceof CreateSessionMessage create) {
|
if (message instanceof CreateSessionMessage create) {
|
||||||
Lobby.getInstance().leave(player);
|
Lobby.getInstance().leave(player);
|
||||||
var session = Lobby.getInstance().createSession(create);
|
try {
|
||||||
var uuid = session.join(player, create.getPlayerName());
|
player.buffer();
|
||||||
return Optional.of(new SessionState(session.getUuid(), uuid, create.getPlayerName()));
|
var session = Lobby.getInstance().createSession(create);
|
||||||
|
var uuid = session.join(player, create.getPlayerName());
|
||||||
|
return Optional.of(new SessionState(session.getUuid(), uuid, create.getPlayerName()));
|
||||||
|
} catch (NackException nack) {
|
||||||
|
// nack must be sent before joinlobby
|
||||||
|
player.send(nack.toMessage());
|
||||||
|
Lobby.getInstance().join(player);
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
} else if (message instanceof JoinSessionMessage join) {
|
} else if (message instanceof JoinSessionMessage join) {
|
||||||
var session = Lobby.getInstance().getSession(join.getSession());
|
Lobby.getInstance().leave(player);
|
||||||
if (session == null) {
|
try {
|
||||||
throw new NackException(NackMessage.NOT_FOUND, "Session not found.");
|
player.buffer();
|
||||||
} else {
|
var session = Lobby.getInstance().getSession(join.getSession());
|
||||||
var uuid = session.join(player, join.getPlayerName());
|
if (session == null) {
|
||||||
return Optional.of(new SessionState(session.getUuid(), uuid, join.getPlayerName()));
|
throw new NackException(NackMessage.NOT_FOUND, "Session not found.");
|
||||||
|
} else {
|
||||||
|
var uuid = session.join(player, join.getPlayerName());
|
||||||
|
return Optional.of(new SessionState(session.getUuid(), uuid, join.getPlayerName()));
|
||||||
|
}
|
||||||
|
} catch (NackException nack) {
|
||||||
|
// nack must be sent before joinlobby
|
||||||
|
player.send(nack.toMessage());
|
||||||
|
Lobby.getInstance().join(player);
|
||||||
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return ClientState.super.onMessage(player, message);
|
return ClientState.super.onMessage(player, message);
|
||||||
|
@ -4,7 +4,6 @@ import eu.jonahbauer.wizard.common.messages.client.ClientMessage;
|
|||||||
import eu.jonahbauer.wizard.common.messages.client.InteractionMessage;
|
import eu.jonahbauer.wizard.common.messages.client.InteractionMessage;
|
||||||
import eu.jonahbauer.wizard.common.messages.client.LeaveSessionMessage;
|
import eu.jonahbauer.wizard.common.messages.client.LeaveSessionMessage;
|
||||||
import eu.jonahbauer.wizard.common.messages.client.ReadyMessage;
|
import eu.jonahbauer.wizard.common.messages.client.ReadyMessage;
|
||||||
import eu.jonahbauer.wizard.common.messages.server.NackMessage;
|
|
||||||
import eu.jonahbauer.wizard.server.Lobby;
|
import eu.jonahbauer.wizard.server.Lobby;
|
||||||
import eu.jonahbauer.wizard.server.machine.ClientState;
|
import eu.jonahbauer.wizard.server.machine.ClientState;
|
||||||
import eu.jonahbauer.wizard.server.machine.Player;
|
import eu.jonahbauer.wizard.server.machine.Player;
|
||||||
@ -42,8 +41,7 @@ public class SessionState implements ClientState {
|
|||||||
Lobby.getInstance().getSession(session).handlePlayerMessage(self, playerMessage);
|
Lobby.getInstance().getSession(session).handlePlayerMessage(self, playerMessage);
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
} else {
|
} else {
|
||||||
player.send(new NackMessage(NackMessage.UNEXPECTED_MESSAGE, "Invalid Message!"));
|
return ClientState.super.onMessage(player, message);
|
||||||
return Optional.empty();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package eu.jonahbauer.wizard.server.socket;
|
package eu.jonahbauer.wizard.server.socket;
|
||||||
|
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
import eu.jonahbauer.wizard.common.messages.client.ClientMessage;
|
import eu.jonahbauer.wizard.common.messages.client.ClientMessage;
|
||||||
|
import eu.jonahbauer.wizard.common.messages.server.NackMessage;
|
||||||
|
import eu.jonahbauer.wizard.server.NackException;
|
||||||
import eu.jonahbauer.wizard.server.machine.Player;
|
import eu.jonahbauer.wizard.server.machine.Player;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -29,7 +32,14 @@ public class WizardSocketHandler extends TextWebSocketHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleTextMessage(@NotNull WebSocketSession session, @NotNull TextMessage text) {
|
protected void handleTextMessage(@NotNull WebSocketSession session, @NotNull TextMessage text) {
|
||||||
players.get(session.getId()).onMessage(ClientMessage.parse(text.getPayload()));
|
var player = players.get(session.getId());
|
||||||
|
try {
|
||||||
|
player.onMessage(ClientMessage.parse(text.getPayload()));
|
||||||
|
} catch (NackException e) {
|
||||||
|
player.send(e.toMessage());
|
||||||
|
} catch (JsonParseException e) {
|
||||||
|
player.send(new NackMessage(NackMessage.MALFORMED_MESSAGE, "Could not parse " + text.getPayload() + "."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user