mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 02:44:50 +00:00
fix: conflicts
This commit is contained in:
@@ -1,16 +0,0 @@
|
||||
#nl.hanze.newgameserver.GlobalSettings
|
||||
#Mon Sep 15 21:02:16 CEST 2025
|
||||
challenges=true
|
||||
chat=true
|
||||
debugTournament=false
|
||||
gameserver.homepagetext=Welcome to the web interface of the game server.
|
||||
gameserver.port=7789
|
||||
gameserver.tournament.timebetweengames=5
|
||||
gameserver.turntimelimit=10
|
||||
gameserver.welcomemessage=New Game Server [Aplha version]\n(C) Copyright 2023 Hanzehogeschool Groningen
|
||||
jsonwebtokensecret=SuperGeheimeJWTSecretKeyOmTokensteCreaten
|
||||
logging.file.name=./gameserver.log
|
||||
passwordhash=$2a$10$Yze2Ddu931DdzLQ3J08qGexwsp7dK2cJHFuA8YrZWS2RNyM5IkEeS
|
||||
server.port=8081
|
||||
shuffleWhiteBlack=true
|
||||
subscribe=true
|
||||
@@ -21,49 +21,21 @@ public class Main {
|
||||
|
||||
public static void main(String[] args) throws ExecutionException, InterruptedException, IOException {
|
||||
|
||||
// TcpServer server = new TcpServer(5001);
|
||||
// Thread serverThread = new Thread(server);
|
||||
// serverThread.start();
|
||||
|
||||
initSystems();
|
||||
|
||||
GlobalEventBus.post(new Events.ServerEvents.StartServer("5001"));
|
||||
CompletableFuture<String> serverIdFuture = new CompletableFuture<>();
|
||||
GlobalEventBus.post(new Events.ServerEvents.StartServerRequest("5001", "tictactoe", serverIdFuture));
|
||||
String serverId = serverIdFuture.get();
|
||||
|
||||
CompletableFuture<String> future = new CompletableFuture<>();
|
||||
GlobalEventBus.post(new Events.ServerEvents.StartConnectionRequest("127.0.0.1", "5001", future));
|
||||
String serverId = future.get();
|
||||
CompletableFuture<String> connectionIdFuture = new CompletableFuture<>();
|
||||
GlobalEventBus.post(new Events.ServerEvents.StartConnectionRequest("127.0.0.1", "5001", connectionIdFuture));
|
||||
String connectionId = connectionIdFuture.get();
|
||||
|
||||
// for (int i = 0; i < 1; i++) {
|
||||
// Thread thread = new Thread(() -> {
|
||||
//// logger.info("Server ID: {}", serverId);
|
||||
// GlobalEventBus.post(new Events.ServerEvents.Command(serverId, "HELP", "TEST"));
|
||||
// });
|
||||
// thread.start();
|
||||
// }
|
||||
CompletableFuture<String> ticTacToeGame = new CompletableFuture<>();
|
||||
GlobalEventBus.post(new Events.ServerEvents.CreateTicTacToeGameRequest(serverId, "John", "Pim", ticTacToeGame));
|
||||
String ticTacToeGameId = ticTacToeGame.get();
|
||||
|
||||
GlobalEventBus.post(new Events.ServerEvents.Command(serverId, "HELP", "TEST"));
|
||||
|
||||
GlobalEventBus.post(new Events.ServerEvents.ForceCloseAllConnections());
|
||||
GlobalEventBus.post(new Events.ServerEvents.ForceCloseAllServers());
|
||||
|
||||
//
|
||||
// CompletableFuture<String> future2 = new CompletableFuture<>();
|
||||
// GlobalEventBus.post(new Events.ServerEvents.StartConnectionRequest("127.0.0.1", "5001", future2));
|
||||
// String serverId2 = future.get();
|
||||
// logger.info("Server ID: {}", serverId2);
|
||||
// GlobalEventBus.post(new Events.ServerEvents.Command(serverId2, "HELP", "TEST2"));
|
||||
|
||||
// GlobalEventBus.post(new Events.ServerEvents.StartConnection("127.0.0.1", "5001"));
|
||||
|
||||
|
||||
// Server.startNew("127.0.0.1", "5001");
|
||||
// Testsss.start(""); // Used for testing server.
|
||||
// Window.start("");
|
||||
|
||||
// CompletableFuture<String> future6 = new CompletableFuture<>();
|
||||
// GlobalEventBus.post(new Events.ServerEvents.RequestsAllConnections(future6));
|
||||
// String serverConnections = future6.get();
|
||||
// logger.info("Running connections: {}", serverConnections);
|
||||
GlobalEventBus.post(new Events.ServerEvents.RunTicTacToeGame(serverId, ticTacToeGameId));
|
||||
|
||||
ConsoleGui console = new ConsoleGui();
|
||||
GameBase.State state = GameBase.State.INVALID;
|
||||
|
||||
@@ -84,12 +84,18 @@ public class Events implements IEvents {
|
||||
|
||||
public record ForceCloseAllServers() {}
|
||||
|
||||
public record StartServer(String port) {}
|
||||
public record StartServer(String port, String gameType) {}
|
||||
|
||||
public record StartServerRequest(String port, CompletableFuture<String> future) {}
|
||||
public record StartServerRequest(String port, String gameType, CompletableFuture<String> future) {}
|
||||
|
||||
public record ServerStarted(String uuid, String port) {}
|
||||
|
||||
public record CreateTicTacToeGameRequest(String serverUuid, String playerA, String playerB, CompletableFuture<String> future) {}
|
||||
|
||||
public record RunTicTacToeGame(String serverUuid, String gameUuid) {}
|
||||
|
||||
public record EndTicTacToeGame(String serverUuid, String gameUuid) {}
|
||||
|
||||
/**
|
||||
*
|
||||
* Triggers starting a server connection.
|
||||
@@ -109,6 +115,8 @@ public class Events implements IEvents {
|
||||
*/
|
||||
public record StartConnectionRequest(String ip, String port, CompletableFuture<String> future) {}
|
||||
|
||||
// public record StartGameConnectionRequest(String ip, String port, CompletableFuture<String> future) {}
|
||||
|
||||
/**
|
||||
* Triggers when a connection to a server is established.
|
||||
*
|
||||
|
||||
@@ -12,10 +12,10 @@ public abstract class GameBase {
|
||||
public static char EMPTY = '-';
|
||||
|
||||
protected int size;
|
||||
protected char[] grid;
|
||||
public char[] grid;
|
||||
|
||||
protected Player[] players;
|
||||
protected int currentPlayer;
|
||||
public int currentPlayer;
|
||||
|
||||
public GameBase(int size, Player player1, Player player2) {
|
||||
this.size = size;
|
||||
@@ -43,18 +43,4 @@ public abstract class GameBase {
|
||||
public Player getCurrentPlayer() { return players[currentPlayer]; }
|
||||
|
||||
public abstract State play(int index);
|
||||
|
||||
/**
|
||||
* For AI use only. Does not validate.
|
||||
*/
|
||||
public void setGridAt(int index, char move) {
|
||||
grid[index] = move;
|
||||
}
|
||||
|
||||
/**
|
||||
* For AI use only. Does not validate.
|
||||
*/
|
||||
public void setCurrentPlayer(int player) {
|
||||
currentPlayer = player;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ public class MinMaxTicTacToe {
|
||||
int bestMove = 10; // set bestmove to something impossible
|
||||
|
||||
// simulate all possible moves on the field
|
||||
for (int i = 0; i < game.getGrid().length; i++) {
|
||||
for (int i = 0; i < game.grid.length; i++) {
|
||||
if (game.validateMove(i)) { // check if the move is legal here
|
||||
TicTacToe copyGame = game.copyBoard(); // make a copy of the game
|
||||
GameBase.State result = copyGame.play(i); // play a move on the copy board
|
||||
@@ -58,7 +58,7 @@ public class MinMaxTicTacToe {
|
||||
|
||||
else {
|
||||
boolean empty = false;
|
||||
for (char cell : game.getGrid()) { // else, look at draw conditions. we check per cell if it's empty or not
|
||||
for (char cell : game.grid) { // else, look at draw conditions. we check per cell if it's empty or not
|
||||
if (cell == ' ') {
|
||||
empty = true; // if a thing is empty, set to true
|
||||
break; // break the loop
|
||||
@@ -71,7 +71,7 @@ public class MinMaxTicTacToe {
|
||||
|
||||
if (maximizing) { // it's the maximizing players turn, the AI
|
||||
int bestVal = -100; // set the value to lowest as possible
|
||||
for (int i = 0; i < game.getGrid().length; i++) { // loop through the grid
|
||||
for (int i = 0; i < game.grid.length; i++) { // loop through the grid
|
||||
if (game.validateMove(i)) {
|
||||
TicTacToe copyGame = game.copyBoard();
|
||||
copyGame.play(i); // play the move on a copy board
|
||||
@@ -84,7 +84,7 @@ public class MinMaxTicTacToe {
|
||||
|
||||
else { // it's the minimizing players turn, the player
|
||||
int bestVal = 100; // set the value to the highest possible
|
||||
for (int i = 0; i < game.getGrid().length; i++) { // loop through the grid
|
||||
for (int i = 0; i < game.grid.length; i++) { // loop through the grid
|
||||
if (game.validateMove(i)) {
|
||||
TicTacToe copyGame = game.copyBoard();
|
||||
copyGame.play(i); // play the move on a copy board
|
||||
|
||||
@@ -1,15 +1,48 @@
|
||||
package org.toop.game.tictactoe;
|
||||
|
||||
import org.toop.game.*;
|
||||
import org.toop.server.backend.tictactoe.*;
|
||||
|
||||
public class TicTacToe extends GameBase {
|
||||
private int movesLeft;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public class TicTacToe extends GameBase implements Runnable {
|
||||
public Thread gameThread;
|
||||
public BlockingQueue<ParsedCommand> commandQueue = new LinkedBlockingQueue<>();
|
||||
public BlockingQueue<String> sendQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
public int movesLeft;
|
||||
|
||||
public TicTacToe(String player1, String player2) {
|
||||
super(3, new Player(player1, 'X'), new Player(player2, 'O'));
|
||||
movesLeft = size * size;
|
||||
}
|
||||
|
||||
public void addCommandToQueue(ParsedCommand command) {
|
||||
commandQueue.add(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.gameThread = new Thread(this::gameThread);
|
||||
this.gameThread.start();
|
||||
}
|
||||
|
||||
private void gameThread() {
|
||||
while (true) {
|
||||
// String command = getNewestCommand();
|
||||
// command = this.parseCommand(command).toString();
|
||||
// if (command == null) { continue; }
|
||||
|
||||
if (commandQueue.poll() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: Game use the commandQueue to get the commands.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public State play(int index) {
|
||||
if (!validateMove(index)) {
|
||||
@@ -74,14 +107,14 @@ public class TicTacToe extends GameBase {
|
||||
movesLeft--;
|
||||
}
|
||||
|
||||
public TicTacToe copyBoard() {
|
||||
/**
|
||||
* This method copies the board, mainly for AI use.
|
||||
*/
|
||||
TicTacToe clone = new TicTacToe(players[0].name(), players[1].name());
|
||||
System.arraycopy(this.grid, 0, clone.grid, 0, this.grid.length);
|
||||
clone.movesLeft = this.movesLeft;
|
||||
clone.currentPlayer = this.currentPlayer;
|
||||
return clone;
|
||||
}
|
||||
public TicTacToe copyBoard() {
|
||||
/**
|
||||
* This method copies the board, mainly for AI use.
|
||||
*/
|
||||
TicTacToe clone = new TicTacToe(players[0].name(), players[1].name());
|
||||
System.arraycopy(this.grid, 0, clone.grid, 0, this.grid.length);
|
||||
clone.movesLeft = this.movesLeft;
|
||||
clone.currentPlayer = this.currentPlayer;
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,11 @@ import org.toop.eventbus.GlobalEventBus;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.toop.server.backend.tictactoe.TicTacToeServer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -29,12 +31,23 @@ public class ServerManager {
|
||||
GlobalEventBus.subscribeAndRegister(Events.ServerEvents.StartServerRequest.class, this::handleStartServerRequest);
|
||||
GlobalEventBus.subscribeAndRegister(Events.ServerEvents.StartServer.class, this::handleStartServer);
|
||||
GlobalEventBus.subscribeAndRegister(Events.ServerEvents.ForceCloseAllServers.class, _ -> shutdownAll());
|
||||
GlobalEventBus.subscribeAndRegister(Events.ServerEvents.CreateTicTacToeGameRequest.class, this::handleStartTicTacToeGameOnAServer);
|
||||
GlobalEventBus.subscribeAndRegister(Events.ServerEvents.RunTicTacToeGame.class, this::handleRunTicTacToeGameOnAServer);
|
||||
GlobalEventBus.subscribeAndRegister(Events.ServerEvents.EndTicTacToeGame.class, this::handleEndTicTacToeGameOnAServer);
|
||||
}
|
||||
|
||||
private String startServer(String port) {
|
||||
private String startServer(String port, String gameType) {
|
||||
String serverId = UUID.randomUUID().toString();
|
||||
gameType = gameType.toLowerCase();
|
||||
try {
|
||||
TcpServer server = new TcpServer(Integer.parseInt(port));
|
||||
TcpServer server = null;
|
||||
if (Objects.equals(gameType, "tictactoe")) {
|
||||
server = new TicTacToeServer(Integer.parseInt(port));
|
||||
}
|
||||
else {
|
||||
logger.error("Manager could not create a TcpServer for {}", gameType);
|
||||
return null;
|
||||
}
|
||||
this.servers.put(serverId, server);
|
||||
new Thread(server, "Server-" + serverId).start();
|
||||
logger.info("Connected to server {} at {}", serverId, port);
|
||||
@@ -46,16 +59,41 @@ public class ServerManager {
|
||||
}
|
||||
|
||||
private void handleStartServerRequest(Events.ServerEvents.StartServerRequest request) {
|
||||
request.future().complete(this.startServer(request.port())); // TODO: Maybe post StartServer event.
|
||||
request.future().complete(this.startServer(request.port(), request.gameType())); // TODO: Maybe post StartServer event.
|
||||
}
|
||||
|
||||
private void handleStartServer(Events.ServerEvents.StartServer event) {
|
||||
GlobalEventBus.post(new Events.ServerEvents.ServerStarted(
|
||||
this.startServer(event.port()),
|
||||
this.startServer(event.port(), event.gameType()),
|
||||
event.port()
|
||||
));
|
||||
}
|
||||
|
||||
private void handleStartTicTacToeGameOnAServer(Events.ServerEvents.CreateTicTacToeGameRequest event) {
|
||||
TicTacToeServer serverThing = (TicTacToeServer) this.servers.get(event.serverUuid());
|
||||
String gameId = null;
|
||||
if (serverThing != null) {
|
||||
try {
|
||||
gameId = serverThing.newGame(event.playerA(), event.playerB());
|
||||
logger.info("Created game on server: {}", event.serverUuid());
|
||||
}
|
||||
catch (Exception e) { // TODO: Error handling
|
||||
logger.error("Could not create game on server: {}", event.serverUuid());
|
||||
}
|
||||
} else { logger.warn("Could not find server: {}", event.serverUuid()); }
|
||||
event.future().complete(gameId);
|
||||
}
|
||||
|
||||
private void handleRunTicTacToeGameOnAServer(Events.ServerEvents.RunTicTacToeGame event) {
|
||||
TicTacToeServer gameServer = (TicTacToeServer) this.servers.get(event.serverUuid());
|
||||
gameServer.runGame(event.gameUuid());
|
||||
}
|
||||
|
||||
private void handleEndTicTacToeGameOnAServer(Events.ServerEvents.EndTicTacToeGame event) {
|
||||
TicTacToeServer gameServer = (TicTacToeServer) this.servers.get(event.serverUuid());
|
||||
gameServer.endGame(event.gameUuid());
|
||||
}
|
||||
|
||||
private void getAllServers(Events.ServerEvents.RequestsAllServers request) {
|
||||
ArrayList<TcpServer> a = new ArrayList<>(this.servers.values());
|
||||
request.future().complete(a.toString());
|
||||
|
||||
@@ -2,23 +2,26 @@ package org.toop.server.backend;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.toop.server.backend.tictactoe.ParsedCommand;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.sql.Time;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import static java.lang.Thread.sleep;
|
||||
|
||||
public class TcpServer implements Runnable {
|
||||
|
||||
protected static final Logger logger = LogManager.getLogger(TcpServer.class);
|
||||
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(2);
|
||||
private final BlockingQueue<String> receivedQueue = new LinkedBlockingQueue<>();
|
||||
private final BlockingQueue<String> sendQueue = new LinkedBlockingQueue<>();
|
||||
private final int WAIT_TIME = 500; // MS
|
||||
private final int RETRY_ATTEMPTS = 3;
|
||||
public final BlockingQueue<String> receivedQueue = new LinkedBlockingQueue<>();
|
||||
public final BlockingQueue<ParsedCommand> commandQueue = new LinkedBlockingQueue<>();
|
||||
public final BlockingQueue<String> sendQueue = new LinkedBlockingQueue<>();
|
||||
public final Map<Socket, String> knownPlayers = new HashMap<>();
|
||||
public final Map<String, String> playersGames = new HashMap<>();
|
||||
public final int WAIT_TIME = 500; // MS
|
||||
public final int RETRY_ATTEMPTS = 3;
|
||||
|
||||
protected int port;
|
||||
protected ServerSocket serverSocket = null;
|
||||
@@ -49,17 +52,37 @@ public class TcpServer implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
protected String getNewestCommand() {
|
||||
try { return receivedQueue.poll(this.WAIT_TIME, TimeUnit.MILLISECONDS); }
|
||||
public void runGame() {}
|
||||
|
||||
public void endGame() {}
|
||||
|
||||
public void newGame() {}
|
||||
|
||||
protected String sendServerMessage() {
|
||||
try { return sendQueue.poll(this.WAIT_TIME, TimeUnit.MILLISECONDS); }
|
||||
catch (InterruptedException e) {
|
||||
logger.error("Interrupted", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected void sendMessage(String message) throws InterruptedException {
|
||||
sendQueue.put(message);
|
||||
protected ParsedCommand getNewestCommand() {
|
||||
try {
|
||||
String rec = receivedQueue.poll(this.WAIT_TIME, TimeUnit.MILLISECONDS);
|
||||
if (rec != null) {
|
||||
return new ParsedCommand(rec);
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
logger.error("Interrupted", e);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
//
|
||||
// protected void sendMessage(String message) throws InterruptedException {
|
||||
// sendQueue.put(message);
|
||||
// }
|
||||
|
||||
protected void startWorkers(Socket clientSocket) {
|
||||
running = true;
|
||||
@@ -95,11 +118,6 @@ public class TcpServer implements Runnable {
|
||||
new Thread(() -> {
|
||||
for (int i = 0; i < this.RETRY_ATTEMPTS; i++) {
|
||||
if (this.receivedQueue.offer(finalMessage)) break;
|
||||
try {
|
||||
sleep(this.WAIT_TIME);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package org.toop.server.backend;
|
||||
|
||||
import org.toop.eventbus.Events;
|
||||
import org.toop.eventbus.GlobalEventBus;
|
||||
|
||||
public class Testsss extends Thread {
|
||||
|
||||
public Testsss() {}
|
||||
|
||||
// public void run() {
|
||||
// while (true) {
|
||||
// try {
|
||||
// sleep(100);
|
||||
// GlobalEventBus.post(new Events.ServerEvents.command("HELP", "TEST"));
|
||||
// sleep(1000);
|
||||
// GlobalEventBus.post(new Events.ServerEvents.ChangeConnection("127.0.0.1", "5001"));
|
||||
// } catch (InterruptedException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
public static void start(String keepEmpty) {
|
||||
new Testsss().start();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package org.toop.server.backend.tictactoe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ParsedCommand {
|
||||
public TicTacToeServerCommand command;
|
||||
public ArrayList<Object> arguments;
|
||||
public boolean isValidCommand;
|
||||
public boolean isServerCommand;
|
||||
public TicTacToeServerMessage returnMessage;
|
||||
public String errorMessage;
|
||||
public String originalCommand;
|
||||
|
||||
public ParsedCommand(String receivedCommand) {
|
||||
|
||||
if (receivedCommand.isEmpty()) {
|
||||
this.command = null;
|
||||
this.arguments = null;
|
||||
this.isValidCommand = false;
|
||||
this.isServerCommand = true;
|
||||
this.returnMessage = TicTacToeServerMessage.ERR;
|
||||
this.errorMessage = "The received command is empty";
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
}
|
||||
|
||||
String[] segments = receivedCommand.split(" ");
|
||||
if (segments[0].isEmpty()) {
|
||||
this.command = null;
|
||||
this.arguments = null;
|
||||
this.isValidCommand = false;
|
||||
this.isServerCommand = true;
|
||||
this.returnMessage = TicTacToeServerMessage.ERR;
|
||||
this.errorMessage = "The received command is empty or couldn't be split";
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
}
|
||||
|
||||
TicTacToeServerCommand commandEnum = TicTacToeServerCommand.getCommand(segments[0]);
|
||||
|
||||
switch (commandEnum) {
|
||||
case MOVE -> {
|
||||
if (segments.length == 2 && !segments[1].isEmpty()) {
|
||||
this.command = commandEnum;
|
||||
this.arguments = new ArrayList<>(1);
|
||||
this.arguments.add(segments[1]);
|
||||
this.returnMessage = TicTacToeServerMessage.OK;
|
||||
this.isValidCommand = true;
|
||||
this.isServerCommand = false;
|
||||
this.errorMessage = null;
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
}
|
||||
}
|
||||
case MESSAGE -> {
|
||||
if (segments.length == 3 && !segments[2].isEmpty()) {
|
||||
this.command = commandEnum;
|
||||
this.arguments = new ArrayList<>(2);
|
||||
this.arguments.add(segments[2]);
|
||||
this.returnMessage = TicTacToeServerMessage.OK;
|
||||
this.isValidCommand = true;
|
||||
this.isServerCommand = true;
|
||||
this.errorMessage = null;
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
}
|
||||
}
|
||||
case CHALLENGE -> {
|
||||
if (!segments[1].isEmpty() && segments[1].equals("accept") &&
|
||||
!segments[2].isEmpty()) {
|
||||
this.command = commandEnum;
|
||||
this.arguments = new ArrayList<>(2);
|
||||
this.arguments.add(segments[1]);
|
||||
this.arguments.add(segments[2]); // TODO: Needs to be a number.
|
||||
this.returnMessage = TicTacToeServerMessage.OK;
|
||||
this.isValidCommand = true;
|
||||
this.isServerCommand = true;
|
||||
this.errorMessage = null;
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
} else {
|
||||
this.command = commandEnum;
|
||||
this.arguments = null;
|
||||
this.returnMessage = TicTacToeServerMessage.ERR;
|
||||
this.isValidCommand = false;
|
||||
this.isServerCommand = true;
|
||||
this.errorMessage = "The challenge was not parsable";
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
}
|
||||
}
|
||||
case LOGIN -> { // TODO: Challenge needs to accept different game types later.
|
||||
if (!segments[1].isEmpty()) {
|
||||
this.command = commandEnum;
|
||||
this.arguments = new ArrayList<>(1);
|
||||
this.arguments.add(segments[1]);
|
||||
this.returnMessage = TicTacToeServerMessage.OK;
|
||||
this.isValidCommand = true;
|
||||
this.isServerCommand = true;
|
||||
this.errorMessage = null;
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
} else {
|
||||
this.command = commandEnum;
|
||||
this.arguments = null;
|
||||
this.returnMessage = TicTacToeServerMessage.ERR;
|
||||
this.isValidCommand = false;
|
||||
this.isServerCommand = true;
|
||||
this.errorMessage = "The received name is empty or couldn't be understood";
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// case GET -> { // TODO: Get needs to accept different game types later. And get the players
|
||||
//
|
||||
// }
|
||||
case BYE, DISCONNECT, LOGOUT, QUIT, EXIT, FORFEIT, SUBSCRIBE -> {
|
||||
this.command = commandEnum;
|
||||
this.arguments = null;
|
||||
this.returnMessage = TicTacToeServerMessage.OK;
|
||||
this.isValidCommand = true;
|
||||
this.isServerCommand = true;
|
||||
this.errorMessage = null;
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
}
|
||||
case null, default -> {
|
||||
this.command = null;
|
||||
this.arguments = null;
|
||||
this.returnMessage = TicTacToeServerMessage.ERR;
|
||||
this.isValidCommand = false;
|
||||
this.isServerCommand = true;
|
||||
this.errorMessage = segments[0] + " is not a supported command";
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// public ParsedCommand parseCommand(String command) {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -1,22 +1,26 @@
|
||||
package org.toop.server.backend.tictactoe;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.toop.game.tictactoe.*;
|
||||
import org.toop.server.backend.TcpServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class TicTacToeServer extends TcpServer {
|
||||
|
||||
private TicTacToe game;
|
||||
protected static final Logger logger = LogManager.getLogger(TicTacToeServer.class);
|
||||
/**
|
||||
* Map of gameId -> Game instances
|
||||
*/
|
||||
private final Map<String, TicTacToe> games = new ConcurrentHashMap<>();
|
||||
|
||||
public TicTacToeServer(int port, String playerA, String playerB) throws IOException {
|
||||
public TicTacToeServer(int port) throws IOException {
|
||||
super(port);
|
||||
this.game = new TicTacToe(playerA, playerB);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -29,109 +33,75 @@ public class TicTacToeServer extends TcpServer {
|
||||
logger.info("Connected to client: {}", clientSocket.getInetAddress());
|
||||
|
||||
new Thread(() -> this.startWorkers(clientSocket)).start();
|
||||
new Thread(() -> this.gameThread()).start();
|
||||
new Thread(this::gameManagerThread).start();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ParsedCommand {
|
||||
public TicTacToeServerCommand command;
|
||||
public ArrayList<Object> arguments;
|
||||
public boolean isValidCommand;
|
||||
public TicTacToeServerMessage returnMessage;
|
||||
public String errorMessage;
|
||||
public String originalCommand;
|
||||
|
||||
ParsedCommand(String receivedCommand) {
|
||||
|
||||
if (receivedCommand.isEmpty()) {
|
||||
this.command = null;
|
||||
this.arguments = null;
|
||||
this.isValidCommand = false;
|
||||
this.returnMessage = TicTacToeServerMessage.ERR;
|
||||
this.errorMessage = "The received command is empty";
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
@Override
|
||||
protected ParsedCommand getNewestCommand() {
|
||||
try {
|
||||
String rec = receivedQueue.poll(this.WAIT_TIME, TimeUnit.MILLISECONDS);
|
||||
if (rec != null) {
|
||||
return new ParsedCommand(rec);
|
||||
}
|
||||
|
||||
String[] segments = receivedCommand.split(" ");
|
||||
if (segments[0].isEmpty()) {
|
||||
this.command = null;
|
||||
this.arguments = null;
|
||||
this.isValidCommand = false;
|
||||
this.returnMessage = TicTacToeServerMessage.ERR;
|
||||
this.errorMessage = "The received command is empty or couldn't be split";
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
};
|
||||
|
||||
TicTacToeServerCommand commandEnum = TicTacToeServerCommand.getCommand(segments[0]);
|
||||
switch (commandEnum) {
|
||||
case MOVE -> {
|
||||
if (segments.length == 2 && !segments[1].isEmpty()) {
|
||||
this.command = commandEnum;
|
||||
this.arguments = new ArrayList<Object>(1);
|
||||
this.arguments.add(segments[1]);
|
||||
this.returnMessage = TicTacToeServerMessage.OK;
|
||||
this.isValidCommand = true;
|
||||
this.errorMessage = null;
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
}
|
||||
}
|
||||
case FORFEIT -> {
|
||||
this.command = commandEnum;
|
||||
this.arguments = null;
|
||||
this.returnMessage = TicTacToeServerMessage.OK;
|
||||
this.isValidCommand = true;
|
||||
this.errorMessage = null;
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
}
|
||||
case MESSAGE -> {
|
||||
if (segments.length == 3 && !segments[2].isEmpty()) {
|
||||
this.command = commandEnum;
|
||||
this.arguments = new ArrayList<Object>(2);
|
||||
this.arguments.add(segments[2]);
|
||||
this.returnMessage = TicTacToeServerMessage.OK;
|
||||
this.isValidCommand = true;
|
||||
this.errorMessage = null;
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
}
|
||||
}
|
||||
case BYE, DISCONNECT, LOGOUT, QUIT, EXIT -> {
|
||||
this.command = commandEnum;
|
||||
this.arguments = null;
|
||||
this.returnMessage = TicTacToeServerMessage.OK;
|
||||
this.isValidCommand = true;
|
||||
this.errorMessage = null;
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.command = command;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
}
|
||||
|
||||
private ParsedCommand parseCommand(String command) {
|
||||
catch (InterruptedException e) {
|
||||
logger.error("Interrupted", e);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void gameThread() {
|
||||
|
||||
|
||||
while (true) {
|
||||
String command = getNewestCommand();
|
||||
command = this.parseCommand(command).toString();
|
||||
if (command == null) { continue; }
|
||||
|
||||
// TODO: Game
|
||||
public void gameManagerThread() {
|
||||
while (true) { // TODO: Very heavy on thread
|
||||
try {
|
||||
synchronized (this) {
|
||||
wait(250);
|
||||
} // Fixes current thread is not owner.
|
||||
} catch (InterruptedException e) {
|
||||
logger.error("Interrupted", e);
|
||||
}
|
||||
ParsedCommand command = getNewestCommand();
|
||||
if (command != null && !command.isServerCommand) {
|
||||
TicTacToe testGame = games.values().iterator().next(); // TODO: Is to get first for testing, must be done a different way later.
|
||||
testGame.addCommandToQueue(command);
|
||||
logger.info("Added command to the game queue: {}", command);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String newGame(String playerA, String playerB) {
|
||||
logger.info("Creating a new game: {} vs {}", playerA, playerB);
|
||||
String gameId = UUID.randomUUID().toString();
|
||||
TicTacToe game = new TicTacToe(playerA, playerB);
|
||||
this.games.put(gameId, game);
|
||||
// this.knownPlayers.put(sockA, playerA); // TODO: For remembering players and validation.
|
||||
// this.knownPlayers.put(sockB, playerB);
|
||||
// this.playersGames.put(playerA, gameId);
|
||||
// this.playersGames.put(playerB, gameId);
|
||||
logger.info("Created a new game: {}. {} vs {}", gameId, playerA, playerB);
|
||||
return gameId;
|
||||
}
|
||||
|
||||
public void runGame(String gameId) {
|
||||
TicTacToe game = this.games.get(gameId);
|
||||
game.run();
|
||||
logger.info("Running game: {}, players: {}", gameId, game.getPlayers());
|
||||
}
|
||||
|
||||
public void endGame(String gameId) {
|
||||
TicTacToe game = this.games.get(gameId);
|
||||
this.games.remove(gameId);
|
||||
// this.knownPlayers.put(sockA, playerA); // TODO: Remove players when game is done.
|
||||
// this.knownPlayers.put(sockB, playerB);
|
||||
// this.playersGames.put(playerA, gameId);
|
||||
// this.playersGames.put(playerB, gameId);
|
||||
logger.info("Ended game: {}", gameId);
|
||||
// TODO: Multithreading, close game in a graceful matter, etc.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,11 +12,10 @@
|
||||
// // Fill the board
|
||||
// for (int i = 0; i < board.length(); i++) {
|
||||
// char c = board.charAt(i);
|
||||
// game.play(i);
|
||||
// game.setGridAt(i, c);
|
||||
// if (c != ' ') game.decrementMovesLeft();
|
||||
// game.grid[i] = c;
|
||||
// if (c != ' ') game.movesLeft--;
|
||||
// }
|
||||
// game.setCurrentPlayer(currentPlayer);
|
||||
// game.currentPlayer = currentPlayer;
|
||||
// return game;
|
||||
// }
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user