diff --git a/server.properties b/server.properties new file mode 100644 index 0000000..90a0856 --- /dev/null +++ b/server.properties @@ -0,0 +1,16 @@ +#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 diff --git a/src/main/java/org/toop/server/backend/TcpServer.java b/src/main/java/org/toop/server/backend/TcpServer.java index 921f493..3bbeedb 100644 --- a/src/main/java/org/toop/server/backend/TcpServer.java +++ b/src/main/java/org/toop/server/backend/TcpServer.java @@ -5,13 +5,14 @@ import org.apache.logging.log4j.Logger; import java.io.*; import java.net.*; +import java.sql.Time; import java.util.concurrent.*; import static java.lang.Thread.sleep; public class TcpServer implements Runnable { - private static final Logger logger = LogManager.getLogger(TcpServer.class); + protected static final Logger logger = LogManager.getLogger(TcpServer.class); private final ExecutorService executor = Executors.newFixedThreadPool(2); private final BlockingQueue receivedQueue = new LinkedBlockingQueue<>(); @@ -19,8 +20,8 @@ public class TcpServer implements Runnable { private final int WAIT_TIME = 500; // MS private final int RETRY_ATTEMPTS = 3; - private int port; - private ServerSocket serverSocket = null; + protected int port; + protected ServerSocket serverSocket = null; private boolean running = true; public TcpServer(int port) throws IOException { @@ -28,6 +29,10 @@ public class TcpServer implements Runnable { this.serverSocket = new ServerSocket(port); } + public boolean isRunning() { + return this.running; + } + @Override public void run() { try { @@ -44,7 +49,19 @@ public class TcpServer implements Runnable { } } - private void startWorkers(Socket clientSocket) { + protected String getNewestCommand() { + try { return receivedQueue.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 void startWorkers(Socket clientSocket) { running = true; try { diff --git a/src/main/java/org/toop/server/backend/tictactoe/TicTacToeServer.java b/src/main/java/org/toop/server/backend/tictactoe/TicTacToeServer.java index ffff076..705977b 100644 --- a/src/main/java/org/toop/server/backend/tictactoe/TicTacToeServer.java +++ b/src/main/java/org/toop/server/backend/tictactoe/TicTacToeServer.java @@ -4,33 +4,78 @@ import org.toop.server.backend.tictactoe.game.TicTacToe; import org.toop.server.backend.TcpServer; import java.io.IOException; +import java.io.ObjectStreamException; import java.net.Socket; +import java.util.ArrayList; public class TicTacToeServer extends TcpServer { - public TicTacToeServer(int port) throws IOException { + + private TicTacToe game; + + public TicTacToeServer(int port, String playerA, String playerB) throws IOException { super(port); + this.game = new TicTacToe(playerA, playerB); } @Override public void run() { try { - logger.info("Server listening on port {}", port); + logger.info("Tic tac toe server listening on port {}", this.port); - while (running) { + while (isRunning()) { Socket clientSocket = this.serverSocket.accept(); logger.info("Connected to client: {}", clientSocket.getInetAddress()); new Thread(() -> this.startWorkers(clientSocket)).start(); + new Thread(() -> this.gameThread()).start(); } } catch (IOException e) { e.printStackTrace(); } } - private void gameThread(String main_character, String opponent_character) { - TicTacToe ticTacToe = new TicTacToe(main_character, opponent_character); + @FunctionalInterface + public interface TicTacToeCommand { + Object execute(TicTacToe game, String[] args); + } + + private TicTacToeCommand parseCommand(String command) { + if (command.isEmpty()) { + try { + wait(250); // TODO: Magic number + return null; + } catch (InterruptedException e) { + logger.error("Interrupted", e); + throw new RuntimeException(e); // TODO: Maybe not throw it. + } + } + + String[] segments = command.split(" "); + if (segments[0].isEmpty()) return null; + + TicTacToeServerCommand commandEnum = TicTacToeServerCommand.getCommand(segments[0]); + switch (commandEnum) { + case MOVE -> { + if (segments.length > 1 && !segments[1].isEmpty()) return null; + try { + int parsedInteger = Integer.parseInt(segments[1]); + if (this.game.validateMove(parsedInteger)) return this.game.playMove(parsedInteger); + }; + } + } + + } + + private void gameThread() { + while (true) { + String command = getNewestCommand(); + command = this.parseCommand(command); + if (command == null) { continue; } + + + // TODO: Game }