feat: Multiplayer #3
14
.idea/FuzzierSettings.xml
generated
Normal file
14
.idea/FuzzierSettings.xml
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="com.mituuz.fuzzier.FuzzierSettings">
|
||||
<option name="modules">
|
||||
<map>
|
||||
<entry key="common" value="$PROJECT_DIR$" />
|
||||
<entry key="game" value="$PROJECT_DIR$" />
|
||||
<entry key="game (1)" value="$PROJECT_DIR$" />
|
||||
<entry key="server" value="$PROJECT_DIR$" />
|
||||
</map>
|
||||
</option>
|
||||
<option name="recentlySearchedFiles" value="rO0ABXNyABxqYXZheC5zd2luZy5EZWZhdWx0TGlzdE1vZGVsBgfGCGLvV2ICAAFMAAhkZWxlZ2F0ZXQAEkxqYXZhL3V0aWwvVmVjdG9yO3hyAB1qYXZheC5zd2luZy5BYnN0cmFjdExpc3RNb2RlbFrW+oYSs63tAgABTAAMbGlzdGVuZXJMaXN0dAAlTGphdmF4L3N3aW5nL2V2ZW50L0V2ZW50TGlzdGVuZXJMaXN0O3hwc3IAI2phdmF4LnN3aW5nLmV2ZW50LkV2ZW50TGlzdGVuZXJMaXN0kUjMLXPfDt4DAAB4cHB4c3IAEGphdmEudXRpbC5WZWN0b3LZl31bgDuvAQMAA0kAEWNhcGFjaXR5SW5jcmVtZW50SQAMZWxlbWVudENvdW50WwALZWxlbWVudERhdGF0ABNbTGphdmEvbGFuZy9PYmplY3Q7eHAAAAAAAAAAAXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAApzcgBIY29tLm1pdHV1ei5mdXp6aWVyLmVudGl0aWVzLkZ1enp5TWF0Y2hDb250YWluZXIkU2VyaWFsaXplZE1hdGNoQ29udGFpbmVy2S8sP5uny74CAARMAAhmaWxlUGF0aHQAEkxqYXZhL2xhbmcvU3RyaW5nO0wACGZpbGVuYW1lcQB+AA1MAA5tb2R1bGVCYXNlUGF0aHEAfgANTAAFc2NvcmV0ADxMY29tL21pdHV1ei9mdXp6aWVyL2VudGl0aWVzL0Z1enp5TWF0Y2hDb250YWluZXIkRnV6enlTY29yZTt4cHQARC9nYW1lL3NyYy9tYWluL2phdmEvY3ovanppdG5pay9jbGllbnQvdXRpbHMvZXZlbnRzL0V2ZW50TWFuYWdlci5qYXZhdAARRXZlbnRNYW5hZ2VyLmphdmF0ABYvaG9tZS9rdWJhL0NvZGluZy9nYW1lc3IAOmNvbS5taXR1dXouZnV6emllci5lbnRpdGllcy5GdXp6eU1hdGNoQ29udGFpbmVyJEZ1enp5U2NvcmUvP9P07ROG2QIABUkADWZpbGVuYW1lU2NvcmVJAA9tdWx0aU1hdGNoU2NvcmVJABBwYXJ0aWFsUGF0aFNjb3JlSQALc3RyZWFrU2NvcmVMABNoaWdobGlnaHRDaGFyYWN0ZXJzdAAPTGphdmEvdXRpbC9TZXQ7eHAAAAAIAAAAAAAAAAAAAAADc3IAEWphdmEudXRpbC5IYXNoU2V0ukSFlZa4tzQDAAB4cHcMAAAAED9AAAAAAAAIc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAABzcQB+ABgAAAABc3EAfgAYAAAAAnNxAH4AGAAAAANzcQB+ABgAAAAEc3EAfgAYAAAABXNxAH4AGAAAAAZzcQB+ABgAAAAHeHBwcHBwcHBwcHg=" />
|
||||
</component>
|
||||
</project>
|
||||
1
.idea/compiler.xml
generated
1
.idea/compiler.xml
generated
@@ -2,6 +2,7 @@
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="true" />
|
||||
<profile name="Maven default annotation processors profile" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
|
||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -8,5 +8,5 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" default="true" 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" />
|
||||
</project>
|
||||
@@ -24,5 +24,12 @@
|
||||
<artifactId>jackson-dataformat-yaml</artifactId>
|
||||
<version>3.0.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.42</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package cz.jzitnik.common.socket;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public interface SocketMessage extends Serializable {
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package cz.jzitnik.common.socket.messages;
|
||||
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
public class Test implements SocketMessage {
|
||||
}
|
||||
6
game/.idea/encodings.xml
generated
6
game/.idea/encodings.xml
generated
@@ -1,6 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/common/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/common/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/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/server/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/server/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
|
||||
16
game/.idea/misc.xml
generated
16
game/.idea/misc.xml
generated
@@ -1,17 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<list size="3">
|
||||
<item index="0" class="java.lang.String" itemvalue="cz.jzitnik.annotations.EventHandler" />
|
||||
<item index="1" class="java.lang.String" itemvalue="cz.jzitnik.annotations.ui.KeyboardPressHandler" />
|
||||
<item index="2" class="java.lang.String" itemvalue="cz.jzitnik.annotations.ui.MouseHandler" />
|
||||
</list>
|
||||
<writeAnnotations>
|
||||
<writeAnnotation name="cz.jzitnik.annotations.injectors.InjectConfig" />
|
||||
<writeAnnotation name="cz.jzitnik.annotations.injectors.InjectDependency" />
|
||||
<writeAnnotation name="cz.jzitnik.annotations.injectors.InjectState" />
|
||||
</writeAnnotations>
|
||||
</component>
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
@@ -20,7 +8,5 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" default="true" project-jdk-name="openjdk-25" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_X" default="true" project-jdk-name="openjdk-25" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
@@ -179,5 +179,11 @@
|
||||
<artifactId>jvm</artifactId>
|
||||
<version>2.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.tyrus.bundles</groupId>
|
||||
<artifactId>tyrus-standalone-client</artifactId>
|
||||
<version>2.2.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -10,6 +10,7 @@ import cz.jzitnik.client.annotations.injectors.InjectState;
|
||||
import cz.jzitnik.client.events.KeyboardPressEvent;
|
||||
import cz.jzitnik.client.events.MouseAction;
|
||||
import cz.jzitnik.client.events.TerminalResizeEvent;
|
||||
import cz.jzitnik.client.socket.SocketEventManager;
|
||||
import cz.jzitnik.client.states.RunningState;
|
||||
import cz.jzitnik.client.states.TerminalState;
|
||||
import cz.jzitnik.client.utils.events.EventManager;
|
||||
@@ -23,6 +24,9 @@ public class Cli implements Runnable {
|
||||
@InjectDependency
|
||||
private EventManager eventManager;
|
||||
|
||||
@InjectDependency
|
||||
private SocketEventManager socketEventManager;
|
||||
|
||||
@InjectState
|
||||
private TerminalState terminalState;
|
||||
|
||||
@@ -31,7 +35,9 @@ public class Cli implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
eventManager.start(); // Start event manager thread
|
||||
// Start event manager thread
|
||||
eventManager.start();
|
||||
socketEventManager.start();
|
||||
|
||||
try (TerminalScreen terminal = new DefaultTerminalFactory()
|
||||
.setMouseCaptureMode(MouseCaptureMode.CLICK_RELEASE_DRAG_MOVE)
|
||||
|
||||
@@ -2,10 +2,12 @@ package cz.jzitnik.client;
|
||||
|
||||
import cz.jzitnik.client.annotations.injectors.InjectDependency;
|
||||
import cz.jzitnik.client.game.setup.GameSetup;
|
||||
import cz.jzitnik.client.socket.Client;
|
||||
import cz.jzitnik.client.utils.DependencyManager;
|
||||
import cz.jzitnik.client.utils.GlobalIOHandlerRepository;
|
||||
import cz.jzitnik.client.utils.ScheduledTaskManager;
|
||||
import cz.jzitnik.client.utils.ThreadManager;
|
||||
import jakarta.websocket.DeploymentException;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -23,15 +25,23 @@ public class Game {
|
||||
private ScheduledTaskManager scheduledTaskManager;
|
||||
@InjectDependency
|
||||
private GlobalIOHandlerRepository globalIOHandlerRepository;
|
||||
@InjectDependency
|
||||
private Client client;
|
||||
|
||||
public void start() throws IOException {
|
||||
dependencyManager.inject(this);
|
||||
|
||||
try {
|
||||
client.connect();
|
||||
|
||||
gameSetup.setup();
|
||||
threadManager.startAll();
|
||||
scheduledTaskManager.startAll();
|
||||
globalIOHandlerRepository.setup();
|
||||
|
||||
cli.run();
|
||||
} catch (DeploymentException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package cz.jzitnik.client.annotations;
|
||||
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface SocketEventHandler {
|
||||
Class<? extends SocketMessage> value();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cz.jzitnik.client.events;
|
||||
|
||||
import cz.jzitnik.client.utils.events.Event;
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
public record SendSocketMessageEvent(SocketMessage message) implements Event {
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cz.jzitnik.client.events.handlers;
|
||||
|
||||
import cz.jzitnik.client.annotations.EventHandler;
|
||||
import cz.jzitnik.client.annotations.injectors.InjectDependency;
|
||||
import cz.jzitnik.client.events.SendSocketMessageEvent;
|
||||
import cz.jzitnik.client.socket.Client;
|
||||
import cz.jzitnik.client.utils.events.AbstractEventHandler;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@EventHandler(SendSocketMessageEvent.class)
|
||||
public class SendSocketMessageEventHandler extends AbstractEventHandler<SendSocketMessageEvent> {
|
||||
@InjectDependency
|
||||
private Client client;
|
||||
|
||||
@Override
|
||||
public void handle(SendSocketMessageEvent event) {
|
||||
try {
|
||||
client.send(event.message());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cz.jzitnik.client.socket;
|
||||
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
public abstract class AbstractSocketEventHandler<T extends SocketMessage> {
|
||||
public abstract void handle(T event);
|
||||
}
|
||||
50
game/src/main/java/cz/jzitnik/client/socket/Client.java
Normal file
50
game/src/main/java/cz/jzitnik/client/socket/Client.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package cz.jzitnik.client.socket;
|
||||
|
||||
import cz.jzitnik.client.annotations.Dependency;
|
||||
import cz.jzitnik.client.annotations.injectors.InjectDependency;
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
import jakarta.websocket.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@Slf4j
|
||||
@Dependency
|
||||
@ClientEndpoint
|
||||
public class Client {
|
||||
private Session session;
|
||||
|
||||
@InjectDependency
|
||||
private SocketEventManager socketEventManager;
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(ByteBuffer buffer) {
|
||||
try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(buffer.array()))) {
|
||||
SocketMessage message = (SocketMessage) ois.readObject();
|
||||
socketEventManager.emitEvent(message);
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void send(SocketMessage message) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(message);
|
||||
oos.flush();
|
||||
|
||||
session.getBasicRemote().sendBinary(ByteBuffer.wrap(baos.toByteArray()));
|
||||
}
|
||||
|
||||
public void connect() throws DeploymentException, IOException {
|
||||
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
|
||||
container.connectToServer(this, URI.create("ws://localhost:8025/ws"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package cz.jzitnik.client.socket;
|
||||
|
||||
import cz.jzitnik.client.annotations.Dependency;
|
||||
import cz.jzitnik.client.annotations.SocketEventHandler;
|
||||
import cz.jzitnik.client.annotations.injectors.InjectConfig;
|
||||
import cz.jzitnik.client.annotations.injectors.InjectState;
|
||||
import cz.jzitnik.client.config.ThreadPoolConfig;
|
||||
import cz.jzitnik.client.states.RunningState;
|
||||
import cz.jzitnik.client.utils.DependencyManager;
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
@Slf4j
|
||||
@Dependency
|
||||
public class SocketEventManager extends Thread {
|
||||
private final DependencyManager dependencyManager;
|
||||
|
||||
private ExecutorService eventExecutor;
|
||||
private final HashMap<Class<? extends SocketMessage>, AbstractSocketEventHandler<?>> handlers = new HashMap<>();
|
||||
private final BlockingQueue<SocketMessage> eventQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
@InjectConfig
|
||||
private ThreadPoolConfig threadPoolConfig;
|
||||
|
||||
@InjectState
|
||||
private RunningState runningState;
|
||||
|
||||
public void emitEvent(SocketMessage event) {
|
||||
eventQueue.add(event);
|
||||
}
|
||||
|
||||
public SocketEventManager(Reflections reflections, DependencyManager dependencyManager) {
|
||||
this.dependencyManager = dependencyManager;
|
||||
setDaemon(true);
|
||||
|
||||
var classes = reflections.getTypesAnnotatedWith(SocketEventHandler.class);
|
||||
|
||||
for (var clazz : classes) {
|
||||
SocketEventHandler eventHandler = clazz.getAnnotation(SocketEventHandler.class);
|
||||
try {
|
||||
var instance = (AbstractSocketEventHandler<?>) clazz.getDeclaredConstructor().newInstance();
|
||||
handlers.put(eventHandler.value(), instance);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
|
||||
NoSuchMethodException e) {
|
||||
log.error("Failed to instantiate socket event handler: {}", clazz.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (Object instance : handlers.values()) {
|
||||
dependencyManager.inject(instance);
|
||||
}
|
||||
|
||||
eventExecutor = Executors.newFixedThreadPool(threadPoolConfig.eventThreadCount());
|
||||
while (runningState.isRunning()) {
|
||||
try {
|
||||
SocketMessage event = eventQueue.take();
|
||||
handleEvent(event);
|
||||
} catch (InterruptedException e) {
|
||||
// The game is shutting down.
|
||||
eventExecutor.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
eventExecutor.shutdown();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends SocketMessage> AbstractSocketEventHandler<T> getHandler(Class<T> type) {
|
||||
return (AbstractSocketEventHandler<T>) handlers.get(type);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void handleEvent(SocketMessage event) {
|
||||
eventExecutor.submit(() -> {
|
||||
try {
|
||||
AbstractSocketEventHandler<SocketMessage> handler = getHandler((Class<SocketMessage>) event.getClass());
|
||||
handler.handle(event);
|
||||
} catch (Exception e) {
|
||||
log.error("Error", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package cz.jzitnik.client.socket.events;
|
||||
|
||||
import cz.jzitnik.client.annotations.SocketEventHandler;
|
||||
import cz.jzitnik.client.socket.AbstractSocketEventHandler;
|
||||
import cz.jzitnik.common.socket.messages.Test;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@SocketEventHandler(Test.class)
|
||||
public class TestHandler extends AbstractSocketEventHandler<Test> {
|
||||
@Override
|
||||
public void handle(Test event) {
|
||||
log.debug("Got test: {}", event);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
package cz.jzitnik.client.utils.events;
|
||||
|
||||
public abstract class AbstractEventHandler<T> {
|
||||
public abstract class AbstractEventHandler<T extends Event> {
|
||||
public abstract void handle(T event);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public class EventManager extends Thread {
|
||||
private ThreadPoolConfig threadPoolConfig;
|
||||
|
||||
private ExecutorService eventExecutor;
|
||||
private final HashMap<Class<? extends Event>, AbstractEventHandler<? extends Event>> handlers = new HashMap<>();
|
||||
private final HashMap<Class<? extends Event>, AbstractEventHandler<?>> handlers = new HashMap<>();
|
||||
private final BlockingQueue<EventRecord> eventQueue = new LinkedBlockingQueue<>();
|
||||
private final DependencyManager dependencyManager;
|
||||
|
||||
@@ -74,7 +74,7 @@ public class EventManager extends Thread {
|
||||
for (var clazz : classes) {
|
||||
EventHandler eventHandler = clazz.getAnnotation(EventHandler.class);
|
||||
try {
|
||||
var instance = (AbstractEventHandler<? extends Event>) clazz.getDeclaredConstructor().newInstance();
|
||||
var instance = (AbstractEventHandler<?>) clazz.getDeclaredConstructor().newInstance();
|
||||
handlers.put(eventHandler.value(), instance);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
|
||||
NoSuchMethodException e) {
|
||||
|
||||
@@ -18,5 +18,49 @@
|
||||
<artifactId>common</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.42</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.websocket</groupId>
|
||||
<artifactId>jakarta.websocket-api</artifactId>
|
||||
<version>2.3.0-M2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.tyrus</groupId>
|
||||
<artifactId>tyrus-server</artifactId>
|
||||
<version>2.2.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.tyrus</groupId>
|
||||
<artifactId>tyrus-container-grizzly-server</artifactId>
|
||||
<version>2.2.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.tyrus</groupId>
|
||||
<artifactId>tyrus-client</artifactId>
|
||||
<version>2.2.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>2.0.17</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.5.25</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
package cz.jzitnik.server;
|
||||
|
||||
public class Main {
|
||||
static void main() {
|
||||
import jakarta.websocket.DeploymentException;
|
||||
import org.glassfish.tyrus.server.Server;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Main {
|
||||
static void main() throws DeploymentException {
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
Server server = new Server("localhost", 8025, "/", properties, WebSocket.class);
|
||||
|
||||
server.start();
|
||||
new Scanner(System.in).nextLine();
|
||||
}
|
||||
}
|
||||
|
||||
53
server/src/main/java/cz/jzitnik/server/WebSocket.java
Normal file
53
server/src/main/java/cz/jzitnik/server/WebSocket.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package cz.jzitnik.server;
|
||||
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
import cz.jzitnik.common.socket.messages.Test;
|
||||
import jakarta.websocket.*;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
@Slf4j
|
||||
@ServerEndpoint("/ws")
|
||||
public class WebSocket {
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session) {
|
||||
log.debug("Client connected: " + session.getId());
|
||||
|
||||
try {
|
||||
SocketMessage response = new Test();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(response);
|
||||
oos.flush();
|
||||
session.getBasicRemote().sendBinary(java.nio.ByteBuffer.wrap(baos.toByteArray()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Receive binary data from client
|
||||
@OnMessage
|
||||
public void onMessage(byte[] bytes, Session session) {
|
||||
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
|
||||
ObjectInputStream ois = new ObjectInputStream(bais)) {
|
||||
|
||||
SocketMessage socketMessage = (SocketMessage) ois.readObject();
|
||||
System.out.println("Received: " + socketMessage);
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose(Session session, CloseReason reason) {
|
||||
System.out.println("Connection closed: " + reason);
|
||||
}
|
||||
|
||||
@OnError
|
||||
public void onError(Session session, Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user