Local tic tac toe thread

This commit is contained in:
lieght
2025-09-19 17:31:37 +02:00
parent 1d90df4e86
commit ba16f2e135
38 changed files with 327 additions and 236 deletions

View File

@@ -1,14 +1,15 @@
package org.toop; package org.toop;
import org.toop.UI.LocalServerSelector; import org.toop.frontend.UI.LocalServerSelector;
import org.toop.eventbus.EventRegistry; import org.toop.eventbus.EventRegistry;
import org.toop.eventbus.Events; import org.toop.eventbus.Events;
import org.toop.eventbus.GlobalEventBus; import org.toop.eventbus.GlobalEventBus;
import org.toop.server.backend.ServerManager; import org.toop.backend.ServerManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.toop.server.frontend.ConnectionManager; import org.toop.frontend.ConnectionManager;
import org.toop.frontend.games.LocalTicTacToe;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@@ -18,7 +19,7 @@ public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException { public static void main(String[] args) throws ExecutionException, InterruptedException {
// Logging.disableAllLogs(); // Logging.disableAllLogs();
Logging.disableLogsForClass(EventRegistry.class); // Logging.enableAllLogsForClass(LocalTicTacToe.class);
// Logging.enableLogsForClass(ServerManager.class, Level.ALL); // Logging.enableLogsForClass(ServerManager.class, Level.ALL);
// Logging.enableLogsForClass(TicTacToeServer.class, Level.ALL); // Logging.enableLogsForClass(TicTacToeServer.class, Level.ALL);
// Logging.enableLogsForClass(TcpClient.class, Level.ALL); // Logging.enableLogsForClass(TcpClient.class, Level.ALL);
@@ -40,10 +41,6 @@ public class Main {
} }
/**
* Returns false if any event could not be initialized.
*/
private static void registerEvents() { private static void registerEvents() {
GlobalEventBus.subscribeAndRegister(Events.WindowEvents.OnQuitRequested.class, event -> { GlobalEventBus.subscribeAndRegister(Events.WindowEvents.OnQuitRequested.class, event -> {
quit(); quit();

View File

@@ -1,139 +0,0 @@
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<String> 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<String> 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");
}
}

View File

@@ -1,11 +1,11 @@
package org.toop.server.backend; package org.toop.backend;
import org.toop.eventbus.Events; import org.toop.eventbus.Events;
import org.toop.eventbus.GlobalEventBus; import org.toop.eventbus.GlobalEventBus;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.toop.server.backend.tictactoe.TicTacToeServer; import org.toop.backend.tictactoe.TicTacToeServer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map; import java.util.Map;

View File

@@ -1,8 +1,8 @@
package org.toop.server.backend; package org.toop.backend;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.toop.server.backend.tictactoe.ParsedCommand; import org.toop.backend.tictactoe.ParsedCommand;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
@@ -10,7 +10,6 @@ import java.io.InputStreamReader;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.*; import java.util.concurrent.*;

View File

@@ -1,8 +1,7 @@
package org.toop.server.backend.tictactoe; package org.toop.backend.tictactoe;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.toop.Main;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.regex.Matcher; import java.util.regex.Matcher;

View File

@@ -1,9 +1,9 @@
package org.toop.server.backend.tictactoe; package org.toop.backend.tictactoe;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.toop.game.tictactoe.TicTacToe; import org.toop.game.tictactoe.TicTacToe;
import org.toop.server.backend.TcpServer; import org.toop.backend.TcpServer;
import java.io.IOException; import java.io.IOException;
import java.net.Socket; import java.net.Socket;

View File

@@ -1,4 +1,4 @@
package org.toop.server.backend.tictactoe; package org.toop.backend.tictactoe;
import java.util.EnumSet; import java.util.EnumSet;

View File

@@ -1,4 +1,4 @@
package org.toop.server.backend.tictactoe; package org.toop.backend.tictactoe;
import java.util.EnumSet; import java.util.EnumSet;

View File

@@ -1,6 +1,6 @@
package org.toop.core; package org.toop.core;
import org.toop.platform.core.glfw.*; import org.toop.frontend.platform.core.glfw.GlfwWindow;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;

View File

@@ -1,7 +1,7 @@
package org.toop.eventbus; package org.toop.eventbus;
import org.toop.core.Window; import org.toop.core.Window;
import org.toop.server.backend.tictactoe.TicTacToeServer; import org.toop.backend.tictactoe.TicTacToeServer;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.Arrays; import java.util.Arrays;

View File

@@ -50,13 +50,13 @@ public class GlobalEventBus {
* @param action The function, or lambda to run when fired. * @param action The function, or lambda to run when fired.
* @return Object to be used for registering an event. * @return Object to be used for registering an event.
*/ */
private static <T> Object subscribe(Class<T> type, Consumer<T> action) { public static <T> Object subscribe(Class<T> type, Consumer<T> action) {
return new Object() { return new Object() {
@Subscribe @Subscribe
public void handle(Object event) { public void handle(Object event) {
if (type.isInstance(event)) { if (type.isInstance(event)) {
action.accept(type.cast(event)); action.accept(type.cast(event));
} }
} }
}; };
} }
@@ -68,18 +68,10 @@ public class GlobalEventBus {
* @param action The function, or lambda to run when fired. * @param action The function, or lambda to run when fired.
* @return Object to be used for registering an event. * @return Object to be used for registering an event.
*/ */
public static <T> EventMeta subscribeAndRegister(Class<T> type, Consumer<T> action) { public static <T> Object subscribeAndRegister(Class<T> type, Consumer<T> action) {
Object listener = new Object() { var listener = subscribe(type, action);
@Subscribe register(listener);
public void handle(Object event) { return listener;
if (type.isInstance(event)) {
action.accept(type.cast(event));
}
}
};
var re = new EventMeta<>(type, listener);
register(re);
return re;
} }
@@ -88,10 +80,8 @@ public class GlobalEventBus {
* *
* @param event The ready event to add to register. * @param event The ready event to add to register.
*/ */
public static <T> void register(EventMeta<T> event) { public static void register(Object listener) {
GlobalEventBus.get().register(event.getEvent()); GlobalEventBus.get().register(listener);
event.setReady(true);
EventRegistry.markReady(event.getType());
} }
/** /**
@@ -99,10 +89,8 @@ public class GlobalEventBus {
* *
* @param event The ready event to unregister. * @param event The ready event to unregister.
*/ */
public static <T> void unregister(EventMeta<T> event) { public static void unregister(Object listener) {
EventRegistry.markNotReady(event.getType()); GlobalEventBus.get().unregister(listener);
event.setReady(false);
GlobalEventBus.get().unregister(event.getEvent());
} }
/** /**

View File

@@ -1,4 +1,4 @@
package org.toop.server.frontend; package org.toop.frontend;
import org.toop.eventbus.Events; import org.toop.eventbus.Events;
import org.toop.eventbus.GlobalEventBus; import org.toop.eventbus.GlobalEventBus;

View File

@@ -1,10 +1,9 @@
package org.toop.server.frontend; package org.toop.frontend;
import org.toop.eventbus.Events;
import org.toop.eventbus.GlobalEventBus;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.toop.eventbus.Events;
import org.toop.eventbus.GlobalEventBus;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
@@ -59,8 +58,7 @@ public final class ServerConnection extends TcpClient implements Runnable {
} }
} }
private void initEvents() { private void initEvents() {}
}
private void startWorkers() { private void startWorkers() {
running = true; running = true;
@@ -87,7 +85,8 @@ public final class ServerConnection extends TcpClient implements Runnable {
String received = this.readLine(); // blocks String received = this.readLine(); // blocks
if (received != null) { if (received != null) {
logger.info("Connection: {} received: '{}'", this.uuid, received); logger.info("Connection: {} received: '{}'", this.uuid, received);
this.addReceivedMessageToQueue(received); // this.addReceivedMessageToQueue(received); // TODO: Will never go empty
GlobalEventBus.post(new Events.ServerEvents.ReceivedMessage(this.uuid, received)); // TODO: mb change
} else { } else {
break; break;
} }

View File

@@ -1,4 +1,4 @@
package org.toop.server.frontend; package org.toop.frontend;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;

View File

@@ -1,4 +1,4 @@
package org.toop.UI; package org.toop.frontend.UI;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.UI.LocalGameSelector"> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.LocalGameSelector">
<grid id="27dc6" binding="panel1" default-binding="true" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <grid id="27dc6" binding="panel1" default-binding="true" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/> <margin top="0" left="0" bottom="0" right="0"/>
<constraints> <constraints>

View File

@@ -0,0 +1,83 @@
package org.toop.frontend.UI;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.toop.eventbus.Events;
import org.toop.eventbus.GlobalEventBus;
import org.toop.frontend.games.LocalTicTacToe;
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 void startGameClicked() {
String playerTypes = (String) playerTypeSelectionBox.getSelectedItem();
String selectedGame = (String) gameSelectionComboBox.getSelectedItem();
LocalTicTacToe lttt = new LocalTicTacToe(true, "127.0.0.1", "5001");
if ("Tic Tac Toe".equalsIgnoreCase(selectedGame)) {
if (tttBoard == null) {
tttBoard = new UIGameBoard(lttt, this);
cards.add(tttBoard.getTTTPanel(), "TicTacToe");
}
cardLayout.show(cards, "TicTacToe");
}
}
public void showMainMenu() {
cardLayout.show(cards, "MainMenu");
}
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.UI.LocalServerSelector"> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.LocalServerSelector">
<grid id="27dc6" binding="panel1" default-binding="true" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <grid id="27dc6" binding="panel1" default-binding="true" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/> <margin top="0" left="0" bottom="0" right="0"/>
<constraints> <constraints>

View File

@@ -1,4 +1,4 @@
package org.toop.UI; package org.toop.frontend.UI;
import javax.swing.*; import javax.swing.*;

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.UI.RemoteGameSelector"> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.RemoteGameSelector">
<grid id="27dc6" binding="mainMenu" layout-manager="GridLayoutManager" row-count="10" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <grid id="27dc6" binding="mainMenu" layout-manager="GridLayoutManager" row-count="10" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="10" left="10" bottom="10" right="10"/> <margin top="10" left="10" bottom="10" right="10"/>
<constraints> <constraints>

View File

@@ -1,4 +1,4 @@
package org.toop.UI; package org.toop.frontend.UI;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.toop.eventbus.Events; import org.toop.eventbus.Events;

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.UI.Services"> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.Services">
<grid id="27dc6" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <grid id="27dc6" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/> <margin top="0" left="0" bottom="0" right="0"/>
<constraints> <constraints>

View File

@@ -1,4 +1,4 @@
package org.toop.UI; package org.toop.frontend.UI;
import javax.swing.*; import javax.swing.*;

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.UI.UIGameBoard"> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.UIGameBoard">
<grid id="27dc6" binding="tttPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <grid id="27dc6" binding="tttPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="10" left="10" bottom="10" right="10"/> <margin top="10" left="10" bottom="10" right="10"/>
<constraints> <constraints>

View File

@@ -1,7 +1,8 @@
package org.toop.UI; package org.toop.frontend.UI;
import org.toop.eventbus.Events; import org.toop.eventbus.Events;
import org.toop.eventbus.GlobalEventBus; import org.toop.eventbus.GlobalEventBus;
import org.toop.frontend.games.LocalTicTacToe;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
@@ -16,18 +17,12 @@ public class UIGameBoard {
private JButton[] cells; private JButton[] cells;
private String currentPlayer = "X"; private String currentPlayer = "X";
private String gameConnectionId;
private String serverId;
private String gameId;
private LocalGameSelector parentSelector; private LocalGameSelector parentSelector;
private LocalTicTacToe localTicTacToe;
public UIGameBoard(String gameType, String gameConnectionId, String serverId, String gameId, LocalGameSelector parent) { public UIGameBoard(LocalTicTacToe lttt, LocalGameSelector parent) {
this.parentSelector = parent; this.parentSelector = parent;
this.localTicTacToe = lttt;
this .gameConnectionId = gameConnectionId;
this.serverId = serverId;
this.gameId = gameId;
// Root panel // Root panel
tttPanel = new JPanel(new BorderLayout()); tttPanel = new JPanel(new BorderLayout());
@@ -59,10 +54,7 @@ public class UIGameBoard {
cells[index].setText(currentPlayer); cells[index].setText(currentPlayer);
if (Objects.equals(currentPlayer, "X")) { currentPlayer = "O"; } if (Objects.equals(currentPlayer, "X")) { currentPlayer = "O"; }
else { currentPlayer = "X"; } else { currentPlayer = "X"; }
GlobalEventBus.post(new Events.ServerEvents.SendCommand(this.gameConnectionId, this.localTicTacToe.move(index);
"gameid ", this.gameId,
"player ", this.currentPlayer, // TODO: Actual player names
"MOVE", "" + index));
System.out.println("Cell clicked: " + index); System.out.println("Cell clicked: " + index);
}); });
} }

View File

@@ -0,0 +1,170 @@
package org.toop.frontend.games;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.toop.eventbus.Events;
import org.toop.eventbus.GlobalEventBus;
import java.util.concurrent.*;
public class LocalTicTacToe { // TODO: Implement runnable
private static final Logger logger = LogManager.getLogger(LocalTicTacToe.class);
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private final BlockingQueue<String> receivedQueue = new LinkedBlockingQueue<>();
Object receivedMessageListener;
volatile String gameId;
volatile String connectionId;
volatile String serverId;
/**
* Is either 1 or 2.
*/
private int playersTurn = 1;
// LocalTicTacToe(String gameId, String connectionId, String serverId) {
// this.gameId = gameId;
// this.connectionId = connectionId;
// this.serverId = serverId;
// this.receivedMessageListener = GlobalEventBus.subscribe(Events.ServerEvents.ReceivedMessage.class, this::receiveMessageAction);
// GlobalEventBus.register(this.receivedMessageListener);
//
//
// this.executor.submit(this::gameThread);
// } TODO: If remote server
public LocalTicTacToe(boolean isLocalServer, String ip, String port) {
this.receivedMessageListener = GlobalEventBus.subscribe(Events.ServerEvents.ReceivedMessage.class, this::receiveMessageAction);
GlobalEventBus.register(this.receivedMessageListener);
// TODO: Is blocking
if (isLocalServer) { this.serverId = this.createServer(port); }
else { this.serverId = null; } // TODO: What if null?
this.connectionId = this.createConnection(ip, port);
this.createGame(ip, port);
this.executor.submit(this::gameThread);
}
private String createServer(String port) {
CompletableFuture<String> serverIdFuture = new CompletableFuture<>();
GlobalEventBus.post(new Events.ServerEvents.StartServerRequest(port, "tictactoe", serverIdFuture));
try {
return serverIdFuture.get();
} catch (Exception e) {
logger.error("Error getting server ID", e);
}
return null;
}
private String createConnection(String ip, String port) {
CompletableFuture<String> connectionIdFuture = new CompletableFuture<>();
GlobalEventBus.post(new Events.ServerEvents.StartConnectionRequest(ip, port, 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 createGame(String nameA, String nameB) {
nameA = nameA.trim().replace(" ", "-");
nameB = nameB.trim().replace(" ", "-");
this.sendCommand("create_game", nameA, nameB);
}
private void startGame() {
if (this.gameId == null) { return; }
this.sendCommand("start_game", this.gameId);
}
void gameThread() {
logger.info("Starting local game thread, connection: {}, server: {}", this.connectionId, this.serverId);
CountDownLatch latch = new CountDownLatch(1); // TODO: This is bad, fix later
new Thread(() -> {
while(true) {
String msg = this.receivedQueue.poll();
if (msg == null) {continue;}
if (msg.toLowerCase().startsWith("game created successfully")) {
String[] parts = msg.split("\\|");
String gameIdPart = parts[1];
this.gameId = gameIdPart.split(" ")[1];
latch.countDown();
break;
}
}
}).start();
try {
latch.await(); // TODO: Bad, fix later
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
startGame(); // TODO: Actually need to wait, but is fine for now.
boolean running = true;
while (running) {
try {
String rec = this.receivedQueue.take();
if (rec.equalsIgnoreCase("ok")) {continue;}
else if (rec.equalsIgnoreCase("svr game yourturn")) {
if (this.playersTurn == 1) {
this.playersTurn += 1;
} else {
this.playersTurn -= 1;
}
logger.info("Player turn: {}", this.playersTurn);
}
else if (rec.equalsIgnoreCase("svr game win")) {
endListeners();
}
} catch (InterruptedException e) {
throw new RuntimeException(e); // TODO: Error handling
}
}
this.endListeners();
}
public void endGame() {
sendCommand("gameid", "end_game"); // TODO: Command is a bit wrong.
}
public void move(int index) {
sendCommand("gameid", this.gameId, "player", "test", "move", String.valueOf(index));
}
private void endTheGame() {
this.sendCommand("end_game", this.gameId);
this.endListeners();
}
void receiveMessageAction(Events.ServerEvents.ReceivedMessage receivedMessage) {
if (!receivedMessage.ConnectionUuid().equals(this.connectionId)) {
return;
}
try {
logger.info("Received message from " + this.connectionId + ": " + receivedMessage.message());
this.receivedQueue.put(receivedMessage.message());
} catch (InterruptedException e) {
logger.error("Error waiting for received Message", e);
}
}
void sendCommand(String... args) {
GlobalEventBus.post(new Events.ServerEvents.SendCommand(this.connectionId, args));
}
void endListeners() {
GlobalEventBus.unregister(this.receivedMessageListener);
}
}

View File

@@ -1,6 +1,6 @@
package org.toop.graphics; package org.toop.frontend.graphics;
import org.toop.platform.graphics.opengl.*; import org.toop.frontend.platform.graphics.opengl.OpenglRenderer;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;

View File

@@ -1,6 +1,6 @@
package org.toop.graphics; package org.toop.frontend.graphics;
import org.toop.platform.graphics.opengl.*; import org.toop.frontend.platform.graphics.opengl.OpenglShader;
public abstract class Shader { public abstract class Shader {
public static Shader create(String vertexPath, String fragmentPath) { public static Shader create(String vertexPath, String fragmentPath) {

View File

@@ -1,7 +1,7 @@
package org.toop.graphics.node; package org.toop.frontend.graphics.node;
import org.toop.core.*; import org.toop.core.*;
import org.toop.math.*; import org.toop.frontend.math.Color;
public class Button extends Node { public class Button extends Node {
ICallable<Boolean> onHover; ICallable<Boolean> onHover;

View File

@@ -1,6 +1,7 @@
package org.toop.graphics.node; package org.toop.frontend.graphics.node;
import org.toop.math.*; import org.toop.frontend.math.Bounds;
import org.toop.frontend.math.Color;
public abstract class Node { public abstract class Node {
protected Bounds bounds; protected Bounds bounds;

View File

@@ -1,7 +1,7 @@
package org.toop.graphics.node; package org.toop.frontend.graphics.node;
import org.toop.eventbus.*; import org.toop.eventbus.*;
import org.toop.graphics.*; import org.toop.frontend.graphics.Shader;
import java.util.*; import java.util.*;

View File

@@ -1,6 +1,6 @@
package org.toop.graphics.node; package org.toop.frontend.graphics.node;
import org.toop.math.*; import org.toop.frontend.math.Bounds;
import java.util.*; import java.util.*;

View File

@@ -1,4 +1,4 @@
package org.toop.math; package org.toop.frontend.math;
public class Bounds { public class Bounds {
private int x; private int x;

View File

@@ -1,4 +1,4 @@
package org.toop.math; package org.toop.frontend.math;
public class Color { public class Color {
private float r; private float r;

View File

@@ -1,4 +1,4 @@
package org.toop.platform.core.glfw; package org.toop.frontend.platform.core.glfw;
import org.toop.core.*; import org.toop.core.*;
import org.toop.eventbus.*; import org.toop.eventbus.*;

View File

@@ -1,7 +1,8 @@
package org.toop.platform.graphics.opengl; package org.toop.frontend.platform.graphics.opengl;
import org.toop.eventbus.*; import org.toop.eventbus.*;
import org.toop.graphics.*; import org.toop.frontend.graphics.Renderer;
import org.toop.frontend.graphics.Shader;
import org.lwjgl.opengl.*; import org.lwjgl.opengl.*;
import org.lwjgl.system.*; import org.lwjgl.system.*;

View File

@@ -1,7 +1,7 @@
package org.toop.platform.graphics.opengl; package org.toop.frontend.platform.graphics.opengl;
import org.toop.core.*; import org.toop.core.*;
import org.toop.graphics.*; import org.toop.frontend.graphics.Shader;
import org.lwjgl.opengl.*; import org.lwjgl.opengl.*;

View File

@@ -2,8 +2,9 @@ package org.toop.game.tictactoe;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.toop.backend.tictactoe.ParsedCommand;
import org.toop.backend.tictactoe.TicTacToeServerCommand;
import org.toop.game.*; import org.toop.game.*;
import org.toop.server.backend.tictactoe.*;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;