added debug websocket
This commit is contained in:
parent
0f3d3e929d
commit
ec77b05b0d
@ -5,7 +5,10 @@ import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
|
|||||||
import eu.jonahbauer.wizard.common.messages.server.SessionCreatedMessage;
|
import eu.jonahbauer.wizard.common.messages.server.SessionCreatedMessage;
|
||||||
import eu.jonahbauer.wizard.common.messages.server.SessionListMessage;
|
import eu.jonahbauer.wizard.common.messages.server.SessionListMessage;
|
||||||
import eu.jonahbauer.wizard.common.messages.server.SessionRemovedMessage;
|
import eu.jonahbauer.wizard.common.messages.server.SessionRemovedMessage;
|
||||||
|
import eu.jonahbauer.wizard.common.model.Configuration;
|
||||||
|
import eu.jonahbauer.wizard.server.debug.DebugSession;
|
||||||
import eu.jonahbauer.wizard.server.machine.Player;
|
import eu.jonahbauer.wizard.server.machine.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@ -44,6 +47,22 @@ public class Lobby {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DebugSession createDebugSession(@NotNull String name, long timeout, @NotNull Configuration configuration) {
|
||||||
|
lock.readLock().lock();
|
||||||
|
try {
|
||||||
|
DebugSession session;
|
||||||
|
do {
|
||||||
|
session = new DebugSession(UUID.randomUUID(), name, timeout, configuration);
|
||||||
|
} while (sessions.putIfAbsent(session.getUuid(), session) != null);
|
||||||
|
|
||||||
|
notifyPlayers(new SessionCreatedMessage(session.toData()));
|
||||||
|
|
||||||
|
return session;
|
||||||
|
} finally {
|
||||||
|
lock.readLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Session getSession(UUID uuid) {
|
public Session getSession(UUID uuid) {
|
||||||
return sessions.get(uuid);
|
return sessions.get(uuid);
|
||||||
}
|
}
|
||||||
|
@ -26,15 +26,15 @@ import java.util.concurrent.ThreadLocalRandom;
|
|||||||
@Log4j2
|
@Log4j2
|
||||||
@EqualsAndHashCode(of = "uuid")
|
@EqualsAndHashCode(of = "uuid")
|
||||||
public class Session implements Observer {
|
public class Session implements Observer {
|
||||||
private static final int MIN_PLAYERS = 3;
|
protected static final int MIN_PLAYERS = 3;
|
||||||
private static final int MAX_PLAYERS = 6;
|
protected static final int MAX_PLAYERS = 6;
|
||||||
|
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final long timeout;
|
private final long timeout;
|
||||||
private final Configuration configuration;
|
private final Configuration configuration;
|
||||||
|
|
||||||
@Getter(AccessLevel.NONE)
|
@Getter(AccessLevel.PROTECTED)
|
||||||
private final Map<UUID, SessionPlayer> players = new LinkedHashMap<>();
|
private final Map<UUID, SessionPlayer> players = new LinkedHashMap<>();
|
||||||
|
|
||||||
private Game game;
|
private Game game;
|
||||||
@ -174,7 +174,7 @@ public class Session implements Observer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private 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(Configurations.get(configuration).withTimeout(timeout), this);
|
||||||
@ -204,7 +204,7 @@ public class Session implements Observer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyJoined(PlayerData joined) {
|
protected 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())) {
|
||||||
@ -220,7 +220,7 @@ public class Session implements Observer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyPlayers(ServerMessage message) {
|
protected void notifyPlayers(ServerMessage message) {
|
||||||
for (SessionPlayer player : players.values()) {
|
for (SessionPlayer player : players.values()) {
|
||||||
player.send(message);
|
player.send(message);
|
||||||
}
|
}
|
||||||
@ -246,7 +246,7 @@ public class Session implements Observer {
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(of = "uuid")
|
@EqualsAndHashCode(of = "uuid")
|
||||||
private static class SessionPlayer {
|
protected static class SessionPlayer {
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String secret = generateSecret();
|
private final String secret = generateSecret();
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
package eu.jonahbauer.wizard.server.debug;
|
||||||
|
|
||||||
|
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
|
||||||
|
import eu.jonahbauer.wizard.common.messages.server.NackMessage;
|
||||||
|
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
|
||||||
|
import eu.jonahbauer.wizard.common.messages.server.SessionModifiedMessage;
|
||||||
|
import eu.jonahbauer.wizard.common.model.Configuration;
|
||||||
|
import eu.jonahbauer.wizard.server.Lobby;
|
||||||
|
import eu.jonahbauer.wizard.server.NackException;
|
||||||
|
import eu.jonahbauer.wizard.server.Session;
|
||||||
|
import eu.jonahbauer.wizard.server.machine.Player;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class DebugSession extends Session {
|
||||||
|
public DebugSession(UUID uuid, String name, long timeout, Configuration configuration) {
|
||||||
|
super(uuid, name, timeout, configuration);
|
||||||
|
|
||||||
|
var dummy1 = new SessionPlayer(new UUID(0, 1), "Dummy #1");
|
||||||
|
var dummy2 = new SessionPlayer(new UUID(0, 2), "Dummy #2");
|
||||||
|
var dummy3 = new SessionPlayer(new UUID(0, 3), "Dummy #3");
|
||||||
|
var dummy4 = new SessionPlayer(new UUID(0, 4), "Dummy #4");
|
||||||
|
getPlayers().put(dummy1.getUuid(), dummy1);
|
||||||
|
getPlayers().put(dummy2.getUuid(), dummy2);
|
||||||
|
getPlayers().put(dummy3.getUuid(), dummy3);
|
||||||
|
getPlayers().put(dummy4.getUuid(), dummy4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void handlePlayerMessage(UUID uuid, PlayerMessage message) {
|
||||||
|
var player = getPlayers().get(uuid);
|
||||||
|
if (player == null) {
|
||||||
|
throw new NackException(NackMessage.PLAYER_NOT_FOUND, "Who are you?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized UUID join(Player player, String name) {
|
||||||
|
if (getGame() != null) {
|
||||||
|
throw new NackException(NackMessage.GAME_ALREADY_STARTED, "Game has already started.");
|
||||||
|
} else if (getPlayers().size() == MAX_PLAYERS) {
|
||||||
|
throw new NackException(NackMessage.SESSION_FULL, "Session is full.");
|
||||||
|
} else if (getPlayers().values().stream().anyMatch(p -> p.getName().equalsIgnoreCase(name))) {
|
||||||
|
throw new NackException(NackMessage.NAME_TAKEN, "Name is already taken.");
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionPlayer sessionPlayer;
|
||||||
|
long i = 0;
|
||||||
|
do {
|
||||||
|
sessionPlayer = new SessionPlayer(new UUID(0, i++), name);
|
||||||
|
} while (getPlayers().putIfAbsent(sessionPlayer.getUuid(), sessionPlayer) != null);
|
||||||
|
sessionPlayer.setPlayer(player);
|
||||||
|
|
||||||
|
notifyJoined(sessionPlayer.toData());
|
||||||
|
Lobby.getInstance().notifyPlayers(new SessionModifiedMessage(toData()));
|
||||||
|
|
||||||
|
return sessionPlayer.getUuid();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void startGame() {}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
for (var player : getPlayers().values()) {
|
||||||
|
try {
|
||||||
|
player.getPlayer().disconnect();
|
||||||
|
} catch (IOException ignored) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyPlayers(ServerMessage message) {
|
||||||
|
super.notifyPlayers(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package eu.jonahbauer.wizard.server.debug;
|
||||||
|
|
||||||
|
import eu.jonahbauer.wizard.common.messages.ParseException;
|
||||||
|
import eu.jonahbauer.wizard.common.messages.observer.ObserverMessage;
|
||||||
|
import eu.jonahbauer.wizard.common.messages.server.NackMessage;
|
||||||
|
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
|
||||||
|
import eu.jonahbauer.wizard.common.model.Configuration;
|
||||||
|
import eu.jonahbauer.wizard.server.Lobby;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.socket.CloseStatus;
|
||||||
|
import org.springframework.web.socket.TextMessage;
|
||||||
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
|
import org.springframework.web.socket.handler.TextWebSocketHandler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@Log4j2
|
||||||
|
@Component
|
||||||
|
@Profile("debug")
|
||||||
|
public class DebugSocketHandler extends TextWebSocketHandler {
|
||||||
|
private final Map<String, DebugSession> sessions = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterConnectionEstablished(@NotNull WebSocketSession session) {
|
||||||
|
var dummySession = Lobby.getInstance().createDebugSession("Debug Session", 10, Configuration.DEFAULT);
|
||||||
|
sessions.put(session.getId(), dummySession);
|
||||||
|
|
||||||
|
log.info("Dummy connection #{} from {}.", session.getId(), session.getRemoteAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleTextMessage(@NotNull WebSocketSession session, @NotNull TextMessage text) throws IOException {
|
||||||
|
var dummySession = sessions.get(session.getId());
|
||||||
|
for (String line : text.getPayload().lines().toArray(String[]::new)) {
|
||||||
|
try {
|
||||||
|
dummySession.notify(ObserverMessage.parse(line));
|
||||||
|
} catch (ParseException e) {
|
||||||
|
try {
|
||||||
|
dummySession.notifyPlayers(ServerMessage.parse(line));
|
||||||
|
} catch (ParseException e2) {
|
||||||
|
var nack = new NackMessage(NackMessage.MALFORMED_MESSAGE,"Could not parse " + text.getPayload() + ".").toString();
|
||||||
|
session.sendMessage(new TextMessage(nack));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterConnectionClosed(@NotNull WebSocketSession session, @NotNull CloseStatus status) {
|
||||||
|
var dummySession = sessions.get(session.getId());
|
||||||
|
dummySession.close();
|
||||||
|
Lobby.getInstance().removeSession(dummySession.getUuid());
|
||||||
|
|
||||||
|
log.info("Dummy connection #{} closed {}.", session.getId(), status);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package eu.jonahbauer.wizard.server.debug;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
|
||||||
|
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Profile("debug")
|
||||||
|
public class DebugWebSocketConfig implements WebSocketConfigurer {
|
||||||
|
|
||||||
|
@Getter(AccessLevel.PRIVATE)
|
||||||
|
private final DebugSocketHandler debugSocketHandler;
|
||||||
|
|
||||||
|
public DebugWebSocketConfig(DebugSocketHandler debugSocketHandler) {
|
||||||
|
this.debugSocketHandler = debugSocketHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerWebSocketHandlers(@NotNull WebSocketHandlerRegistry registry) {
|
||||||
|
registry.addHandler(this.getDebugSocketHandler(), "/debug").setAllowedOrigins("*");
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ 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.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class Player extends Context<ClientState, Player> {
|
public class Player extends Context<ClientState, Player> {
|
||||||
@ -43,6 +44,10 @@ public class Player extends Context<ClientState, Player> {
|
|||||||
shouldBuffer = Response.class;
|
shouldBuffer = Response.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void disconnect() throws IOException {
|
||||||
|
session.close(CloseStatus.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void send(ServerMessage message) {
|
public void send(ServerMessage message) {
|
||||||
synchronized (session) {
|
synchronized (session) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user