From cbeefa005ae0ee4da82ee6152f4c12390e8872ca Mon Sep 17 00:00:00 2001 From: Almas Baim Date: Fri, 26 Jan 2024 20:15:55 +0000 Subject: [PATCH] feat: added a new module fxgl-intelligence --- fxgl-intelligence/README.md | 3 + fxgl-intelligence/pom.xml | 99 ++++++++++ .../SpeechRecognitionService.java | 14 ++ .../almasb/fxgl/ws/LocalWebSocketServer.java | 181 ++++++++++++++++++ pom.xml | 3 + 5 files changed, 300 insertions(+) create mode 100644 fxgl-intelligence/README.md create mode 100644 fxgl-intelligence/pom.xml create mode 100644 fxgl-intelligence/src/main/java/com/almasb/fxgl/intelligence/SpeechRecognitionService.java create mode 100644 fxgl-intelligence/src/main/java/com/almasb/fxgl/ws/LocalWebSocketServer.java diff --git a/fxgl-intelligence/README.md b/fxgl-intelligence/README.md new file mode 100644 index 000000000..983aed4fd --- /dev/null +++ b/fxgl-intelligence/README.md @@ -0,0 +1,3 @@ +### fxgl-intelligence + +This module does not have module-info as some of its dependencies do not provide a proper module-info.java \ No newline at end of file diff --git a/fxgl-intelligence/pom.xml b/fxgl-intelligence/pom.xml new file mode 100644 index 000000000..9c51475a2 --- /dev/null +++ b/fxgl-intelligence/pom.xml @@ -0,0 +1,99 @@ + + + + fxgl-framework + com.github.almasb + 21+dev-SNAPSHOT + + 4.0.0 + + fxgl-intelligence + + + + com.github.almasb + fxgl-core + ${fxgl.version} + + + + org.java-websocket + Java-WebSocket + ${websocket.version} + + + + org.seleniumhq.selenium + selenium-java + ${selenium.version} + + + + + + + + maven-compiler-plugin + + + + + org.jetbrains.kotlin + kotlin-maven-plugin + + + + + org.apache.maven.plugins + maven-source-plugin + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + + + org.jacoco + jacoco-maven-plugin + ${jacoco.version} + + ${project.build.directory}/coverage-reports/jacoco-unit.exec + ${project.build.directory}/coverage-reports/jacoco-unit.exec + + + + jacoco-initialize + + prepare-agent + + + + jacoco-site + package + + report + + + + report + test + + report + + + + + + + \ No newline at end of file diff --git a/fxgl-intelligence/src/main/java/com/almasb/fxgl/intelligence/SpeechRecognitionService.java b/fxgl-intelligence/src/main/java/com/almasb/fxgl/intelligence/SpeechRecognitionService.java new file mode 100644 index 000000000..ab215714d --- /dev/null +++ b/fxgl-intelligence/src/main/java/com/almasb/fxgl/intelligence/SpeechRecognitionService.java @@ -0,0 +1,14 @@ +/* + * FXGL - JavaFX Game Library. The MIT License (MIT). + * Copyright (c) AlmasB (almaslvl@gmail.com). + * See LICENSE for details. + */ + +package com.almasb.fxgl.intelligence; + +/** + * @author Almas Baim (https://github.com/AlmasB) + */ +public class SpeechRecognitionService { + +} \ No newline at end of file diff --git a/fxgl-intelligence/src/main/java/com/almasb/fxgl/ws/LocalWebSocketServer.java b/fxgl-intelligence/src/main/java/com/almasb/fxgl/ws/LocalWebSocketServer.java new file mode 100644 index 000000000..29b7f00ac --- /dev/null +++ b/fxgl-intelligence/src/main/java/com/almasb/fxgl/ws/LocalWebSocketServer.java @@ -0,0 +1,181 @@ +/* + * FXGL - JavaFX Game Library. The MIT License (MIT). + * Copyright (c) AlmasB (almaslvl@gmail.com). + * See LICENSE for details. + */ + +package com.almasb.fxgl.ws; + +import com.almasb.fxgl.logging.Logger; +import org.java_websocket.WebSocket; +import org.java_websocket.handshake.ClientHandshake; +import org.java_websocket.server.WebSocketServer; + +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.function.Consumer; + +/** + * A simple localhost websocket server. + * All methods are internally run in a background thread, + * so they are safe to be called from any thread. + * + * @author Almas Baimagambetov (almaslvl@gmail.com) + */ +public final class LocalWebSocketServer extends WebSocketServer { + + private static final String POISON_PILL = "62jkasdy732qjkkhs63jASY_HSF"; + + private final Logger log; + + private boolean isLoggingEnabled = true; + + private String serverName; + private List> messageHandlers = new ArrayList<>(); + + private SendMessageThread thread; + private WebSocket socket = null; + + /** + * Create a server without a name at given port. + */ + public LocalWebSocketServer(int port) { + this("Unnamed", port); + } + + /** + * Create a server with the given dev-friendly name at given port. + */ + public LocalWebSocketServer(String serverName, int port) { + super(new InetSocketAddress("localhost", port)); + this.serverName = serverName; + + log = Logger.get("WSServer " + serverName + ":" + port); + thread = new SendMessageThread(serverName); + } + + public boolean isLoggingEnabled() { + return isLoggingEnabled; + } + + public void setLoggingEnabled(boolean isLoggingEnabled) { + this.isLoggingEnabled = isLoggingEnabled; + } + + /** + * Add a handler for new messages. + */ + public void addMessageHandler(Consumer handler) { + messageHandlers.add(handler); + } + + /** + * Remove an existing handler. + */ + public void removeMessageHandler(Consumer handler) { + messageHandlers.remove(handler); + } + + /** + * @return last connected socket + */ + public Optional socket() { + return Optional.ofNullable(socket); + } + + /** + * Send a String to the other end of the socket. + */ + public void send(String data) { + if (!isConnected()) { + log.warning("Cannot send <" + data + "> Socket is not connected"); + return; + } + + try { + thread.messages.put(data); + } catch (Exception e) { + log.warning("Failed to send data to SendMessageThread", e); + } + } + + public boolean isConnected() { + return socket != null; + } + + @Override + public void onOpen(WebSocket conn, ClientHandshake handshake) { + log.info("Opened connection: " + conn.getRemoteSocketAddress()); + + socket = conn; + } + + @Override + public void onClose(WebSocket conn, int code, String reason, boolean remote) { + log.info("Closed connection, code: " + code); + } + + @Override + public void onMessage(WebSocket conn, String message) { + messageHandlers.forEach(h -> h.accept(message)); + } + + @Override + public void onError(WebSocket conn, Exception ex) { + log.warning("WS error", ex); + } + + @Override + public void onStart() { + log.info("Server started successfully"); + } + + @Override + public void start() { + try { + thread.start(); + super.start(); + } catch (Exception e) { + log.warning("Failed to start WS server", e); + } + } + + @Override + public void stop() { + try { + thread.messages.put(POISON_PILL); + super.stop(); + } catch (Exception e) { + log.warning("Failed to stop WS server", e); + } + } + + private class SendMessageThread extends Thread { + BlockingQueue messages = new ArrayBlockingQueue<>(10); + + SendMessageThread(String name) { + super(name); + } + + @Override + public void run() { + while (true) { + try { + var data = messages.take(); + + if (data.equals(POISON_PILL)) + break; + + socket.send(data); + + } catch (Exception e) { + log.warning("Failed to send data", e); + } + } + } + } +} diff --git a/pom.xml b/pom.xml index e7d92a729..d2450f357 100644 --- a/pom.xml +++ b/pom.xml @@ -20,6 +20,7 @@ fxgl fxgl-test fxgl-controllerinput + fxgl-intelligence fxgl-gameplay fxgl-samples fxgl-tools @@ -93,6 +94,8 @@ 1.8.10 4.0.17 2.14.2 + 1.5.5 + 4.17.0 5.10.0