mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 10:54:51 +00:00
Refactoring, removed unnecessary files and classes.
This commit is contained in:
36
pom.xml
36
pom.xml
@@ -15,28 +15,8 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<main-class>org.toop.Main</main-class>
|
||||
|
||||
<lwjgl.version>3.3.6</lwjgl.version>
|
||||
</properties>
|
||||
|
||||
<profiles>
|
||||
<profile><id>lwjgl-natives-windows-amd64</id><activation><os><family>windows</family><arch>amd64</arch></os></activation><properties><lwjgl.natives>natives-windows</lwjgl.natives></properties></profile>
|
||||
<profile><id>lwjgl-natives-linux-amd64</id><activation><os><family>unix</family><name>linux</name><arch>amd64</arch></os></activation><properties><lwjgl.natives>natives-linux</lwjgl.natives></properties></profile>
|
||||
<profile><id>lwjgl-natives-macos-aarch64</id><activation><os><family>mac</family><arch>aarch64</arch></os></activation><properties><lwjgl.natives>natives-macos-arm64</lwjgl.natives></properties></profile>
|
||||
</profiles>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.lwjgl</groupId>
|
||||
<artifactId>lwjgl-bom</artifactId>
|
||||
<version>${lwjgl.version}</version>
|
||||
<scope>import</scope>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit</groupId>
|
||||
@@ -117,15 +97,6 @@
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.2.6.Final</version>
|
||||
</dependency>
|
||||
|
||||
<dependency><groupId>org.lwjgl</groupId><artifactId>lwjgl</artifactId></dependency>
|
||||
<dependency><groupId>org.lwjgl</groupId><artifactId>lwjgl-glfw</artifactId></dependency>
|
||||
<dependency><groupId>org.lwjgl</groupId><artifactId>lwjgl-opengl</artifactId></dependency>
|
||||
<dependency><groupId>org.lwjgl</groupId><artifactId>lwjgl-stb</artifactId></dependency>
|
||||
<dependency><groupId>org.lwjgl</groupId><artifactId>lwjgl</artifactId><classifier>${lwjgl.natives}</classifier></dependency>
|
||||
<dependency><groupId>org.lwjgl</groupId><artifactId>lwjgl-glfw</artifactId><classifier>${lwjgl.natives}</classifier></dependency>
|
||||
<dependency><groupId>org.lwjgl</groupId><artifactId>lwjgl-opengl</artifactId><classifier>${lwjgl.natives}</classifier></dependency>
|
||||
<dependency><groupId>org.lwjgl</groupId><artifactId>lwjgl-stb</artifactId><classifier>${lwjgl.natives}</classifier></dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -198,13 +169,6 @@
|
||||
<reflowLongStrings>true</reflowLongStrings>
|
||||
<formatJavadoc>true</formatJavadoc>
|
||||
</googleJavaFormat>
|
||||
|
||||
<!-- make sure every file has the following copyright header.
|
||||
optionally, Spotless can set copyright years by digging
|
||||
through git history (see "license" section below) -->
|
||||
<!-- <licenseHeader>-->
|
||||
<!-- <content>/* (C)$YEAR */</content> <!– or <file>${project.basedir}/license-header</file> –>-->
|
||||
<!-- </licenseHeader>-->
|
||||
</java>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
@@ -1,214 +0,0 @@
|
||||
//package org.toop;
|
||||
//
|
||||
//import java.util.*;
|
||||
//import java.util.concurrent.CompletableFuture;
|
||||
//import java.util.concurrent.ExecutionException;
|
||||
//import org.apache.logging.log4j.LogManager;
|
||||
//import org.apache.logging.log4j.Logger;
|
||||
//import org.toop.eventbus.events.Events;
|
||||
//import org.toop.eventbus.GlobalEventBus;
|
||||
//import org.toop.game.tictactoe.*;
|
||||
//import org.toop.game.tictactoe.ai.MinMaxTicTacToe;
|
||||
//
|
||||
//public class ConsoleGui {
|
||||
//
|
||||
// private static final Logger logger = LogManager.getLogger(ConsoleGui.class);
|
||||
//
|
||||
// private Scanner scanner;
|
||||
//
|
||||
// private TicTacToe game;
|
||||
// private MinMaxTicTacToe ai;
|
||||
//
|
||||
// private String ai1 = null;
|
||||
// private String ai2 = null;
|
||||
//
|
||||
// private String serverId = null;
|
||||
// private String connectionId = null;
|
||||
// private String ticTacToeGameId = null;
|
||||
//
|
||||
// public ConsoleGui() throws ExecutionException, InterruptedException {
|
||||
// scanner = new Scanner(System.in);
|
||||
// Random random = new Random(3453498);
|
||||
//
|
||||
// int mode = -1;
|
||||
//
|
||||
// System.out.print(
|
||||
// """
|
||||
// 1. player vs player
|
||||
// 2. player vs ai
|
||||
// 3. ai vs player
|
||||
// 4. ai v ai
|
||||
// Choose mode (default is 1):\s\
|
||||
// """);
|
||||
// String modeString = scanner.nextLine();
|
||||
//
|
||||
// try {
|
||||
// mode = Integer.parseInt(modeString);
|
||||
// } catch (Exception e) {
|
||||
// logger.error(e.getMessage());
|
||||
// }
|
||||
//
|
||||
// String player1 = null;
|
||||
// String player2 = null;
|
||||
//
|
||||
// switch (mode) {
|
||||
// // player vs ai
|
||||
// case 2:
|
||||
// {
|
||||
// System.out.print("Please enter your name: ");
|
||||
// String name = scanner.nextLine();
|
||||
//
|
||||
// player1 = name;
|
||||
// ai2 = player2 = "AI#" + random.nextInt();
|
||||
//
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// // ai vs player
|
||||
// case 3:
|
||||
// {
|
||||
// System.out.print("Enter your name: ");
|
||||
// String name = scanner.nextLine();
|
||||
//
|
||||
// ai1 = player1 = "AI#" + random.nextInt();
|
||||
// player2 = name;
|
||||
//
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// // ai vs ai
|
||||
// case 4:
|
||||
// {
|
||||
// ai1 = player1 = "AI#" + random.nextInt();
|
||||
// ai2 = player2 = "AI2" + random.nextInt();
|
||||
//
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// // player vs player
|
||||
// case 1:
|
||||
// default:
|
||||
// {
|
||||
// System.out.print("Player 1. Please enter your name: ");
|
||||
// String name1 = scanner.nextLine();
|
||||
//
|
||||
// System.out.print("Player 2. Please enter your name: ");
|
||||
// String name2 = scanner.nextLine();
|
||||
//
|
||||
// player1 = name1;
|
||||
// player2 = name2;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// game = new TicTacToe(player1, player2);
|
||||
// ai = new MinMaxTicTacToe();
|
||||
//
|
||||
// CompletableFuture<String> serverIdFuture = new CompletableFuture<>();
|
||||
// GlobalEventBus.post(
|
||||
// new Events.ServerEvents.StartServerRequest("5001", "tictactoe", serverIdFuture));
|
||||
// serverId = serverIdFuture.get();
|
||||
//
|
||||
// CompletableFuture<String> connectionIdFuture = new CompletableFuture<>();
|
||||
// GlobalEventBus.post(
|
||||
// new Events.ServerEvents.StartConnectionRequest(
|
||||
// "127.0.0.1", "5001", connectionIdFuture));
|
||||
// connectionId = connectionIdFuture.get();
|
||||
//
|
||||
// CompletableFuture<String> ticTacToeGame = new CompletableFuture<>();
|
||||
// GlobalEventBus.post(
|
||||
// new Events.ServerEvents.CreateTicTacToeGameRequest(
|
||||
// serverId, player1, player2, ticTacToeGame));
|
||||
// ticTacToeGameId = ticTacToeGame.get();
|
||||
// GlobalEventBus.post(new Events.ServerEvents.RunTicTacToeGame(serverId, ticTacToeGameId));
|
||||
// }
|
||||
//
|
||||
// public void print() {
|
||||
// char[] seperator = new char[game.getSize() * 4 - 1];
|
||||
// Arrays.fill(seperator, '-');
|
||||
//
|
||||
// for (int i = 0; i < game.getSize(); i++) {
|
||||
// String buffer = " ";
|
||||
//
|
||||
// for (int j = 0; j < game.getSize() - 1; j++) {
|
||||
// buffer += game.getGrid()[i * game.getSize() + j] + " | ";
|
||||
// }
|
||||
//
|
||||
// buffer += game.getGrid()[i * game.getSize() + game.getSize() - 1];
|
||||
// System.out.println(buffer);
|
||||
//
|
||||
// if (i < game.getSize() - 1) {
|
||||
// System.out.println(seperator);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public boolean next() {
|
||||
// Player current = game.getCurrentPlayer();
|
||||
// int move = -1;
|
||||
//
|
||||
// if (ai1 != null && current.getName() == ai1 || ai2 != null && current.getName() == ai2) {
|
||||
// move = ai.findBestMove(game);
|
||||
// } else {
|
||||
// System.out.printf(
|
||||
// "%s's (%c) turn. Please choose an empty cell between 0-8: ",
|
||||
// current.getName(), current.getSymbol());
|
||||
// String input = scanner.nextLine();
|
||||
//
|
||||
// try {
|
||||
// move = Integer.parseInt(input);
|
||||
// } catch (NumberFormatException e) {
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// GameBase.State state = game.play(move);
|
||||
// boolean keepRunning = true;
|
||||
//
|
||||
// switch (state) {
|
||||
// case INVALID:
|
||||
// {
|
||||
// System.out.println("Please select an empty cell. Between 0-8");
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// case DRAW:
|
||||
// {
|
||||
// System.out.println("Game ended in a draw.");
|
||||
// keepRunning = false;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// case WIN:
|
||||
// {
|
||||
// System.out.printf("%s has won the game.\n", current.getName());
|
||||
// keepRunning = false;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// case NORMAL:
|
||||
// default:
|
||||
// {
|
||||
// keepRunning = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// GlobalEventBus.post(
|
||||
// new Events.ServerEvents.SendCommand(
|
||||
// connectionId,
|
||||
// "gameid " + ticTacToeGameId,
|
||||
// "player " + current.getName(),
|
||||
// "MOVE",
|
||||
// String.valueOf(move)));
|
||||
//
|
||||
// if (!keepRunning) {
|
||||
// GlobalEventBus.post(
|
||||
// new Events.ServerEvents.EndTicTacToeGame(serverId, ticTacToeGameId));
|
||||
// }
|
||||
//
|
||||
// return keepRunning;
|
||||
// }
|
||||
//
|
||||
// public GameBase getGame() {
|
||||
// return game;
|
||||
// }
|
||||
//}
|
||||
@@ -7,7 +7,6 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.toop.backend.tictactoe.ServerManager;
|
||||
import org.toop.eventbus.EventPublisher;
|
||||
import org.toop.eventbus.EventRegistry;
|
||||
import org.toop.eventbus.events.Events;
|
||||
import org.toop.eventbus.GlobalEventBus;
|
||||
import org.toop.frontend.UI.LocalServerSelector;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package org.toop;
|
||||
|
||||
import org.toop.eventbus.EventFlow;
|
||||
import org.toop.eventbus.GlobalEventBus;
|
||||
import org.toop.eventbus.events.NetworkEvents;
|
||||
import org.toop.frontend.networking.NetworkingGameClientHandler;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class MainTest {
|
||||
MainTest() {
|
||||
var a = new EventFlow()
|
||||
.addPostEvent(NetworkEvents.StartClient.class,
|
||||
(Supplier<NetworkingGameClientHandler>) NetworkingGameClientHandler::new,
|
||||
"127.0.0.1",
|
||||
5001)
|
||||
.onResponse(NetworkEvents.StartClientSuccess.class)
|
||||
.perform(this::handleStartClientSuccess)
|
||||
.unsubscribeAfterSuccess().asyncPostEvent();
|
||||
}
|
||||
|
||||
private void handleStartClientSuccess(NetworkEvents.StartClientSuccess event) {
|
||||
GlobalEventBus.post(new NetworkEvents.CloseClient(event.clientId()));
|
||||
}
|
||||
}
|
||||
@@ -1,216 +0,0 @@
|
||||
package org.toop.backend.tictactoe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class ParsedCommand {
|
||||
private static final Logger logger = LogManager.getLogger(ParsedCommand.class);
|
||||
|
||||
public TicTacToeServerCommand command;
|
||||
public ArrayList<Object> arguments;
|
||||
public boolean isValidCommand;
|
||||
public boolean isServerCommand;
|
||||
public TicTacToeServerMessage returnMessage;
|
||||
public String errorMessage;
|
||||
public String originalCommand;
|
||||
public String gameId;
|
||||
public String player;
|
||||
|
||||
public ParsedCommand(String receivedCommand) {
|
||||
|
||||
if (receivedCommand.isEmpty()) {
|
||||
logger.info("Received empty command");
|
||||
this.gameId = null;
|
||||
this.player = null;
|
||||
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;
|
||||
}
|
||||
|
||||
// Case-insensitive regex to match: game_id {id} player {name}
|
||||
Pattern pattern =
|
||||
Pattern.compile(
|
||||
"(?i)\\bgame[_]?id\\s+(\\S+)\\s+player\\s+(\\S+)",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
Matcher matcher = pattern.matcher(receivedCommand);
|
||||
|
||||
String tempGameId = null;
|
||||
String tempPlayer = null;
|
||||
String tempPayload = receivedCommand;
|
||||
|
||||
if (matcher.find()) {
|
||||
tempGameId = matcher.group(1); // first capture group → game_id
|
||||
tempPlayer = matcher.group(2); // second capture group → player
|
||||
// Remove the matched part from the original command
|
||||
tempPayload = matcher.replaceFirst("").trim();
|
||||
}
|
||||
|
||||
this.gameId = tempGameId;
|
||||
this.player = tempPlayer;
|
||||
receivedCommand = tempPayload;
|
||||
|
||||
logger.info("Received gameId: {}", gameId);
|
||||
logger.info("Received player: {}", player);
|
||||
logger.info("Received command: {}", receivedCommand);
|
||||
|
||||
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 CREATE_GAME -> {
|
||||
if (segments.length == 3 && !segments[1].isEmpty() && !segments[2].isEmpty()) {
|
||||
this.command = commandEnum;
|
||||
this.arguments = new ArrayList<>(2);
|
||||
this.arguments.add(segments[1]);
|
||||
this.arguments.add(segments[2]);
|
||||
this.returnMessage = TicTacToeServerMessage.OK;
|
||||
this.isValidCommand = true;
|
||||
this.isServerCommand = true;
|
||||
this.errorMessage = null;
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
}
|
||||
}
|
||||
case END_GAME, START_GAME -> {
|
||||
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 = true;
|
||||
this.errorMessage = null;
|
||||
this.originalCommand = receivedCommand;
|
||||
return;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.originalCommand; // TODO: Maybe return more info.
|
||||
}
|
||||
|
||||
//
|
||||
// public ParsedCommand parseCommand(String command) {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package org.toop.backend.tictactoe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.toop.eventbus.EventPublisher;
|
||||
import org.toop.eventbus.events.Events;
|
||||
|
||||
// TODO more methods.
|
||||
|
||||
public class ServerManager {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(ServerManager.class);
|
||||
|
||||
/** Map of serverId -> Server instances */
|
||||
private final Map<String, TcpServer> servers = new ConcurrentHashMap<>();
|
||||
|
||||
/** Starts a server manager, to manage, servers. */
|
||||
public ServerManager() {
|
||||
new EventPublisher<>(Events.ServerEvents.StartServerRequest.class, this::handleStartServerRequest);
|
||||
new EventPublisher<>(Events.ServerEvents.StartServer.class, this::handleStartServer);
|
||||
new EventPublisher<>(Events.ServerEvents.ForceCloseAllServers.class, _ -> shutdownAll());
|
||||
new EventPublisher<>(Events.ServerEvents.CreateTicTacToeGameRequest.class, this::handleStartTicTacToeGameOnAServer);
|
||||
new EventPublisher<>(Events.ServerEvents.RunTicTacToeGame.class, this::handleRunTicTacToeGameOnAServer);
|
||||
new EventPublisher<>(Events.ServerEvents.EndTicTacToeGame.class, this::handleEndTicTacToeGameOnAServer);
|
||||
}
|
||||
|
||||
private String startServer(int port, String gameType) {
|
||||
String serverId = UUID.randomUUID().toString();
|
||||
gameType = gameType.toLowerCase();
|
||||
try {
|
||||
TcpServer server = null;
|
||||
if (Objects.equals(gameType, "tictactoe")) {
|
||||
server = new TicTacToeServer(port);
|
||||
} else {
|
||||
logger.error("Manager could not create a server for game type: {}", gameType);
|
||||
return null;
|
||||
}
|
||||
this.servers.put(serverId, server);
|
||||
new Thread(server, "Server-" + serverId).start();
|
||||
logger.info("Created server with id: {}, port: {}", serverId, port);
|
||||
return serverId;
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to start server", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleStartServerRequest(Events.ServerEvents.StartServerRequest request) {
|
||||
request.future()
|
||||
.complete(
|
||||
this.startServer(
|
||||
request.port(),
|
||||
request.gameType())); // TODO: Maybe post StartServer event.
|
||||
}
|
||||
|
||||
private void handleStartServer(Events.ServerEvents.StartServer event) {
|
||||
new EventPublisher<>(Events.ServerEvents.ServerStarted.class, 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());
|
||||
}
|
||||
|
||||
public void shutdownAll() {
|
||||
this.servers.values().forEach(TcpServer::stop);
|
||||
this.servers.clear();
|
||||
logger.info("All servers shut down");
|
||||
}
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
package org.toop.backend.tictactoe;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Lightweight, thread-pool based TCP server base class.
|
||||
*
|
||||
* <p>Responsibilities: - accept sockets - hand off socket I/O to connectionExecutor (pooled
|
||||
* threads) - provide thread-safe queues (receivedQueue / sendQueue) to subclasses
|
||||
*
|
||||
* <p>Notes: - Subclasses should consume receivedQueue (or call getNewestCommand()) and use
|
||||
* sendQueue to send messages to all clients (or per-client, if implemented).
|
||||
*/
|
||||
public abstract class TcpServer implements Runnable {
|
||||
|
||||
protected static final Logger logger = LogManager.getLogger(TcpServer.class);
|
||||
|
||||
// Executor used for per-connection I/O tasks (reading/writing)
|
||||
protected final ExecutorService connectionExecutor = Executors.newCachedThreadPool();
|
||||
|
||||
// Shared queues for subclasses / consumers
|
||||
public final BlockingQueue<String> receivedQueue = new LinkedBlockingQueue<>();
|
||||
public final BlockingQueue<String> sendQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
// Association for sockets -> player ids
|
||||
public final Map<Socket, String> knownPlayers = new ConcurrentHashMap<>();
|
||||
public final Map<String, String> playersGames = new ConcurrentHashMap<>();
|
||||
|
||||
// tunables
|
||||
public final int WAIT_TIME = 500; // ms used by poll-based methods
|
||||
public final int RETRY_ATTEMPTS = 3;
|
||||
|
||||
protected final int port;
|
||||
protected final ServerSocket serverSocket;
|
||||
private volatile boolean running = true;
|
||||
|
||||
public TcpServer(int port) throws IOException {
|
||||
this.port = port;
|
||||
this.serverSocket = new ServerSocket(port);
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default run: accept connections and hand off to connectionExecutor. Subclasses overriding
|
||||
* run() should still call startWorkers(Socket) for each accepted socket.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
logger.info("Server listening on port {}", port);
|
||||
try {
|
||||
while (running) {
|
||||
Socket clientSocket = serverSocket.accept();
|
||||
logger.info("Accepted connection from {}", clientSocket.getRemoteSocketAddress());
|
||||
// hand off to pool to manage I/O for this socket
|
||||
connectionExecutor.submit(() -> startWorkers(clientSocket));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (running) {
|
||||
logger.error("Accept failed", e);
|
||||
} else {
|
||||
logger.info("Server socket closed, stopping acceptor");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen/Write workers for an accepted client socket. This method submits two tasks to the
|
||||
* connectionExecutor: - inputLoop: reads lines and enqueues them to receivedQueue - outputLoop:
|
||||
* polls sendQueue and writes messages to the client
|
||||
*
|
||||
* <p>Note: This is a simple model where sendQueue is global; if you need per-client
|
||||
* send-queues, adapt this method to use one per socket.
|
||||
*/
|
||||
protected void startWorkers(Socket clientSocket) {
|
||||
try {
|
||||
BufferedReader in =
|
||||
new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
|
||||
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
|
||||
|
||||
// Input task: read lines and put them on receivedQueue
|
||||
Runnable inputTask =
|
||||
() -> {
|
||||
logger.info(
|
||||
"Starting read loop for {}", clientSocket.getRemoteSocketAddress());
|
||||
try {
|
||||
String line;
|
||||
while (running && (line = in.readLine()) != null) {
|
||||
if (line.isEmpty()) continue;
|
||||
logger.debug(
|
||||
"Received from {}: {}",
|
||||
clientSocket.getRemoteSocketAddress(),
|
||||
line);
|
||||
|
||||
boolean offered = false;
|
||||
for (int i = 0; i < RETRY_ATTEMPTS && !offered; i++) {
|
||||
try {
|
||||
// Use offer to avoid blocking indefinitely; adapt
|
||||
// timeout/policy as needed
|
||||
offered =
|
||||
this.receivedQueue.offer(
|
||||
line, 200, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!offered) {
|
||||
logger.warn(
|
||||
"Backpressure: dropping line from {}: {}",
|
||||
clientSocket.getRemoteSocketAddress(),
|
||||
line);
|
||||
// Policy choice: drop, notify, or close connection. We drop
|
||||
// here.
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.info(
|
||||
"Connection closed by remote: {}",
|
||||
clientSocket.getRemoteSocketAddress());
|
||||
} finally {
|
||||
try {
|
||||
clientSocket.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
logger.info(
|
||||
"Stopped read loop for {}",
|
||||
clientSocket.getRemoteSocketAddress());
|
||||
}
|
||||
};
|
||||
|
||||
// Output task: poll global sendQueue and write to this specific client.
|
||||
// NOTE: With a single global sendQueue, every message is sent to every connected
|
||||
// client.
|
||||
// If you want per-client sends, change this to use per-client queue map.
|
||||
Runnable outputTask =
|
||||
() -> {
|
||||
logger.info(
|
||||
"Starting write loop for {}",
|
||||
clientSocket.getRemoteSocketAddress());
|
||||
try {
|
||||
while (running && !clientSocket.isClosed()) {
|
||||
String msg = sendQueue.poll(WAIT_TIME, TimeUnit.MILLISECONDS);
|
||||
if (msg != null) {
|
||||
out.println(msg);
|
||||
out.flush();
|
||||
logger.debug(
|
||||
"Sent to {}: {}",
|
||||
clientSocket.getRemoteSocketAddress(),
|
||||
msg);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
logger.info(
|
||||
"Writer interrupted for {}",
|
||||
clientSocket.getRemoteSocketAddress());
|
||||
} catch (Exception e) {
|
||||
logger.error(
|
||||
"Writer error for {}: {}",
|
||||
clientSocket.getRemoteSocketAddress(),
|
||||
e.toString());
|
||||
} finally {
|
||||
try {
|
||||
clientSocket.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
logger.info(
|
||||
"Stopped write loop for {}",
|
||||
clientSocket.getRemoteSocketAddress());
|
||||
}
|
||||
};
|
||||
|
||||
// Input and Output mappings
|
||||
connectionExecutor.submit(inputTask);
|
||||
connectionExecutor.submit(outputTask);
|
||||
|
||||
} catch (IOException e) {
|
||||
logger.error("Could not start workers for client: {}", e.toString());
|
||||
try {
|
||||
clientSocket.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience: wrapper to obtain the latest command (non-blocking poll). Subclasses can use
|
||||
* this, but for blocking behavior consider using receivedQueue.take()
|
||||
*/
|
||||
protected ParsedCommand getNewestCommand() {
|
||||
try {
|
||||
String rec = receivedQueue.poll(WAIT_TIME, TimeUnit.MILLISECONDS);
|
||||
if (rec != null) return new ParsedCommand(rec);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
logger.warn("Interrupted while polling receivedQueue", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Stop server and cleanup executors/sockets. */
|
||||
public void stop() {
|
||||
running = false;
|
||||
|
||||
try {
|
||||
serverSocket.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
|
||||
connectionExecutor.shutdownNow();
|
||||
|
||||
logger.info(
|
||||
"TcpServer stopped. receivedQueue size={}, sendQueue size={}",
|
||||
receivedQueue.size(),
|
||||
sendQueue.size());
|
||||
}
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
package org.toop.backend.tictactoe;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.*;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.toop.game.tictactoe.TicTacToe;
|
||||
|
||||
public class TicTacToeServer extends TcpServer {
|
||||
|
||||
protected static final Logger logger = LogManager.getLogger(TicTacToeServer.class);
|
||||
|
||||
private final ExecutorService connectionExecutor =
|
||||
Executors.newCachedThreadPool(); // socket I/O
|
||||
private final ExecutorService dispatcherExecutor;
|
||||
private final ExecutorService forwarderExecutor = Executors.newSingleThreadExecutor();
|
||||
|
||||
private final BlockingQueue<ParsedCommand> incomingCommands;
|
||||
private final Map<String, TicTacToe> games = new ConcurrentHashMap<>();
|
||||
|
||||
public TicTacToeServer(int port) throws IOException {
|
||||
super(port);
|
||||
|
||||
int dispatchers = Math.max(2, Runtime.getRuntime().availableProcessors());
|
||||
this.dispatcherExecutor =
|
||||
Executors.newFixedThreadPool(
|
||||
dispatchers + 1); // TODO: Magic number for forwardMessages
|
||||
this.incomingCommands = new LinkedBlockingQueue<>(5_000);
|
||||
|
||||
forwarderExecutor.submit(this::forwardLoop);
|
||||
|
||||
for (int i = 0; i < dispatchers; i++) {
|
||||
dispatcherExecutor.submit(this::dispatchLoop);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
logger.info("TicTacToe server listening on port {}", this.port);
|
||||
|
||||
while (isRunning()) {
|
||||
Socket clientSocket = this.serverSocket.accept();
|
||||
logger.info("Connected to client: {}", clientSocket.getInetAddress());
|
||||
|
||||
connectionExecutor.submit(() -> this.startWorkers(clientSocket));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("I/O error in server run loop", e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Forwards raw messages from TcpServer.receivedQueue into ParsedCommand objects. */
|
||||
private void forwardLoop() {
|
||||
logger.info("Forwarder loop started");
|
||||
try {
|
||||
while (isRunning()) {
|
||||
String raw = this.receivedQueue.take(); // blocks
|
||||
logger.info("Received command: {}", raw);
|
||||
try {
|
||||
ParsedCommand pc = new ParsedCommand(raw);
|
||||
this.incomingCommands.put(pc); // blocks if full
|
||||
} catch (Exception e) {
|
||||
logger.warn("Invalid message ignored: {}", raw, e);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
logger.info("Forwarder loop interrupted");
|
||||
}
|
||||
}
|
||||
|
||||
/** Dispatches parsed commands into the game logic. */
|
||||
private void dispatchLoop() {
|
||||
logger.info("Dispatcher thread started");
|
||||
try {
|
||||
while (isRunning()) {
|
||||
ParsedCommand command = this.incomingCommands.take(); // blocks
|
||||
if (command.isServerCommand) {
|
||||
handleServerCommand(command);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find game by ID
|
||||
TicTacToe game = this.games.get(command.gameId);
|
||||
if (game != null) {
|
||||
game.addCommandToQueue(command);
|
||||
logger.info(
|
||||
"Dispatched command {} to game {}", command.toString(), command.gameId);
|
||||
} else {
|
||||
logger.warn(
|
||||
"No active game with ID {} for command {}",
|
||||
command.gameId,
|
||||
command.toString());
|
||||
// TODO: reply back
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
logger.info("Dispatcher interrupted");
|
||||
}
|
||||
}
|
||||
|
||||
private void handleServerCommand(ParsedCommand command) {
|
||||
if (command.isValidCommand) {
|
||||
this.sendQueue.offer("ok");
|
||||
}
|
||||
|
||||
if (command.command == TicTacToeServerCommand.CREATE_GAME) {
|
||||
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) {
|
||||
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");
|
||||
} else if (command.command == TicTacToeServerCommand.LOGIN) {
|
||||
this.endGame((String) command.arguments.getFirst());
|
||||
this.sendQueue.offer("svr login successful");
|
||||
} else if (command.command == TicTacToeServerCommand.SUBSCRIBE) {
|
||||
this.endGame((String) command.arguments.getFirst());
|
||||
this.sendQueue.offer("svr added {} to the queue");
|
||||
}
|
||||
}
|
||||
|
||||
public void forwardGameMessages(TicTacToe game) {
|
||||
dispatcherExecutor.submit(
|
||||
() -> {
|
||||
try {
|
||||
while (isRunning()) {
|
||||
String msg =
|
||||
game.sendQueue
|
||||
.take(); // blocks until a message is added to the queue
|
||||
logger.info(
|
||||
"Games: {}, Adding: {} to the send queue", game.gameId, msg);
|
||||
this.sendQueue.put(msg); // push to network layer
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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, gameId);
|
||||
this.games.put(gameId, game);
|
||||
forwardGameMessages(game);
|
||||
logger.info("Created new game: {}. {} vs {}", gameId, playerA, playerB);
|
||||
return 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;
|
||||
}
|
||||
}
|
||||
|
||||
public void endGame(String gameId) {
|
||||
TicTacToe game = this.games.remove(gameId);
|
||||
if (game != null) {
|
||||
logger.info("Ended game: {}", gameId);
|
||||
// TODO: gracefully stop game thread
|
||||
} else {
|
||||
logger.warn("Tried to end unknown game {}", gameId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package org.toop.backend.tictactoe;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
public enum TicTacToeServerCommand {
|
||||
CREATE_GAME,
|
||||
START_GAME,
|
||||
END_GAME,
|
||||
/** Login, "username" */
|
||||
LOGIN,
|
||||
/** Logout, "username" */
|
||||
LOGOUT,
|
||||
EXIT,
|
||||
QUIT,
|
||||
DISCONNECT,
|
||||
BYE,
|
||||
GET,
|
||||
SUBSCRIBE,
|
||||
MOVE,
|
||||
CHALLENGE,
|
||||
FORFEIT,
|
||||
MESSAGE,
|
||||
HELP;
|
||||
|
||||
private static final EnumSet<TicTacToeServerCommand> VALID_COMMANDS =
|
||||
EnumSet.of(
|
||||
TicTacToeServerCommand.LOGIN,
|
||||
TicTacToeServerCommand.LOGOUT,
|
||||
TicTacToeServerCommand.EXIT,
|
||||
TicTacToeServerCommand.QUIT,
|
||||
TicTacToeServerCommand.DISCONNECT,
|
||||
TicTacToeServerCommand.BYE,
|
||||
TicTacToeServerCommand.GET,
|
||||
TicTacToeServerCommand.SUBSCRIBE,
|
||||
TicTacToeServerCommand.MOVE,
|
||||
TicTacToeServerCommand.CHALLENGE,
|
||||
TicTacToeServerCommand.FORFEIT,
|
||||
TicTacToeServerCommand.MESSAGE,
|
||||
TicTacToeServerCommand.HELP);
|
||||
|
||||
public static EnumSet<TicTacToeServerCommand> getValidCommands() {
|
||||
return VALID_COMMANDS;
|
||||
}
|
||||
|
||||
// TODO: Garbage code.
|
||||
|
||||
/**
|
||||
* @param command Checks if string is a valid command.
|
||||
* @return returns a boolean if string is a valid command.
|
||||
*/
|
||||
public static boolean isValid(String command) {
|
||||
try {
|
||||
TicTacToeServerCommand.valueOf(command.toUpperCase());
|
||||
return true;
|
||||
} catch (IllegalArgumentException err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Return something better
|
||||
/**
|
||||
* @param command Converts a string into a TicTacToeServerCommand.
|
||||
* @return returns a TicTacToeServerCommand enum.
|
||||
*/
|
||||
public static TicTacToeServerCommand getCommand(String command) {
|
||||
if (isValid(command)) {
|
||||
return TicTacToeServerCommand.valueOf(command.toUpperCase());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package org.toop.backend.tictactoe;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
public enum TicTacToeServerMessage {
|
||||
OK,
|
||||
ERR,
|
||||
SVR;
|
||||
|
||||
private static final EnumSet<TicTacToeServerMessage> VALID_COMMANDS =
|
||||
EnumSet.of(
|
||||
TicTacToeServerMessage.OK,
|
||||
TicTacToeServerMessage.ERR,
|
||||
TicTacToeServerMessage.SVR);
|
||||
|
||||
public static EnumSet<TicTacToeServerMessage> getValidCommands() {
|
||||
return VALID_COMMANDS;
|
||||
}
|
||||
|
||||
// TODO: Garbage code.
|
||||
/**
|
||||
* @param command Checks if string is a valid command.
|
||||
* @return returns a boolean if string is a valid command.
|
||||
*/
|
||||
public static boolean isValid(String command) {
|
||||
try {
|
||||
TicTacToeServerMessage.valueOf(command.toUpperCase());
|
||||
return true;
|
||||
} catch (IllegalArgumentException err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Return something better
|
||||
/**
|
||||
* @param command Converts a string into a ServerCommand.
|
||||
* @return returns a ServerCommand enum.
|
||||
*/
|
||||
public static TicTacToeServerMessage getCommand(String command) {
|
||||
if (isValid(command)) {
|
||||
return TicTacToeServerMessage.valueOf(command.toUpperCase());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package org.toop.core;
|
||||
|
||||
import java.io.*;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class FileSystem {
|
||||
public record File(String path, CharSequence buffer) {}
|
||||
;
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(FileSystem.class);
|
||||
|
||||
public static File read(String path) {
|
||||
File file;
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
String line = reader.readLine();
|
||||
|
||||
while (line != null) {
|
||||
buffer.append(line);
|
||||
buffer.append(System.lineSeparator());
|
||||
line = reader.readLine();
|
||||
}
|
||||
|
||||
file = new File(path, buffer);
|
||||
} catch (IOException e) {
|
||||
logger.error("{}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package org.toop.core;
|
||||
|
||||
public interface ICallable<T> {
|
||||
public T call();
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
//package org.toop.core;
|
||||
//
|
||||
//import org.apache.logging.log4j.LogManager;
|
||||
//import org.apache.logging.log4j.Logger;
|
||||
//import org.toop.frontend.platform.core.glfw.GlfwWindow;
|
||||
//
|
||||
//public abstract class Window {
|
||||
// public enum API {
|
||||
// NONE,
|
||||
// GLFW,
|
||||
// }
|
||||
//
|
||||
// public record Size(int width, int height) {}
|
||||
//
|
||||
// protected static final Logger logger = LogManager.getLogger(Window.class);
|
||||
//
|
||||
// private static API api = API.NONE;
|
||||
// private static Window instance = null;
|
||||
//
|
||||
// public static Window setup(API api, String title, Size size) {
|
||||
// if (instance != null) {
|
||||
// logger.warn("Window is already setup.");
|
||||
// return instance;
|
||||
// }
|
||||
//
|
||||
// switch (api) {
|
||||
// case GLFW:
|
||||
// instance = new GlfwWindow(title, size);
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// logger.fatal("No valid window api chosen");
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// Window.api = api;
|
||||
// return instance;
|
||||
// }
|
||||
//
|
||||
// public static API getApi() {
|
||||
// return api;
|
||||
// }
|
||||
//
|
||||
// public void cleanup() {
|
||||
// instance = null;
|
||||
// logger.info("Window cleanup.");
|
||||
// }
|
||||
//
|
||||
// public abstract void update();
|
||||
//}
|
||||
@@ -1,42 +0,0 @@
|
||||
package org.toop.eventbus;
|
||||
|
||||
/** Wraps an event with its type and a ready flag. */
|
||||
public class EventMeta<T> {
|
||||
private final Class<T> type;
|
||||
private final Object event;
|
||||
private boolean ready;
|
||||
|
||||
public EventMeta(Class<T> type, Object event) {
|
||||
this.type = type;
|
||||
this.event = event;
|
||||
this.ready = false; // default not ready
|
||||
}
|
||||
|
||||
public Class<T> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Object getEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
return ready;
|
||||
}
|
||||
|
||||
public void setReady(boolean ready) {
|
||||
this.ready = ready;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ReadyEvent{"
|
||||
+ "type="
|
||||
+ type.getSimpleName()
|
||||
+ ", event="
|
||||
+ event
|
||||
+ ", ready="
|
||||
+ ready
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
package org.toop.eventbus;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/** Thread-safe registry for storing events and tracking readiness of event types. */
|
||||
public class EventRegistry {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(EventRegistry.class);
|
||||
|
||||
private static final Map<Class<?>, CopyOnWriteArrayList<EventEntry<?>>> eventHistory =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
private static final Map<Class<?>, Boolean> readyStates = new ConcurrentHashMap<>();
|
||||
|
||||
/** Stores an event in the registry. Safe for concurrent use. */
|
||||
public static <T> void storeEvent(EventMeta<T> eventMeta) {
|
||||
logger.info("Storing event: {}", eventMeta.toString());
|
||||
eventHistory
|
||||
.computeIfAbsent(eventMeta.getType(), k -> new CopyOnWriteArrayList<>())
|
||||
.add(new EventEntry<>(eventMeta));
|
||||
}
|
||||
|
||||
/** Marks a specific event type as ready (safe to post). */
|
||||
public static <T> void markReady(Class<T> type) {
|
||||
logger.info("Marking event as ready: {}", type.toString());
|
||||
readyStates.put(type, true);
|
||||
}
|
||||
|
||||
/** Marks a specific event type as not ready (posting will fail). */
|
||||
public static <T> void markNotReady(Class<T> type) {
|
||||
logger.info("Marking event as not ready: {}", type.toString());
|
||||
readyStates.put(type, false);
|
||||
}
|
||||
|
||||
/** Returns true if this event type is marked ready. */
|
||||
public static <T> boolean isReady(Class<T> type) {
|
||||
return readyStates.getOrDefault(type, false);
|
||||
}
|
||||
|
||||
/** Gets all stored events of a given type. */
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> List<EventEntry<T>> getEvents(Class<T> type) {
|
||||
return (List<EventEntry<T>>)
|
||||
(List<?>) eventHistory.getOrDefault(type, new CopyOnWriteArrayList<>());
|
||||
}
|
||||
|
||||
/** Gets the most recent event of a given type, or null if none exist. */
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> EventEntry<T> getLastEvent(Class<T> type) {
|
||||
List<EventEntry<?>> entries = eventHistory.get(type);
|
||||
if (entries == null || entries.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return (EventEntry<T>) entries.getLast();
|
||||
}
|
||||
|
||||
/** Clears the stored events for a given type. */
|
||||
public static <T> void clearEvents(Class<T> type) {
|
||||
logger.info("Clearing events: {}", type.toString());
|
||||
eventHistory.remove(type);
|
||||
}
|
||||
|
||||
/** Clears all events and resets readiness. */
|
||||
public static void reset() {
|
||||
logger.info("Resetting event registry events");
|
||||
eventHistory.clear();
|
||||
readyStates.clear();
|
||||
}
|
||||
|
||||
/** Wrapper for stored events, with a ready flag for per-event state. */
|
||||
public static class EventEntry<T> {
|
||||
private final T event;
|
||||
private volatile boolean ready = false;
|
||||
|
||||
public EventEntry(T event) {
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
public T getEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
return ready;
|
||||
}
|
||||
|
||||
public void setReady(boolean ready) {
|
||||
this.ready = ready;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EventEntry{" + "event=" + event + ", ready=" + ready + '}';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
//package org.toop.frontend.graphics;
|
||||
//
|
||||
//import org.apache.logging.log4j.LogManager;
|
||||
//import org.apache.logging.log4j.Logger;
|
||||
//import org.toop.frontend.platform.graphics.opengl.OpenglRenderer;
|
||||
//
|
||||
//public abstract class Renderer {
|
||||
// public enum API {
|
||||
// NONE,
|
||||
// OPENGL,
|
||||
// };
|
||||
//
|
||||
// protected static final Logger logger = LogManager.getLogger(Renderer.class);
|
||||
//
|
||||
// private static API api = API.NONE;
|
||||
// private static Renderer instance = null;
|
||||
//
|
||||
// public static Renderer setup(API api) {
|
||||
// if (instance != null) {
|
||||
// logger.warn("Renderer is already setup.");
|
||||
// return instance;
|
||||
// }
|
||||
//
|
||||
// switch (api) {
|
||||
// case OPENGL:
|
||||
// instance = new OpenglRenderer();
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// logger.fatal("No valid renderer api chosen");
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// Renderer.api = api;
|
||||
// return instance;
|
||||
// }
|
||||
//
|
||||
// public static API getApi() {
|
||||
// return api;
|
||||
// }
|
||||
//
|
||||
// public void cleanup() {
|
||||
// instance = null;
|
||||
// logger.info("Renderer cleanup.");
|
||||
// }
|
||||
//
|
||||
// public abstract void clear();
|
||||
//
|
||||
// public abstract void render();
|
||||
//}
|
||||
@@ -1,27 +0,0 @@
|
||||
//package org.toop.frontend.graphics;
|
||||
//
|
||||
//import org.toop.frontend.platform.graphics.opengl.OpenglShader;
|
||||
//
|
||||
//public abstract class Shader {
|
||||
// public static Shader create(String vertexPath, String fragmentPath) {
|
||||
// Shader shader = null;
|
||||
//
|
||||
// switch (Renderer.getApi()) {
|
||||
// case OPENGL:
|
||||
// shader = new OpenglShader(vertexPath, fragmentPath);
|
||||
// break;
|
||||
//
|
||||
// case NONE:
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// return shader;
|
||||
// }
|
||||
//
|
||||
// public abstract void cleanup();
|
||||
//
|
||||
// public abstract void start();
|
||||
//
|
||||
// public abstract void stop();
|
||||
//}
|
||||
@@ -1,33 +0,0 @@
|
||||
package org.toop.frontend.graphics.node;
|
||||
|
||||
import org.toop.core.*;
|
||||
import org.toop.frontend.math.Color;
|
||||
|
||||
public class Button extends Node {
|
||||
ICallable<Boolean> onHover;
|
||||
ICallable<Boolean> onClick;
|
||||
|
||||
public Button(
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
Color color,
|
||||
ICallable<Boolean> onHover,
|
||||
ICallable<Boolean> onClick) {
|
||||
super(x, y, width, height, color);
|
||||
|
||||
this.onHover = onHover;
|
||||
this.onClick = onClick;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hover() {
|
||||
onHover.call();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click() {
|
||||
onClick.call();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package org.toop.frontend.graphics.node;
|
||||
|
||||
import org.toop.frontend.math.Bounds;
|
||||
import org.toop.frontend.math.Color;
|
||||
|
||||
public abstract class Node {
|
||||
protected Bounds bounds;
|
||||
protected Color color;
|
||||
|
||||
public Node(int x, int y, int width, int height, Color color) {
|
||||
bounds = new Bounds(x, y, width, height);
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public boolean check(int x, int y) {
|
||||
return bounds.check(x, y);
|
||||
}
|
||||
|
||||
public void hover() {}
|
||||
|
||||
public void click() {}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
//package org.toop.frontend.graphics.node;
|
||||
//
|
||||
//import java.util.*;
|
||||
//import org.apache.logging.log4j.LogManager;
|
||||
//import org.apache.logging.log4j.Logger;
|
||||
//import org.toop.eventbus.*;
|
||||
//import org.toop.eventbus.events.Events;
|
||||
//import org.toop.frontend.graphics.Shader;
|
||||
//
|
||||
//public class NodeManager {
|
||||
// private static final Logger logger = LogManager.getLogger(NodeManager.class);
|
||||
//
|
||||
// private static NodeManager instance = null;
|
||||
//
|
||||
// public static NodeManager setup() {
|
||||
// if (instance != null) {
|
||||
// logger.warn("NodeManager is already setup.");
|
||||
// return instance;
|
||||
// }
|
||||
//
|
||||
// instance = new NodeManager();
|
||||
// return instance;
|
||||
// }
|
||||
//
|
||||
// private Shader shader;
|
||||
// private ArrayList<Node> nodes;
|
||||
// private Node active;
|
||||
//
|
||||
// private NodeManager() {
|
||||
// shader =
|
||||
// Shader.create(
|
||||
// "src/main/resources/shaders/gui_vertex.glsl",
|
||||
// "src/main/resources/shaders/gui_fragment.glsl");
|
||||
//
|
||||
// nodes = new ArrayList<Node>();
|
||||
//
|
||||
// GlobalEventBus.subscribeAndRegister(
|
||||
// Events.WindowEvents.OnMouseMove.class,
|
||||
// event -> {
|
||||
// for (int i = 0; i < nodes.size(); i++) {
|
||||
// Node node = nodes.get(i);
|
||||
//
|
||||
// if (node.check(event.x(), event.y())) {
|
||||
// active = node;
|
||||
// node.hover();
|
||||
//
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// GlobalEventBus.subscribeAndRegister(
|
||||
// Events.WindowEvents.OnMouseClick.class,
|
||||
// event -> {
|
||||
// if (active != null) {
|
||||
// active.click();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// public void cleanup() {}
|
||||
//
|
||||
// public void add(Node node) {
|
||||
// nodes.add(node);
|
||||
// }
|
||||
//
|
||||
// public void render() {}
|
||||
//}
|
||||
@@ -1,48 +0,0 @@
|
||||
package org.toop.frontend.graphics.node;
|
||||
|
||||
import java.util.*;
|
||||
import org.toop.frontend.math.Bounds;
|
||||
|
||||
public class Widget {
|
||||
Bounds bounds;
|
||||
private ArrayList<Node> nodes;
|
||||
|
||||
public Widget(Bounds bounds) {
|
||||
this.bounds = bounds;
|
||||
nodes = new ArrayList<Node>();
|
||||
}
|
||||
|
||||
public boolean check(int x, int y) {
|
||||
return bounds.check(x, y);
|
||||
}
|
||||
|
||||
public void add(Node node) {
|
||||
nodes.add(node);
|
||||
}
|
||||
|
||||
public boolean hover(int x, int y) {
|
||||
for (int i = 0; i < nodes.size(); i++) {
|
||||
Node node = nodes.get(i);
|
||||
|
||||
if (node.check(x, y)) {
|
||||
node.hover();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean click(int x, int y) {
|
||||
for (int i = 0; i < nodes.size(); i++) {
|
||||
Node node = nodes.get(i);
|
||||
|
||||
if (node.check(x, y)) {
|
||||
node.click();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package org.toop.frontend.math;
|
||||
|
||||
public class Bounds {
|
||||
private int x;
|
||||
private int y;
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
public Bounds(int x, int y, int width, int height) {
|
||||
set(x, y, width, height);
|
||||
}
|
||||
|
||||
public void set(int x, int y, int width, int height) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public boolean check(int x, int y) {
|
||||
return x >= this.x && x <= this.x + this.width && y >= this.y && y <= this.y + this.height;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package org.toop.frontend.math;
|
||||
|
||||
public class Color {
|
||||
private float r;
|
||||
private float g;
|
||||
private float b;
|
||||
|
||||
public Color(float r, float g, float b) {
|
||||
this.r = r;
|
||||
this.g = g;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public float r() {
|
||||
return r;
|
||||
}
|
||||
|
||||
public float g() {
|
||||
return g;
|
||||
}
|
||||
|
||||
public float b() {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
package org.toop.frontend.networking;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.util.concurrent.*;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.toop.eventbus.EventPublisher;
|
||||
import org.toop.eventbus.events.Events;
|
||||
import org.toop.eventbus.GlobalEventBus;
|
||||
import org.toop.eventbus.events.NetworkEvents;
|
||||
|
||||
public final class ServerConnection extends TcpClient implements Runnable {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(ServerConnection.class);
|
||||
|
||||
private final BlockingQueue<String> receivedQueue = new LinkedBlockingQueue<>();
|
||||
private final BlockingQueue<String> sendQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(2);
|
||||
|
||||
String uuid;
|
||||
volatile boolean running = false;
|
||||
|
||||
public ServerConnection(String uuid, String ip, String port) throws IOException {
|
||||
super(ip, Integer.parseInt(port));
|
||||
this.uuid = uuid;
|
||||
this.initEvents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a command to the server.
|
||||
*
|
||||
* @param args The arguments for the command.
|
||||
*/
|
||||
public void sendCommandByString(String... args) {
|
||||
// if (!TicTacToeServerCommand.isValid(command)) {
|
||||
// logger.error("Invalid command: {}", command);
|
||||
// return;
|
||||
// } // TODO: DO I CARE?
|
||||
|
||||
// if (!this.running) {
|
||||
// logger.warn("Server has been stopped");
|
||||
// return;
|
||||
// } // TODO: Server not running
|
||||
|
||||
String command = String.join(" ", args);
|
||||
|
||||
this.sendQueue.add(command);
|
||||
logger.info("Command '{}' added to the queue", command); // TODO: Better log, which uuid?
|
||||
}
|
||||
|
||||
private void addReceivedMessageToQueue(String message) {
|
||||
try {
|
||||
receivedQueue.put(message);
|
||||
} catch (InterruptedException e) {
|
||||
logger.error("{}", e); // TODO: Make more informative
|
||||
}
|
||||
}
|
||||
|
||||
private void initEvents() {}
|
||||
|
||||
private void startWorkers() {
|
||||
running = true;
|
||||
this.executor.submit(this::inputLoop);
|
||||
this.executor.submit(this::outputLoop);
|
||||
}
|
||||
|
||||
private void stopWorkers() {
|
||||
this.running = false;
|
||||
this.sendQueue.clear();
|
||||
try {
|
||||
this.closeSocket();
|
||||
} catch (IOException e) {
|
||||
logger.warn("Error closing client socket", e); // TODO: Better log
|
||||
}
|
||||
|
||||
this.executor.shutdownNow();
|
||||
}
|
||||
|
||||
void inputLoop() {
|
||||
logger.info("Starting {}:{} connection read", this.serverAddress, this.serverPort);
|
||||
try {
|
||||
while (running) {
|
||||
String received = this.readLine(); // blocks
|
||||
if (received != null) {
|
||||
logger.info("Connection: {} received: '{}'", this.uuid, received);
|
||||
// this.addReceivedMessageToQueue(received); // TODO: Will never go empty
|
||||
new EventPublisher<>(NetworkEvents.ReceivedMessage.class, this.uuid, received).postEvent();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("Error reading from server", e);
|
||||
}
|
||||
}
|
||||
|
||||
void outputLoop() {
|
||||
logger.info("Starting {}:{} connection write", this.serverAddress, this.serverPort);
|
||||
try {
|
||||
while (this.running) {
|
||||
String command = this.sendQueue.poll(500, TimeUnit.MILLISECONDS);
|
||||
if (command != null) {
|
||||
this.sendMessage(command);
|
||||
logger.info("Sent command: '{}'", command);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (IOException e) {
|
||||
logger.error("Error sending command", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a new server.
|
||||
*
|
||||
* @param ip The ip to connect to.
|
||||
* @param port The port to connect to.
|
||||
*/
|
||||
public void connect(InetAddress ip, int port) {
|
||||
if (this.running) {
|
||||
this.closeConnection(); // Also stops workers.
|
||||
}
|
||||
|
||||
this.serverAddress = ip;
|
||||
this.serverPort = port;
|
||||
|
||||
this.startWorkers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconnects to previous address.
|
||||
*
|
||||
* @throws IOException wip
|
||||
*/
|
||||
public void reconnect() throws IOException {
|
||||
this.connect(this.serverAddress, this.serverPort);
|
||||
}
|
||||
|
||||
/** Close connection to server. */
|
||||
public void closeConnection() {
|
||||
this.stopWorkers();
|
||||
logger.info(
|
||||
"Closed connection: {}, to server {}:{}",
|
||||
this.uuid,
|
||||
this.serverAddress,
|
||||
this.serverPort);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
reconnect();
|
||||
} catch (IOException e) {
|
||||
logger.error("Initial connection failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"Server {ip: \"%s\", port: \"%s\", running: %s}",
|
||||
this.serverAddress, this.serverPort, this.running);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package org.toop.frontend.networking;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
/** A simple wrapper for creating TCP clients. */
|
||||
public abstract class TcpClient {
|
||||
|
||||
InetAddress serverAddress;
|
||||
int serverPort;
|
||||
Socket socket;
|
||||
BufferedReader in;
|
||||
PrintWriter out;
|
||||
|
||||
public TcpClient(byte[] serverIp, int serverPort) throws IOException {
|
||||
this.serverAddress = InetAddress.getByAddress(serverIp);
|
||||
this.serverPort = serverPort;
|
||||
this.socket = createSocket();
|
||||
this.in = createIn();
|
||||
this.out = createOut();
|
||||
}
|
||||
|
||||
public TcpClient(String serverIp, int serverPort) throws IOException {
|
||||
this.serverAddress = InetAddress.getByName(serverIp);
|
||||
this.serverPort = serverPort;
|
||||
this.socket = createSocket();
|
||||
this.in = createIn();
|
||||
this.out = createOut();
|
||||
}
|
||||
|
||||
public Socket createSocket() throws IOException {
|
||||
return new Socket(serverAddress, serverPort);
|
||||
}
|
||||
|
||||
public void closeSocket() throws IOException {
|
||||
this.socket.close();
|
||||
}
|
||||
|
||||
BufferedReader createIn() throws IOException {
|
||||
return new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
|
||||
}
|
||||
|
||||
PrintWriter createOut() throws IOException {
|
||||
return new PrintWriter(this.socket.getOutputStream(), true);
|
||||
}
|
||||
|
||||
public void sendMessage(String message) throws IOException {
|
||||
this.out.println(message);
|
||||
}
|
||||
|
||||
public String readLine() throws IOException {
|
||||
return this.in.readLine();
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
this.socket.close();
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
//package org.toop.frontend.platform.core.glfw;
|
||||
//
|
||||
//import org.lwjgl.glfw.*;
|
||||
//import org.lwjgl.system.*;
|
||||
//import org.toop.core.*;
|
||||
//import org.toop.eventbus.*;
|
||||
//import org.toop.eventbus.events.Events;
|
||||
//
|
||||
//public class GlfwWindow extends Window {
|
||||
// private long window;
|
||||
//
|
||||
// public GlfwWindow(String title, Size size) {
|
||||
// if (!GLFW.glfwInit()) {
|
||||
// logger.fatal("Failed to initialize glfw");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// GLFW.glfwDefaultWindowHints();
|
||||
// GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE);
|
||||
// GLFW.glfwWindowHint(GLFW.GLFW_RESIZABLE, GLFW.GLFW_TRUE);
|
||||
//
|
||||
// GLFWVidMode videoMode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor());
|
||||
//
|
||||
// int width = size.width();
|
||||
// int height = size.height();
|
||||
//
|
||||
// if (width <= 0 || height <= 0 || width > videoMode.width() || height > videoMode.height()) {
|
||||
// width = videoMode.width();
|
||||
// height = videoMode.height();
|
||||
//
|
||||
// GLFW.glfwWindowHint(GLFW.GLFW_MAXIMIZED, GLFW.GLFW_TRUE);
|
||||
// }
|
||||
//
|
||||
// long window = GLFW.glfwCreateWindow(width, height, title, MemoryUtil.NULL, MemoryUtil.NULL);
|
||||
//
|
||||
// if (window == MemoryUtil.NULL) {
|
||||
// GLFW.glfwTerminate();
|
||||
//
|
||||
// logger.fatal("Failed to create glfw window");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// int[] widthBuffer = new int[1];
|
||||
// int[] heightBuffer = new int[1];
|
||||
// GLFW.glfwGetWindowSize(window, widthBuffer, heightBuffer);
|
||||
//
|
||||
// GLFW.glfwMakeContextCurrent(window);
|
||||
// GLFW.glfwSwapInterval(1);
|
||||
//
|
||||
// GLFW.glfwSetWindowCloseCallback(
|
||||
// window,
|
||||
// (lwindow) -> {
|
||||
// GlobalEventBus.post(new Events.WindowEvents.OnQuitRequested());
|
||||
// });
|
||||
//
|
||||
// GLFW.glfwSetFramebufferSizeCallback(
|
||||
// window,
|
||||
// (lwindow, lwidth, lheight) -> {
|
||||
// GlobalEventBus.post(
|
||||
// new Events.WindowEvents.OnResize(new Size(lwidth, lheight)));
|
||||
// });
|
||||
//
|
||||
// GLFW.glfwSetCursorPosCallback(
|
||||
// window,
|
||||
// (lwindow, lx, ly) -> {
|
||||
// GlobalEventBus.post(new Events.WindowEvents.OnMouseMove((int) lx, (int) ly));
|
||||
// });
|
||||
//
|
||||
// GLFW.glfwSetMouseButtonCallback(
|
||||
// window,
|
||||
// (lwindow, lbutton, laction, lmods) -> {
|
||||
// switch (laction) {
|
||||
// case GLFW.GLFW_PRESS:
|
||||
// GlobalEventBus.post(new Events.WindowEvents.OnMouseClick(lbutton));
|
||||
// break;
|
||||
//
|
||||
// case GLFW.GLFW_RELEASE:
|
||||
// GlobalEventBus.post(new Events.WindowEvents.OnMouseRelease(lbutton));
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// this.window = window;
|
||||
// GLFW.glfwShowWindow(window);
|
||||
//
|
||||
// logger.info(
|
||||
// "Glfw window setup. Title: {}. Width: {}. Height: {}.",
|
||||
// title,
|
||||
// size.width(),
|
||||
// size.height());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void cleanup() {
|
||||
// GLFW.glfwDestroyWindow(window);
|
||||
// GLFW.glfwTerminate();
|
||||
//
|
||||
// super.cleanup();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void update() {
|
||||
// GLFW.glfwSwapBuffers(window);
|
||||
// GLFW.glfwPollEvents();
|
||||
// }
|
||||
//}
|
||||
@@ -1,79 +0,0 @@
|
||||
//package org.toop.frontend.platform.graphics.opengl;
|
||||
//
|
||||
//import org.lwjgl.opengl.*;
|
||||
//import org.lwjgl.system.*;
|
||||
//import org.toop.eventbus.*;
|
||||
//import org.toop.eventbus.events.Events;
|
||||
//import org.toop.frontend.graphics.Renderer;
|
||||
//import org.toop.frontend.graphics.Shader;
|
||||
//
|
||||
//public class OpenglRenderer extends Renderer {
|
||||
// private Shader shader;
|
||||
// private int vao;
|
||||
//
|
||||
// public OpenglRenderer() {
|
||||
// GL.createCapabilities();
|
||||
// GL45.glClearColor(0.65f, 0.9f, 0.65f, 1f);
|
||||
//
|
||||
// GlobalEventBus.subscribeAndRegister(
|
||||
// Events.WindowEvents.OnResize.class,
|
||||
// event -> {
|
||||
// GL45.glViewport(0, 0, event.size().width(), event.size().height());
|
||||
// });
|
||||
//
|
||||
// logger.info("Opengl renderer setup.");
|
||||
//
|
||||
// // Form here on, everything is temporary
|
||||
// float vertices[] = {
|
||||
// -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
// -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
// 0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
|
||||
// 0.5f, 0.5f, 1.0f, 1.0f, 0.0f,
|
||||
// };
|
||||
//
|
||||
// int indicies[] = {
|
||||
// 0, 1, 2,
|
||||
// 2, 3, 0,
|
||||
// };
|
||||
//
|
||||
// vao = GL45.glCreateVertexArrays();
|
||||
// GL45.glBindVertexArray(vao);
|
||||
//
|
||||
// int vbo = GL45.glCreateBuffers();
|
||||
// GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, vbo);
|
||||
// GL45.glBufferData(GL45.GL_ARRAY_BUFFER, vertices, GL45.GL_STATIC_DRAW);
|
||||
//
|
||||
// GL45.glVertexAttribPointer(0, 2, GL45.GL_FLOAT, false, 5 * 4, 0);
|
||||
// GL45.glVertexAttribPointer(1, 3, GL45.GL_FLOAT, false, 5 * 4, 2 * 4);
|
||||
//
|
||||
// GL45.glEnableVertexAttribArray(0);
|
||||
// GL45.glEnableVertexAttribArray(1);
|
||||
//
|
||||
// int ib = GL45.glCreateBuffers();
|
||||
// GL45.glBindBuffer(GL45.GL_ELEMENT_ARRAY_BUFFER, ib);
|
||||
// GL45.glBufferData(GL45.GL_ELEMENT_ARRAY_BUFFER, indicies, GL45.GL_STATIC_DRAW);
|
||||
//
|
||||
// shader =
|
||||
// Shader.create(
|
||||
// "src/main/resources/shaders/gui_vertex.glsl",
|
||||
// "src/main/resources/shaders/gui_fragment.glsl");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void cleanup() {
|
||||
// super.cleanup();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void clear() {
|
||||
// GL45.glClear(GL45.GL_COLOR_BUFFER_BIT);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void render() {
|
||||
// // temporary
|
||||
// // shader.start();
|
||||
// GL45.glBindVertexArray(vao);
|
||||
// GL45.glDrawElements(GL45.GL_TRIANGLES, 6, GL45.GL_UNSIGNED_INT, MemoryUtil.NULL);
|
||||
// }
|
||||
//}
|
||||
@@ -1,57 +0,0 @@
|
||||
//package org.toop.frontend.platform.graphics.opengl;
|
||||
//
|
||||
//import org.lwjgl.opengl.*;
|
||||
//import org.toop.core.*;
|
||||
//import org.toop.frontend.graphics.Shader;
|
||||
//
|
||||
//public class OpenglShader extends Shader {
|
||||
// private int programID;
|
||||
//
|
||||
// public OpenglShader(String vertexPath, String fragmentPath) {
|
||||
// FileSystem.File vertexSource = FileSystem.read(vertexPath);
|
||||
// FileSystem.File fragmentSource = FileSystem.read(fragmentPath);
|
||||
//
|
||||
// if (vertexSource == null || fragmentPath == null) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// programID = GL45.glCreateProgram();
|
||||
//
|
||||
// int vertexShader = GL45.glCreateShader(GL45.GL_VERTEX_SHADER);
|
||||
// int fragmentShader = GL45.glCreateShader(GL45.GL_FRAGMENT_SHADER);
|
||||
//
|
||||
// GL45.glShaderSource(vertexShader, vertexSource.buffer());
|
||||
// GL45.glShaderSource(fragmentShader, fragmentSource.buffer());
|
||||
//
|
||||
// GL45.glCompileShader(vertexShader);
|
||||
// GL45.glCompileShader(fragmentShader);
|
||||
//
|
||||
// GL45.glAttachShader(programID, vertexShader);
|
||||
// GL45.glAttachShader(programID, fragmentShader);
|
||||
//
|
||||
// GL45.glLinkProgram(programID);
|
||||
// GL45.glValidateProgram(programID);
|
||||
//
|
||||
// GL45.glDetachShader(programID, vertexShader);
|
||||
// GL45.glDetachShader(programID, fragmentShader);
|
||||
//
|
||||
// GL45.glDeleteShader(vertexShader);
|
||||
// GL45.glDeleteShader(fragmentShader);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void cleanup() {
|
||||
// stop();
|
||||
// GL45.glDeleteProgram(programID);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void start() {
|
||||
// GL45.glUseProgram(programID);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void stop() {
|
||||
// GL45.glUseProgram(0);
|
||||
// }
|
||||
//}
|
||||
Reference in New Issue
Block a user