mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 10:54:51 +00:00
Refactor and fixes
This commit is contained in:
2
.idea/encodings.xml
generated
2
.idea/encodings.xml
generated
@@ -1,6 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="Encoding">
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/app/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/app/src/main/resources" charset="UTF-8" />
|
||||||
<file url="file://$PROJECT_DIR$/framework/src/main/java" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/framework/src/main/java" charset="UTF-8" />
|
||||||
<file url="file://$PROJECT_DIR$/framework/src/main/resources" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/framework/src/main/resources" charset="UTF-8" />
|
||||||
<file url="file://$PROJECT_DIR$/game/src/main/java" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/game/src/main/java" charset="UTF-8" />
|
||||||
|
|||||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -13,7 +13,7 @@
|
|||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_24" project-jdk-name="openjdk-25" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_X" default="true" project-jdk-name="openjdk-25" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
15
app/pom.xml
15
app/pom.xml
@@ -7,6 +7,10 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<main-class>org.toop.Main</main-class>
|
<main-class>org.toop.Main</main-class>
|
||||||
|
<maven.compiler.source>25</maven.compiler.source>
|
||||||
|
<maven.compiler.target>25</maven.compiler.target>
|
||||||
|
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -15,17 +19,22 @@
|
|||||||
<version>0.1</version>
|
<version>0.1</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.toop</groupId>
|
||||||
|
<artifactId>pism_game</artifactId>
|
||||||
|
<version>0.1</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>16</source>
|
<source>25</source>
|
||||||
<target>16</target>
|
<target>25</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
package org.toop;
|
package org.toop;
|
||||||
|
|
||||||
|
import org.toop.framework.networking.NetworkingClientManager;
|
||||||
|
import org.toop.framework.networking.NetworkingInitializationException;
|
||||||
|
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
initSystems();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void initSystems() throws NetworkingInitializationException {
|
||||||
|
new NetworkingClientManager();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
package org.toop.app.gui;
|
package org.toop.app.gui;
|
||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.util.Objects;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.function.Supplier;
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
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.framework.eventbus.events.Events;
|
import org.toop.framework.eventbus.EventFlow;
|
||||||
import org.toop.framework.eventbus.GlobalEventBus;
|
|
||||||
import org.toop.framework.eventbus.events.NetworkEvents;
|
import org.toop.framework.eventbus.events.NetworkEvents;
|
||||||
import org.toop.tictactoe.LocalTicTacToe;
|
import org.toop.tictactoe.LocalTicTacToe;
|
||||||
import org.toop.framework.networking.NetworkingGameClientHandler;
|
import org.toop.framework.networking.NetworkingGameClientHandler;
|
||||||
@@ -56,35 +54,18 @@ public class RemoteGameSelector {
|
|||||||
&& !ipTextField.getText().isEmpty()
|
&& !ipTextField.getText().isEmpty()
|
||||||
&& !portTextField.getText().isEmpty()) {
|
&& !portTextField.getText().isEmpty()) {
|
||||||
|
|
||||||
CompletableFuture<String> serverIdFuture = new CompletableFuture<>();
|
AtomicReference<String> clientId = new AtomicReference<>();
|
||||||
GlobalEventBus.post(
|
new EventFlow().addPostEvent(
|
||||||
new Events.ServerEvents.StartServerRequest(
|
NetworkEvents.StartClient.class,
|
||||||
Integer.parseInt(portTextField.getText()), // TODO: Unsafe parse
|
(Supplier<NetworkingGameClientHandler>) NetworkingGameClientHandler::new,
|
||||||
Objects.requireNonNull(gameSelectorBox.getSelectedItem())
|
"127.0.0.1",
|
||||||
.toString()
|
5001
|
||||||
.toLowerCase()
|
).onResponse(
|
||||||
.replace(" ", ""),
|
NetworkEvents.StartClientSuccess.class,
|
||||||
serverIdFuture));
|
(response) -> {
|
||||||
String serverId;
|
clientId.set(response.clientId());
|
||||||
try {
|
}
|
||||||
serverId = serverIdFuture.get();
|
).asyncPostEvent();
|
||||||
} catch (InterruptedException | ExecutionException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
} // TODO: Better error handling to not crash the system.
|
|
||||||
|
|
||||||
CompletableFuture<String> connectionIdFuture = new CompletableFuture<>();
|
|
||||||
GlobalEventBus.post(
|
|
||||||
new NetworkEvents.StartClientRequest(
|
|
||||||
NetworkingGameClientHandler::new,
|
|
||||||
ipTextField.getText(),
|
|
||||||
Integer.parseInt(portTextField.getText()), // TODO: Not safe parsing
|
|
||||||
connectionIdFuture));
|
|
||||||
String connectionId;
|
|
||||||
try {
|
|
||||||
connectionId = connectionIdFuture.get();
|
|
||||||
} catch (InterruptedException | ExecutionException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
} // TODO: Better error handling to not crash the system.
|
|
||||||
|
|
||||||
// GlobalEventBus.subscribeAndRegister(
|
// GlobalEventBus.subscribeAndRegister(
|
||||||
// NetworkEvents.ReceivedMessage.class,
|
// NetworkEvents.ReceivedMessage.class,
|
||||||
@@ -103,35 +84,7 @@ public class RemoteGameSelector {
|
|||||||
// logger.info("{}", event.message());
|
// logger.info("{}", event.message());
|
||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
|
|
||||||
GlobalEventBus.post(
|
|
||||||
new Events.ServerEvents.SendCommand(
|
|
||||||
connectionId,
|
|
||||||
"create_game",
|
|
||||||
nameTextField.getText(),
|
|
||||||
name2TextField.getText()));
|
|
||||||
|
|
||||||
// CompletableFuture<String> ticTacToeGame = new
|
|
||||||
// CompletableFuture<>();
|
|
||||||
// GlobalEventBus.post(new
|
|
||||||
// Events.ServerEvents.CreateTicTacToeGameRequest( // TODO: Make this happen
|
|
||||||
// through commands send through the connection, instead of an event.
|
|
||||||
// serverId,
|
|
||||||
// nameTextField.getText(),
|
|
||||||
// name2TextField.getText(),
|
|
||||||
// ticTacToeGame
|
|
||||||
// ));
|
|
||||||
// String ticTacToeGameId;
|
|
||||||
// try {
|
|
||||||
// ticTacToeGameId = ticTacToeGame.get();
|
|
||||||
// } catch (InterruptedException | ExecutionException ex) {
|
|
||||||
// throw new RuntimeException(ex);
|
|
||||||
// } // TODO: Better error handling to not crash the system.
|
|
||||||
|
|
||||||
frame.remove(mainMenu);
|
frame.remove(mainMenu);
|
||||||
localTicTacToe =
|
|
||||||
LocalTicTacToe.createRemote(
|
|
||||||
ipTextField.getText(), portTextField.getText());
|
|
||||||
UIGameBoard ttt = new UIGameBoard(localTicTacToe, this);
|
UIGameBoard ttt = new UIGameBoard(localTicTacToe, this);
|
||||||
localTicTacToe.startThreads();
|
localTicTacToe.startThreads();
|
||||||
frame.add(ttt.getTTTPanel()); // TODO: Fix later
|
frame.add(ttt.getTTTPanel()); // TODO: Fix later
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import java.util.concurrent.*;
|
|||||||
|
|
||||||
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.framework.eventbus.EventPublisher;
|
import org.toop.framework.eventbus.EventFlow;
|
||||||
import org.toop.framework.eventbus.events.Events;
|
import org.toop.framework.eventbus.events.Events;
|
||||||
import org.toop.framework.eventbus.events.NetworkEvents;
|
import org.toop.framework.eventbus.events.NetworkEvents;
|
||||||
|
import org.toop.game.GameBase;
|
||||||
import org.toop.tictactoe.gui.UIGameBoard;
|
import org.toop.tictactoe.gui.UIGameBoard;
|
||||||
import org.toop.framework.networking.NetworkingGameClientHandler;
|
import org.toop.framework.networking.NetworkingGameClientHandler;
|
||||||
import org.toop.game.GameBase;
|
import org.toop.tictactoe.TicTacToeAI;
|
||||||
import org.toop.game.tictactoe.ai.MinMaxTicTacToe;
|
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ public class LocalTicTacToe { // TODO: Implement runnable
|
|||||||
private String serverId = null;
|
private String serverId = null;
|
||||||
|
|
||||||
private boolean isAiPlayer[] = new boolean[2];
|
private boolean isAiPlayer[] = new boolean[2];
|
||||||
private MinMaxTicTacToe[] aiPlayers = new MinMaxTicTacToe[2];
|
private TicTacToeAI[] aiPlayers = new TicTacToeAI[2];
|
||||||
private TicTacToe ticTacToe;
|
private TicTacToe ticTacToe;
|
||||||
private UIGameBoard ui;
|
private UIGameBoard ui;
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ public class LocalTicTacToe { // TODO: Implement runnable
|
|||||||
|
|
||||||
for (int i = 0; i < aiFlags.length && i < this.aiPlayers.length; i++) {
|
for (int i = 0; i < aiFlags.length && i < this.aiPlayers.length; i++) {
|
||||||
if (aiFlags[i]) {
|
if (aiFlags[i]) {
|
||||||
this.aiPlayers[i] = new MinMaxTicTacToe(); // create AI for that player
|
this.aiPlayers[i] = new TicTacToeAI(); // create AI for that player
|
||||||
} else {
|
} else {
|
||||||
this.aiPlayers[i] = null; // not an AI player
|
this.aiPlayers[i] = null; // not an AI player
|
||||||
}
|
}
|
||||||
@@ -110,23 +110,11 @@ public class LocalTicTacToe { // TODO: Implement runnable
|
|||||||
return new LocalTicTacToe(ip, port);
|
return new LocalTicTacToe(ip, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createServer(int port) {
|
|
||||||
CompletableFuture<String> serverIdFuture = new CompletableFuture<>();
|
|
||||||
new EventPublisher<>(Events.ServerEvents.StartServerRequest.class, port, "tictactoe", serverIdFuture)
|
|
||||||
.postEvent();
|
|
||||||
try {
|
|
||||||
return serverIdFuture.get();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("Error getting server ID", e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String createConnection(String ip, int port) {
|
private String createConnection(String ip, int port) {
|
||||||
CompletableFuture<String> connectionIdFuture = new CompletableFuture<>();
|
CompletableFuture<String> connectionIdFuture = new CompletableFuture<>();
|
||||||
new EventPublisher<>(NetworkEvents.StartClientRequest.class,
|
new EventFlow().addPostEvent(NetworkEvents.StartClientRequest.class,
|
||||||
(Supplier<NetworkingGameClientHandler>) NetworkingGameClientHandler::new,
|
(Supplier<NetworkingGameClientHandler>) NetworkingGameClientHandler::new,
|
||||||
ip, port, connectionIdFuture).postEvent(); // TODO: what if server couldn't be started with port.
|
ip, port, connectionIdFuture).asyncPostEvent(); // TODO: what if server couldn't be started with port.
|
||||||
try {
|
try {
|
||||||
return connectionIdFuture.get();
|
return connectionIdFuture.get();
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
@@ -258,7 +246,7 @@ public class LocalTicTacToe { // TODO: Implement runnable
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sendCommand(String... args) {
|
private void sendCommand(String... args) {
|
||||||
new EventPublisher<>(NetworkEvents.SendCommand.class, this.connectionId, args).postEvent();
|
new EventFlow().addPostEvent(NetworkEvents.SendCommand.class, this.connectionId, args).asyncPostEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
// private void endListeners() {
|
// private void endListeners() {
|
||||||
|
|||||||
@@ -86,4 +86,17 @@
|
|||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>25</source>
|
||||||
|
<target>25</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package org.toop.framework.eventbus;
|
package org.toop.framework.eventbus;
|
||||||
|
|
||||||
|
import org.toop.framework.eventbus.events.EventType;
|
||||||
import org.toop.framework.eventbus.events.EventWithUuid;
|
import org.toop.framework.eventbus.events.EventWithUuid;
|
||||||
import org.toop.framework.eventbus.events.IEvent;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
@@ -32,7 +32,7 @@ public class EventFlow {
|
|||||||
private String eventId = null;
|
private String eventId = null;
|
||||||
|
|
||||||
/** The event instance created by this publisher. */
|
/** The event instance created by this publisher. */
|
||||||
private IEvent event = null;
|
private EventType event = null;
|
||||||
|
|
||||||
/** The listener returned by GlobalEventBus subscription. Used for unsubscription. */
|
/** The listener returned by GlobalEventBus subscription. Used for unsubscription. */
|
||||||
private Object listener;
|
private Object listener;
|
||||||
@@ -43,13 +43,13 @@ public class EventFlow {
|
|||||||
/** Holds the results returned from the subscribed event, if any. */
|
/** Holds the results returned from the subscribed event, if any. */
|
||||||
private Map<String, Object> result = null;
|
private Map<String, Object> result = null;
|
||||||
|
|
||||||
/** Empty constructor (event must be added via {@link #addPostEvent}). */
|
/** Empty constructor (event must be added via {@link #addPostEvent(Class, Object...)}). */
|
||||||
public EventFlow() {}
|
public EventFlow() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate an event of the given class and store it in this publisher.
|
* Instantiate an event of the given class and store it in this publisher.
|
||||||
*/
|
*/
|
||||||
public <T extends IEvent> EventFlow addPostEvent(Class<T> eventClass, Object... args) {
|
public <T extends EventType> EventFlow addPostEvent(Class<T> eventClass, Object... args) {
|
||||||
try {
|
try {
|
||||||
boolean isUuidEvent = EventWithUuid.class.isAssignableFrom(eventClass);
|
boolean isUuidEvent = EventWithUuid.class.isAssignableFrom(eventClass);
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ public class EventFlow {
|
|||||||
finalArgs = args;
|
finalArgs = args;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.event = (IEvent) ctorHandle.invokeWithArguments(finalArgs);
|
this.event = (EventType) ctorHandle.invokeWithArguments(finalArgs);
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
@@ -89,11 +89,11 @@ public class EventFlow {
|
|||||||
/**
|
/**
|
||||||
* Start listening for a response event type, chainable with perform().
|
* Start listening for a response event type, chainable with perform().
|
||||||
*/
|
*/
|
||||||
public <TT extends IEvent> ResponseBuilder<TT> onResponse(Class<TT> eventClass) {
|
public <TT extends EventType> ResponseBuilder<TT> onResponse(Class<TT> eventClass) {
|
||||||
return new ResponseBuilder<>(this, eventClass);
|
return new ResponseBuilder<>(this, eventClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ResponseBuilder<R extends IEvent> {
|
public static class ResponseBuilder<R extends EventType> {
|
||||||
private final EventFlow parent;
|
private final EventFlow parent;
|
||||||
private final Class<R> responseClass;
|
private final Class<R> responseClass;
|
||||||
|
|
||||||
@@ -153,17 +153,17 @@ public class EventFlow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// choose event type
|
// choose event type
|
||||||
public <TT extends IEvent> EventSubscriberBuilder<TT> onEvent(Class<TT> eventClass) {
|
public <TT extends EventType> EventSubscriberBuilder<TT> onEvent(Class<TT> eventClass) {
|
||||||
return new EventSubscriberBuilder<>(this, eventClass);
|
return new EventSubscriberBuilder<>(this, eventClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
// One-liner shorthand
|
// One-liner shorthand
|
||||||
public <TT extends IEvent> EventFlow listen(Class<TT> eventClass, Consumer<TT> action) {
|
public <TT extends EventType> EventFlow listen(Class<TT> eventClass, Consumer<TT> action) {
|
||||||
return this.onEvent(eventClass).perform(action);
|
return this.onEvent(eventClass).perform(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builder for chaining .onEvent(...).perform(...)
|
// Builder for chaining .onEvent(...).perform(...)
|
||||||
public static class EventSubscriberBuilder<TT extends IEvent> {
|
public static class EventSubscriberBuilder<TT extends EventType> {
|
||||||
private final EventFlow publisher;
|
private final EventFlow publisher;
|
||||||
private final Class<TT> eventClass;
|
private final Class<TT> eventClass;
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@ public class EventFlow {
|
|||||||
return this.result;
|
return this.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEvent getEvent() {
|
public EventType getEvent() {
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package org.toop.framework.eventbus;
|
package org.toop.framework.eventbus;
|
||||||
|
|
||||||
import org.toop.framework.eventbus.events.EventWithUuid;
|
import org.toop.framework.eventbus.events.EventWithUuid;
|
||||||
import org.toop.framework.eventbus.events.IEvent;
|
import org.toop.framework.eventbus.events.EventType;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
@@ -20,7 +20,7 @@ import java.util.function.Consumer;
|
|||||||
*
|
*
|
||||||
* <p><b>Performance note:</b> Directly using {@link GlobalEventBus} is possible,
|
* <p><b>Performance note:</b> Directly using {@link GlobalEventBus} is possible,
|
||||||
* but for safer type handling, automatic UUID management, and easier unsubscription,
|
* but for safer type handling, automatic UUID management, and easier unsubscription,
|
||||||
* it is recommended to use {@link EventPublisher} whenever possible.</p>
|
* it is recommended to use {@link EventFlow} whenever possible.</p>
|
||||||
*
|
*
|
||||||
* <p>The bus maintains a fixed pool of worker threads that continuously process queued events.</p>
|
* <p>The bus maintains a fixed pool of worker threads that continuously process queued events.</p>
|
||||||
*/
|
*/
|
||||||
@@ -30,10 +30,10 @@ public final class GlobalEventBus {
|
|||||||
private static final int WORKERS = Runtime.getRuntime().availableProcessors();
|
private static final int WORKERS = Runtime.getRuntime().availableProcessors();
|
||||||
|
|
||||||
/** Queue for asynchronous event processing. */
|
/** Queue for asynchronous event processing. */
|
||||||
private static final BlockingQueue<IEvent> EVENT_QUEUE = new LinkedBlockingQueue<>(WORKERS * 1024);
|
private static final BlockingQueue<EventType> EVENT_QUEUE = new LinkedBlockingQueue<>(WORKERS * 1024);
|
||||||
|
|
||||||
/** Map of event class to type-specific listeners. */
|
/** Map of event class to type-specific listeners. */
|
||||||
private static final Map<Class<?>, CopyOnWriteArrayList<Consumer<? super IEvent>>> LISTENERS = new ConcurrentHashMap<>();
|
private static final Map<Class<?>, CopyOnWriteArrayList<Consumer<? super EventType>>> LISTENERS = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/** Map of event class to UUID-specific listeners. */
|
/** Map of event class to UUID-specific listeners. */
|
||||||
private static final Map<Class<?>, ConcurrentHashMap<String, Consumer<? extends EventWithUuid>>> UUID_LISTENERS = new ConcurrentHashMap<>();
|
private static final Map<Class<?>, ConcurrentHashMap<String, Consumer<? extends EventWithUuid>>> UUID_LISTENERS = new ConcurrentHashMap<>();
|
||||||
@@ -59,7 +59,7 @@ public final class GlobalEventBus {
|
|||||||
private static void workerLoop() {
|
private static void workerLoop() {
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
IEvent event = EVENT_QUEUE.take();
|
EventType event = EVENT_QUEUE.take();
|
||||||
dispatchEvent(event);
|
dispatchEvent(event);
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@@ -75,8 +75,8 @@ public final class GlobalEventBus {
|
|||||||
* @param <T> the event type
|
* @param <T> the event type
|
||||||
* @return the provided listener for possible unsubscription
|
* @return the provided listener for possible unsubscription
|
||||||
*/
|
*/
|
||||||
public static <T extends IEvent> Consumer<T> subscribe(Class<T> eventClass, Consumer<T> listener) {
|
public static <T extends EventType> Consumer<T> subscribe(Class<T> eventClass, Consumer<T> listener) {
|
||||||
CopyOnWriteArrayList<Consumer<? super IEvent>> list =
|
CopyOnWriteArrayList<Consumer<? super EventType>> list =
|
||||||
LISTENERS.computeIfAbsent(eventClass, k -> new CopyOnWriteArrayList<>());
|
LISTENERS.computeIfAbsent(eventClass, k -> new CopyOnWriteArrayList<>());
|
||||||
list.add(event -> listener.accept(eventClass.cast(event)));
|
list.add(event -> listener.accept(eventClass.cast(event)));
|
||||||
return listener;
|
return listener;
|
||||||
@@ -135,7 +135,7 @@ public final class GlobalEventBus {
|
|||||||
* @param event the event instance to post
|
* @param event the event instance to post
|
||||||
* @param <T> the event type
|
* @param <T> the event type
|
||||||
*/
|
*/
|
||||||
public static <T extends IEvent> void post(T event) {
|
public static <T extends EventType> void post(T event) {
|
||||||
dispatchEvent(event);
|
dispatchEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ public final class GlobalEventBus {
|
|||||||
* @param event the event instance to post
|
* @param event the event instance to post
|
||||||
* @param <T> the event type
|
* @param <T> the event type
|
||||||
*/
|
*/
|
||||||
public static <T extends IEvent> void postAsync(T event) {
|
public static <T extends EventType> void postAsync(T event) {
|
||||||
if (!EVENT_QUEUE.offer(event)) {
|
if (!EVENT_QUEUE.offer(event)) {
|
||||||
dispatchEvent(event);
|
dispatchEvent(event);
|
||||||
}
|
}
|
||||||
@@ -154,19 +154,19 @@ public final class GlobalEventBus {
|
|||||||
|
|
||||||
/** Dispatches an event to all type-specific, generic, and UUID-specific listeners. */
|
/** Dispatches an event to all type-specific, generic, and UUID-specific listeners. */
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static void dispatchEvent(IEvent event) {
|
private static void dispatchEvent(EventType event) {
|
||||||
Class<?> clazz = event.getClass();
|
Class<?> clazz = event.getClass();
|
||||||
|
|
||||||
CopyOnWriteArrayList<Consumer<? super IEvent>> classListeners = LISTENERS.get(clazz);
|
CopyOnWriteArrayList<Consumer<? super EventType>> classListeners = LISTENERS.get(clazz);
|
||||||
if (classListeners != null) {
|
if (classListeners != null) {
|
||||||
for (Consumer<? super IEvent> listener : classListeners) {
|
for (Consumer<? super EventType> listener : classListeners) {
|
||||||
try { listener.accept(event); } catch (Throwable ignored) {}
|
try { listener.accept(event); } catch (Throwable ignored) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyOnWriteArrayList<Consumer<? super IEvent>> genericListeners = LISTENERS.get(Object.class);
|
CopyOnWriteArrayList<Consumer<? super EventType>> genericListeners = LISTENERS.get(Object.class);
|
||||||
if (genericListeners != null) {
|
if (genericListeners != null) {
|
||||||
for (Consumer<? super IEvent> listener : genericListeners) {
|
for (Consumer<? super EventType> listener : genericListeners) {
|
||||||
try { listener.accept(event); } catch (Throwable ignored) {}
|
try { listener.accept(event); } catch (Throwable ignored) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,12 +67,4 @@ public class Events {
|
|||||||
// Create a new instance
|
// Create a new instance
|
||||||
return constructor.newInstance(args);
|
return constructor.newInstance(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class EventBusEvents {}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static class TttEvents {}
|
|
||||||
|
|
||||||
public static class AiTttEvents {}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,13 +17,18 @@ public class NetworkingClientManager {
|
|||||||
private final Map<String, NetworkingClient> networkClients = new ConcurrentHashMap<>();
|
private final Map<String, NetworkingClient> networkClients = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/** Starts a connection manager, to manage, connections. */
|
/** Starts a connection manager, to manage, connections. */
|
||||||
public NetworkingClientManager() {
|
public NetworkingClientManager() throws NetworkingInitializationException {
|
||||||
new EventFlow().listen(NetworkEvents.StartClientRequest.class, this::handleStartClientRequest);
|
try {
|
||||||
new EventFlow().listen(NetworkEvents.StartClient.class, this::handleStartClient);
|
new EventFlow().listen(NetworkEvents.StartClientRequest.class, this::handleStartClientRequest);
|
||||||
new EventFlow().listen(NetworkEvents.SendCommand.class, this::handleCommand);
|
new EventFlow().listen(NetworkEvents.StartClient.class, this::handleStartClient);
|
||||||
new EventFlow().listen(NetworkEvents.CloseClient.class, this::handleCloseClient);
|
new EventFlow().listen(NetworkEvents.SendCommand.class, this::handleCommand);
|
||||||
new EventFlow().listen(NetworkEvents.RequestsAllClients.class, this::getAllConnections);
|
new EventFlow().listen(NetworkEvents.CloseClient.class, this::handleCloseClient);
|
||||||
new EventFlow().listen(NetworkEvents.ForceCloseAllClients.class, this::shutdownAll);
|
new EventFlow().listen(NetworkEvents.RequestsAllClients.class, this::getAllConnections);
|
||||||
|
new EventFlow().listen(NetworkEvents.ForceCloseAllClients.class, this::shutdownAll);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Failed to initialize the client manager", e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String startClientRequest(Supplier<? extends NetworkingGameClientHandler> handlerFactory,
|
private String startClientRequest(Supplier<? extends NetworkingGameClientHandler> handlerFactory,
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package org.toop.framework.networking;
|
||||||
|
|
||||||
|
public class NetworkingInitializationException extends RuntimeException {
|
||||||
|
public NetworkingInitializationException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
game/pom.xml
14
game/pom.xml
@@ -34,4 +34,18 @@
|
|||||||
<version>2.0.17</version>
|
<version>2.0.17</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>25</source>
|
||||||
|
<target>25</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -5,7 +5,7 @@ public class Player {
|
|||||||
String name;
|
String name;
|
||||||
char symbol;
|
char symbol;
|
||||||
|
|
||||||
Player(String name, char symbol) {
|
public Player(String name, char symbol) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.symbol = symbol;
|
this.symbol = symbol;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,18 +6,14 @@ import org.apache.logging.log4j.LogManager;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.toop.game.GameBase;
|
import org.toop.game.GameBase;
|
||||||
import org.toop.game.Player;
|
import org.toop.game.Player;
|
||||||
import org.toop.backend.tictactoe.ParsedCommand;
|
|
||||||
import org.toop.backend.tictactoe.TicTacToeServerCommand;
|
|
||||||
|
|
||||||
// Todo: refactor
|
// Todo: refactor
|
||||||
public class TicTacToe extends GameBase implements Runnable {
|
public class TicTacToe extends GameBase {
|
||||||
|
|
||||||
protected static final Logger logger = LogManager.getLogger(TicTacToe.class);
|
protected static final Logger logger = LogManager.getLogger(TicTacToe.class);
|
||||||
|
|
||||||
public Thread gameThread;
|
public Thread gameThread;
|
||||||
public String gameId;
|
public String gameId;
|
||||||
public BlockingQueue<ParsedCommand> commandQueue = new LinkedBlockingQueue<>();
|
|
||||||
public BlockingQueue<String> sendQueue = new LinkedBlockingQueue<>();
|
|
||||||
|
|
||||||
public int movesLeft;
|
public int movesLeft;
|
||||||
|
|
||||||
@@ -39,115 +35,6 @@ public class TicTacToe extends GameBase implements Runnable {
|
|||||||
movesLeft = size * size;
|
movesLeft = size * size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addCommandToQueue(ParsedCommand command) {
|
|
||||||
commandQueue.add(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ParsedCommand takeFromCommandQueue() {
|
|
||||||
try {
|
|
||||||
return this.commandQueue.take();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.error("Taking from queue interrupted, in game with id: {}", this.gameId);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addSendToQueue(String send) {
|
|
||||||
try {
|
|
||||||
sendQueue.put(send);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.error("Sending to queue interrupted, in game with id: {}", this.gameId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
this.gameThread = new Thread(this::gameThread);
|
|
||||||
this.gameThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void gameThread() {
|
|
||||||
boolean running = true;
|
|
||||||
|
|
||||||
while (running) {
|
|
||||||
ParsedCommand cmd = takeFromCommandQueue();
|
|
||||||
|
|
||||||
// Get next command if there was no command
|
|
||||||
if (cmd == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do something based which command was given
|
|
||||||
switch (cmd.command) {
|
|
||||||
case TicTacToeServerCommand.MOVE:
|
|
||||||
{
|
|
||||||
// TODO: Check if it is this player's turn, not required for local play (I
|
|
||||||
// think?).
|
|
||||||
|
|
||||||
// Convert given argument to integer
|
|
||||||
Object arg = cmd.arguments.getFirst();
|
|
||||||
int index;
|
|
||||||
try {
|
|
||||||
index = Integer.parseInt((String) arg);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("Error parsing argument to String or Integer");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to play the move
|
|
||||||
State state = play(index);
|
|
||||||
|
|
||||||
if (state != State.INVALID) {
|
|
||||||
// Tell all players who made a move and what move was made
|
|
||||||
// TODO: What is the reaction of the game? WIN, DRAW etc?
|
|
||||||
String player = getCurrentPlayer().getName();
|
|
||||||
addSendToQueue(
|
|
||||||
"SVR GAME MOVE {PLAYER: \""
|
|
||||||
+ player
|
|
||||||
+ "\", DETAILS: \"<reactie spel op zet>\",MOVE: \""
|
|
||||||
+ index
|
|
||||||
+ "\"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check move result
|
|
||||||
switch (state) {
|
|
||||||
case State.WIN:
|
|
||||||
{
|
|
||||||
// Win
|
|
||||||
running = false;
|
|
||||||
addSendToQueue(
|
|
||||||
"SVR GAME WIN {PLAYERONESCORE: \"<score speler1>\","
|
|
||||||
+ " PLAYERTWOSCORE: \"<score speler2>\", COMMENT:"
|
|
||||||
+ " \"<commentaar op resultaat>\"}\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case State.DRAW:
|
|
||||||
{
|
|
||||||
// Draw
|
|
||||||
running = false;
|
|
||||||
addSendToQueue(
|
|
||||||
"SVR GAME DRAW {PLAYERONESCORE: \"<score speler1>\","
|
|
||||||
+ " PLAYERTWOSCORE: \"<score speler2>\", COMMENT:"
|
|
||||||
+ " \"<commentaar op resultaat>\"}\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case State.NORMAL:
|
|
||||||
{
|
|
||||||
// Valid move but not end of game
|
|
||||||
addSendToQueue("SVR GAME YOURTURN");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case State.INVALID:
|
|
||||||
{
|
|
||||||
// Invalid move
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public State play(int index) {
|
public State play(int index) {
|
||||||
if (!validateMove(index)) {
|
if (!validateMove(index)) {
|
||||||
|
|||||||
8
pom.xml
8
pom.xml
@@ -113,6 +113,14 @@
|
|||||||
<artifactId>maven-failsafe-plugin</artifactId>
|
<artifactId>maven-failsafe-plugin</artifactId>
|
||||||
<version>3.5.4</version>
|
<version>3.5.4</version>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>25</source>
|
||||||
|
<target>25</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
|||||||
Reference in New Issue
Block a user