diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml index 75d7be8..3be6285 100644 --- a/.idea/uiDesigner.xml +++ b/.idea/uiDesigner.xml @@ -119,9 +119,12 @@ + + + - \ No newline at end of file diff --git a/img/background.jpg b/img/background.jpg new file mode 100644 index 0000000..0e5a01f Binary files /dev/null and b/img/background.jpg differ diff --git a/src/main/java/org/toop/Main.java b/src/main/java/org/toop/Main.java index e7866b3..01bed37 100644 --- a/src/main/java/org/toop/Main.java +++ b/src/main/java/org/toop/Main.java @@ -1,7 +1,6 @@ package org.toop; -import org.apache.logging.log4j.Level; -import org.toop.UI.GameSelectorWindow; +import org.toop.UI.LocalServerSelector; import org.toop.eventbus.EventRegistry; import org.toop.eventbus.Events; import org.toop.eventbus.GlobalEventBus; @@ -9,9 +8,7 @@ import org.toop.server.backend.ServerManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; -import org.toop.server.backend.tictactoe.TicTacToeServer; import org.toop.server.frontend.ConnectionManager; -import org.toop.server.frontend.TcpClient; import java.util.concurrent.ExecutionException; @@ -20,7 +17,8 @@ public class Main { private static boolean running = false; public static void main(String[] args) throws ExecutionException, InterruptedException { - Logging.disableAllLogs(); +// Logging.disableAllLogs(); + Logging.disableLogsForClass(EventRegistry.class); // Logging.enableLogsForClass(ServerManager.class, Level.ALL); // Logging.enableLogsForClass(TicTacToeServer.class, Level.ALL); // Logging.enableLogsForClass(TcpClient.class, Level.ALL); @@ -28,33 +26,17 @@ public class Main { initSystems(); registerEvents(); - /* - Window window = Window.setup(Window.API.GLFW, "Test", new Window.Size(1280, 720)); - Renderer renderer = Renderer.setup(Renderer.API.OPENGL); +// JFrame frame = new JFrame("Server Settings"); +// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); +// frame.setSize(800, 600); +// frame.setLocationRelativeTo(null); +// frame.setVisible(true); - if (!initEvents()) { - throw new RuntimeException("A event could not be initialized"); - } + javax.swing.SwingUtilities.invokeLater(LocalServerSelector::new); - TcpServer server = new TcpServer(5001); - Thread serverThread = new Thread(server); - serverThread.start(); - Server.start("127.0.0.1", "5001"); - // Testsss.start(""); // Used for testing server. - Window.start(""); - */ - -// ConsoleGui console = new ConsoleGui(); -// -// do { -// console.print(); -// } while (console.next()); -// -// console.print(); - - new Thread(() -> { - GameSelectorWindow gameSelectorWindow = new GameSelectorWindow(); - }).start(); +// new Thread(() -> { +// LocalServerSelector window = new LocalServerSelector(); +// }).start(); } diff --git a/src/main/java/org/toop/UI/BackgroundPanel.java b/src/main/java/org/toop/UI/BackgroundPanel.java new file mode 100644 index 0000000..4bd1caf --- /dev/null +++ b/src/main/java/org/toop/UI/BackgroundPanel.java @@ -0,0 +1,21 @@ +package org.toop.UI; + +import javax.swing.*; +import java.awt.*; + +public class BackgroundPanel extends JPanel { + private Image backgroundImage; + + public void setBackgroundImage(Image image) { + this.backgroundImage = image; + repaint(); + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + if (backgroundImage != null) { + g.drawImage(backgroundImage, 0, 0, getWidth(), getHeight(), this); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/toop/UI/LocalGameSelector.form b/src/main/java/org/toop/UI/LocalGameSelector.form new file mode 100644 index 0000000..217c38a --- /dev/null +++ b/src/main/java/org/toop/UI/LocalGameSelector.form @@ -0,0 +1,37 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/main/java/org/toop/UI/LocalGameSelector.java b/src/main/java/org/toop/UI/LocalGameSelector.java new file mode 100644 index 0000000..f4ed81b --- /dev/null +++ b/src/main/java/org/toop/UI/LocalGameSelector.java @@ -0,0 +1,139 @@ +package org.toop.UI; + +import jdk.jfr.Event; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.toop.Main; +import org.toop.eventbus.Events; +import org.toop.eventbus.GlobalEventBus; + +import javax.swing.*; +import java.awt.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; + +public class LocalGameSelector extends JFrame { + private static final Logger logger = LogManager.getLogger(LocalGameSelector.class); + + private JPanel panel1; + private JComboBox gameSelectionComboBox; + private JButton startGame; + private JComboBox playerTypeSelectionBox; + + private JPanel cards; // CardLayout panel + private CardLayout cardLayout; + + private UIGameBoard tttBoard; + + public LocalGameSelector() { + setTitle("Local Game Selector"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setSize(1920, 1080); + setLocationRelativeTo(null); + + // Setup CardLayout + cardLayout = new CardLayout(); + cards = new JPanel(cardLayout); + setContentPane(cards); + + // --- Main menu panel --- + panel1 = new JPanel(); + panel1.setLayout(new FlowLayout()); + gameSelectionComboBox = new JComboBox<>(); + gameSelectionComboBox.addItem("Tic Tac Toe"); + gameSelectionComboBox.addItem("Reversi"); + + playerTypeSelectionBox = new JComboBox<>(); + playerTypeSelectionBox.addItem("Player vs Player"); + playerTypeSelectionBox.addItem("Player vs AI"); + playerTypeSelectionBox.addItem("AI vs Player"); + + panel1.add(gameSelectionComboBox); + panel1.add(playerTypeSelectionBox); + + startGame = new JButton("Start Game"); + panel1.add(startGame); + + cards.add(panel1, "MainMenu"); + + // Start button action + startGame.addActionListener(e -> startGameClicked()); + + setVisible(true); + } + + private String createServer() { + CompletableFuture serverIdFuture = new CompletableFuture<>(); + GlobalEventBus.post(new Events.ServerEvents.StartServerRequest("5001", "tictactoe", serverIdFuture)); // TODO: what if 5001 is in use + try { + return serverIdFuture.get(); + } catch (Exception e) { + logger.error("Error getting server ID", e); + } + return null; + } + + private String createConnection() { + CompletableFuture connectionIdFuture = new CompletableFuture<>(); + GlobalEventBus.post(new Events.ServerEvents.StartConnectionRequest("127.0.0.1", "5001", connectionIdFuture)); // TODO: what if server couldn't be started with port. + try { + return connectionIdFuture.get(); + } catch (InterruptedException | ExecutionException e) { + logger.error("Error getting connection ID", e); + } + return null; + } + + private void startGameClicked() { + String playerTypes = (String) playerTypeSelectionBox.getSelectedItem(); + String selectedGame = (String) gameSelectionComboBox.getSelectedItem(); + + String serverId = createServer(); + String connectionId = createConnection(); + final String[] gameId = new String[1]; + + if ("Player vs AI".equalsIgnoreCase(playerTypes)) { + GlobalEventBus.post(new Events.ServerEvents.SendCommand(connectionId, "create_game", "Player", "AI")); + } else if ("AI vs Player".equalsIgnoreCase(playerTypes)) { + GlobalEventBus.post(new Events.ServerEvents.SendCommand(connectionId, "create_game", "Player", "AI")); + } else { // Player vs Player is default + GlobalEventBus.post(new Events.ServerEvents.SendCommand(connectionId, "create_game", "Player1", "Player2")); + } + + CountDownLatch latch = new CountDownLatch(1); // TODO: This is bad, fix later + + new Thread(() -> { + GlobalEventBus.subscribeAndRegister(Events.ServerEvents.ReceivedMessage.class, event -> { + logger.info(event.message()); + if (event.message().toLowerCase().startsWith("game created successfully")) { + String[] parts = event.message().split("\\|"); + String gameIdPart = parts[1]; + gameId[0] = gameIdPart.split(" ")[1]; + latch.countDown(); + } + }); + }).start(); + + try { + latch.await(); // TODO: Bad, fix later + + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + GlobalEventBus.post(new Events.ServerEvents.SendCommand(connectionId, "START_GAME", gameId[0])); + + if ("Tic Tac Toe".equalsIgnoreCase(selectedGame)) { + if (tttBoard == null) { + tttBoard = new UIGameBoard("tic tac toe", connectionId, serverId, gameId[0], this); + cards.add(tttBoard.getTTTPanel(), "TicTacToe"); + } + cardLayout.show(cards, "TicTacToe"); + } + } + + public void showMainMenu() { + cardLayout.show(cards, "MainMenu"); + } +} diff --git a/src/main/java/org/toop/UI/LocalServerSelector.form b/src/main/java/org/toop/UI/LocalServerSelector.form new file mode 100644 index 0000000..be26eaf --- /dev/null +++ b/src/main/java/org/toop/UI/LocalServerSelector.form @@ -0,0 +1,39 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/main/java/org/toop/UI/LocalServerSelector.java b/src/main/java/org/toop/UI/LocalServerSelector.java new file mode 100644 index 0000000..fefbac9 --- /dev/null +++ b/src/main/java/org/toop/UI/LocalServerSelector.java @@ -0,0 +1,34 @@ +package org.toop.UI; + +import javax.swing.*; + +public class LocalServerSelector { + private JPanel panel1; + private JButton serverButton; + private JButton localButton; + private final JFrame frame; + + public LocalServerSelector() { + frame = new JFrame("Server Selector"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setContentPane(panel1); + frame.setSize(1920, 1080); + frame.setLocationRelativeTo(null); // Sets to center + frame.setVisible(true); + + serverButton.addActionListener(e -> onServerClicked()); + localButton.addActionListener(e -> onLocalClicked()); + + } + + private void onServerClicked() { + frame.dispose(); + new RemoteGameSelector(); + } + + private void onLocalClicked() { + frame.dispose(); + new LocalGameSelector(); + } + +} diff --git a/src/main/java/org/toop/UI/GameSelectorWindow.form b/src/main/java/org/toop/UI/RemoteGameSelector.form similarity index 98% rename from src/main/java/org/toop/UI/GameSelectorWindow.form rename to src/main/java/org/toop/UI/RemoteGameSelector.form index e510e3f..902cb76 100644 --- a/src/main/java/org/toop/UI/GameSelectorWindow.form +++ b/src/main/java/org/toop/UI/RemoteGameSelector.form @@ -1,9 +1,9 @@ -
+ - + diff --git a/src/main/java/org/toop/UI/GameSelectorWindow.java b/src/main/java/org/toop/UI/RemoteGameSelector.java similarity index 93% rename from src/main/java/org/toop/UI/GameSelectorWindow.java rename to src/main/java/org/toop/UI/RemoteGameSelector.java index e40b1ee..d01a52c 100644 --- a/src/main/java/org/toop/UI/GameSelectorWindow.java +++ b/src/main/java/org/toop/UI/RemoteGameSelector.java @@ -6,14 +6,13 @@ import org.toop.eventbus.GlobalEventBus; import javax.swing.*; import java.awt.event.ActionEvent; -import java.util.Locale; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -public class GameSelectorWindow extends JFrame { - private static final Logger logger = LogManager.getLogger(GameSelectorWindow.class); +public class RemoteGameSelector { + private static final Logger logger = LogManager.getLogger(RemoteGameSelector.class); private JPanel mainMenu; private JTextField nameTextField; @@ -27,7 +26,7 @@ public class GameSelectorWindow extends JFrame { private JFrame frame; private JLabel fillAllFields; - public GameSelectorWindow() { + public RemoteGameSelector() { gameSelectorBox.addItem("Tic Tac Toe"); gameSelectorBox.addItem("Reversi"); //todo get supported games from server and add to gameSelectorBox @@ -107,8 +106,8 @@ public class GameSelectorWindow extends JFrame { frame.remove(mainMenu); - UIGameBoard ttt = new UIGameBoard(gameSelectorBox.getSelectedItem().toString(),this); - frame.add(ttt.getTTTPanel()); +// UIGameBoard ttt = new UIGameBoard("tic tac toe", "test", "test",this); // TODO: Fix later +// frame.add(ttt.getTTTPanel()); // TODO: Fix later frame.revalidate(); frame.repaint(); } else { diff --git a/src/main/java/org/toop/UI/Services.form b/src/main/java/org/toop/UI/Services.form new file mode 100644 index 0000000..82187e2 --- /dev/null +++ b/src/main/java/org/toop/UI/Services.form @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/main/java/org/toop/UI/Services.java b/src/main/java/org/toop/UI/Services.java new file mode 100644 index 0000000..e1c8ae3 --- /dev/null +++ b/src/main/java/org/toop/UI/Services.java @@ -0,0 +1,6 @@ +package org.toop.UI; + +import javax.swing.*; + +public class Services { +} diff --git a/src/main/java/org/toop/UI/UIGameBoard.form b/src/main/java/org/toop/UI/UIGameBoard.form index 0d285e4..09a9ed6 100644 --- a/src/main/java/org/toop/UI/UIGameBoard.form +++ b/src/main/java/org/toop/UI/UIGameBoard.form @@ -1,6 +1,6 @@
- + @@ -10,38 +10,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/main/java/org/toop/UI/UIGameBoard.java b/src/main/java/org/toop/UI/UIGameBoard.java index 62b45fe..f103c53 100644 --- a/src/main/java/org/toop/UI/UIGameBoard.java +++ b/src/main/java/org/toop/UI/UIGameBoard.java @@ -1,79 +1,76 @@ package org.toop.UI; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.toop.Main; import org.toop.eventbus.Events; import org.toop.eventbus.GlobalEventBus; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; +import java.util.Objects; -public class UIGameBoard extends JFrame { - private static final Logger logger = LogManager.getLogger(UIGameBoard.class); +public class UIGameBoard { + private static final int TICTACTOE_SIZE = 3; - private final int TICTACTOE_SIZE = 3; - private final int REVERSI_SIZE = 8; - private JLabel name; - private JLabel ip; - private JLabel gameName; - private JPanel tttPanel; - private JPanel cellPanel; + private JPanel tttPanel; // Root panel for this game private JButton backToMainMenuButton; - private JButton[] buttons = new JButton[9]; private JButton[] cells; - public UIGameBoard(String game,GameSelectorWindow gameSelectorWindow) { + private String currentPlayer = "X"; - //cellPanel = new JPanel(); - JPanel gamePanel = new JPanel(); - if(game.toLowerCase().equals("tic tac toe")) { - gamePanel = createGridPanel(TICTACTOE_SIZE, TICTACTOE_SIZE); - } - if(game.toLowerCase().equals("reversi")) { - gamePanel = createGridPanel(REVERSI_SIZE, REVERSI_SIZE); + private String gameConnectionId; + private String serverId; + private String gameId; + + private LocalGameSelector parentSelector; + + public UIGameBoard(String gameType, String gameConnectionId, String serverId, String gameId, LocalGameSelector parent) { + this.parentSelector = parent; + + this .gameConnectionId = gameConnectionId; + this.serverId = serverId; + this.gameId = gameId; + + // Root panel + tttPanel = new JPanel(new BorderLayout()); + + // Back button + backToMainMenuButton = new JButton("Back to Main Menu"); + tttPanel.add(backToMainMenuButton, BorderLayout.SOUTH); + backToMainMenuButton.addActionListener(e -> + // TODO reset game and connections + parent.showMainMenu() + ); + + // Game grid + JPanel gameGrid = createGridPanel(TICTACTOE_SIZE, TICTACTOE_SIZE); + tttPanel.add(gameGrid, BorderLayout.CENTER); + } + + private JPanel createGridPanel(int sizeX, int sizeY) { + JPanel panel = new JPanel(new GridLayout(sizeX, sizeY)); + cells = new JButton[sizeX * sizeY]; + + for (int i = 0; i < sizeX * sizeY; i++) { + cells[i] = new JButton(" "); + cells[i].setFont(new Font("Arial", Font.BOLD, 100 / sizeX)); + panel.add(cells[i]); + + final int index = i; + cells[i].addActionListener((ActionEvent e) -> { + cells[index].setText(currentPlayer); + if (Objects.equals(currentPlayer, "X")) { currentPlayer = "O"; } + else { currentPlayer = "X"; } + GlobalEventBus.post(new Events.ServerEvents.SendCommand(this.gameConnectionId, + "gameid ", this.gameId, + "player ", this.currentPlayer, // TODO: Actual player names + "MOVE", "" + index)); + System.out.println("Cell clicked: " + index); + }); } - cellPanel.removeAll(); - cellPanel.add(gamePanel); - cellPanel.revalidate(); - cellPanel.repaint(); - //tttPanel.add(cellPanel); - backToMainMenuButton.addActionListener(( - ActionEvent e) -> { - gameSelectorWindow.returnToMainMenu(); - System.out.println("gothere"); - }); - } - //Set the IP, game name and name - public void setIGN(String ip, String gameName, String name) { - this.ip.setText(ip); - this.gameName.setText(gameName); - this.name.setText(name); + return panel; } + public JPanel getTTTPanel() { return tttPanel; } - //Creates a grid of buttons and adds a global event bus event on click with the index of the button. - private JPanel createGridPanel(int sizeX, int sizeY) { - JPanel cellPanel = new JPanel(new GridLayout(sizeX,sizeY)); - cells = new JButton[sizeX*sizeY]; - for(int i =0; i < sizeX*sizeY; i++){ - cells[i] = new JButton(" "); - cells[i].setPreferredSize(new Dimension(1000/sizeX,1000/sizeY)); - cells[i].setFont(new Font("Arial", Font.BOLD, 480/sizeX)); - cells[i].setFocusPainted(false); - cellPanel.add(cells[i]); - final int index = i; - cells[i].addActionListener((ActionEvent e) -> { - setCell(index,"X");//■ todo get current player - GlobalEventBus.post(new Events.ServerEvents.CellClicked(index)); - logger.info("Grid button {} was clicked.", index); - }); - } - return cellPanel; - } - public void setCell(int cell, String newValue){ - cells[cell].setText(newValue); - } -} +} \ No newline at end of file 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 ac49390..9685589 100644 --- a/src/main/java/org/toop/server/backend/tictactoe/TicTacToeServer.java +++ b/src/main/java/org/toop/server/backend/tictactoe/TicTacToeServer.java @@ -112,8 +112,9 @@ public class TicTacToeServer extends TcpServer { String gameId = this.newGame((String) command.arguments.getFirst(), (String) command.arguments.get(1)); this.sendQueue.offer("game created successfully|gameid " + gameId); } else if (command.command == TicTacToeServerCommand.START_GAME) { - this.runGame((String) command.arguments.getFirst()); - this.sendQueue.offer("svr game is running successfully"); + boolean success = this.runGame((String) command.arguments.getFirst()); + if (success) {this.sendQueue.offer("svr game is running successfully");} + else {this.sendQueue.offer("svr running game failed");} } else if (command.command == TicTacToeServerCommand.END_GAME) { this.endGame((String) command.arguments.getFirst()); this.sendQueue.offer("svr game ended successfully"); @@ -150,13 +151,15 @@ public class TicTacToeServer extends TcpServer { return gameId; } - public void runGame(String gameId) { + public boolean runGame(String gameId) { TicTacToe game = this.games.get(gameId); if (game != null) { game.run(); logger.info("Running game: {}, players: {}", gameId, game.getPlayers()); + return true; } else { logger.warn("Tried to run unknown game {}", gameId); + return false; } } diff --git a/src/main/java/org/toop/server/frontend/ServerConnection.java b/src/main/java/org/toop/server/frontend/ServerConnection.java index 2f8a99f..ce0ed13 100644 --- a/src/main/java/org/toop/server/frontend/ServerConnection.java +++ b/src/main/java/org/toop/server/frontend/ServerConnection.java @@ -52,10 +52,10 @@ public final class ServerConnection implements Runnable { // return; // } // TODO: DO I CARE? - if (!this.running) { - logger.warn("Server has been stopped"); - return; - } +// if (!this.running) { +// logger.warn("Server has been stopped"); +// return; +// } // TODO: Server not running String command = String.join(" ", args);