chore: Scaffolding of the project
This commit is contained in:
39
.gitignore
vendored
Normal file
39
.gitignore
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
.kotlin
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
3
.idea/.gitignore
generated
vendored
Normal file
3
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
7
.idea/encodings.xml
generated
Normal file
7
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
14
.idea/misc.xml
generated
Normal file
14
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="22" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
143
pom.xml
Normal file
143
pom.xml
Normal file
@@ -0,0 +1,143 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>cz.jzitnik</groupId>
|
||||
<artifactId>game</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.38</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>cz.jzitnik.Main</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<mainClass>cz.jzitnik.Main</mainClass>
|
||||
<classpathScope>compile</classpathScope>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>22</maven.compiler.source>
|
||||
<maven.compiler.target>22</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.38</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.8.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
<version>0.10.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.18.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.2</version>
|
||||
<scope>test</scope>
|
||||
</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.18</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.trilarion</groupId>
|
||||
<artifactId>java-vorbis-support</artifactId>
|
||||
<version>1.2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.esotericsoftware</groupId>
|
||||
<artifactId>kryo</artifactId>
|
||||
<version>5.6.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.googlecode.lanterna</groupId>
|
||||
<artifactId>lanterna</artifactId>
|
||||
<version>3.1.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
53
src/main/java/cz/jzitnik/Cli.java
Normal file
53
src/main/java/cz/jzitnik/Cli.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package cz.jzitnik;
|
||||
|
||||
import com.googlecode.lanterna.input.KeyStroke;
|
||||
import com.googlecode.lanterna.screen.TerminalScreen;
|
||||
import com.googlecode.lanterna.terminal.DefaultTerminalFactory;
|
||||
import com.googlecode.lanterna.terminal.MouseCaptureMode;
|
||||
import cz.jzitnik.annotations.Dependency;
|
||||
import cz.jzitnik.annotations.injectors.InjectDependency;
|
||||
import cz.jzitnik.events.KeyboardPressEvent;
|
||||
import cz.jzitnik.events.MouseAction;
|
||||
import cz.jzitnik.states.RunningState;
|
||||
import cz.jzitnik.utils.StateManager;
|
||||
import cz.jzitnik.utils.events.EventManager;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
@Dependency
|
||||
public class Cli implements Runnable {
|
||||
@InjectDependency
|
||||
private EventManager eventManager;
|
||||
|
||||
@InjectDependency
|
||||
private StateManager stateManager;
|
||||
|
||||
@SneakyThrows // I know deal with it
|
||||
@Override
|
||||
public void run() {
|
||||
eventManager.start(); // Start event manager thread
|
||||
|
||||
TerminalScreen terminal = new DefaultTerminalFactory()
|
||||
.setMouseCaptureMode(MouseCaptureMode.CLICK_RELEASE_DRAG_MOVE)
|
||||
.createScreen();
|
||||
|
||||
terminal.setCursorPosition(null);
|
||||
terminal.doResizeIfNecessary();
|
||||
terminal.getTerminal().enterPrivateMode();
|
||||
|
||||
RunningState runningState = stateManager.getOrThrow(RunningState.class);
|
||||
while (runningState.isRunning()) {
|
||||
KeyStroke keyStroke = terminal.pollInput();
|
||||
if (keyStroke != null) {
|
||||
if (keyStroke instanceof com.googlecode.lanterna.input.MouseAction mouse) {
|
||||
eventManager.emitEvent(new MouseAction(mouse));
|
||||
continue;
|
||||
}
|
||||
|
||||
eventManager.emitEvent(new KeyboardPressEvent(keyStroke));
|
||||
}
|
||||
Thread.sleep(50);
|
||||
}
|
||||
|
||||
terminal.close();
|
||||
}
|
||||
}
|
||||
13
src/main/java/cz/jzitnik/Game.java
Normal file
13
src/main/java/cz/jzitnik/Game.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package cz.jzitnik;
|
||||
|
||||
import cz.jzitnik.utils.DependencyManager;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
public class Game {
|
||||
private final DependencyManager dependencyManager = new DependencyManager(new Reflections("cz.jzitnik"));
|
||||
|
||||
public void start() {
|
||||
Cli cli = dependencyManager.getDependencyOrThrow(Cli.class);
|
||||
cli.run();
|
||||
}
|
||||
}
|
||||
7
src/main/java/cz/jzitnik/Main.java
Normal file
7
src/main/java/cz/jzitnik/Main.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package cz.jzitnik;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
new Game().start();
|
||||
}
|
||||
}
|
||||
11
src/main/java/cz/jzitnik/annotations/Config.java
Normal file
11
src/main/java/cz/jzitnik/annotations/Config.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package cz.jzitnik.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface Config {
|
||||
}
|
||||
13
src/main/java/cz/jzitnik/annotations/Dependency.java
Normal file
13
src/main/java/cz/jzitnik/annotations/Dependency.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package cz.jzitnik.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface Dependency {
|
||||
/** Custom alias **/
|
||||
Class<?> value() default Object.class;
|
||||
}
|
||||
14
src/main/java/cz/jzitnik/annotations/EventHandler.java
Normal file
14
src/main/java/cz/jzitnik/annotations/EventHandler.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package cz.jzitnik.annotations;
|
||||
|
||||
import cz.jzitnik.utils.events.Event;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface EventHandler {
|
||||
Class<? extends Event> value();
|
||||
}
|
||||
11
src/main/java/cz/jzitnik/annotations/State.java
Normal file
11
src/main/java/cz/jzitnik/annotations/State.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package cz.jzitnik.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface State {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package cz.jzitnik.annotations.injectors;
|
||||
|
||||
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.FIELD})
|
||||
public @interface InjectConfig {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package cz.jzitnik.annotations.injectors;
|
||||
|
||||
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.FIELD})
|
||||
public @interface InjectDependency {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package cz.jzitnik.annotations.injectors;
|
||||
|
||||
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.FIELD})
|
||||
public @interface InjectState {
|
||||
}
|
||||
7
src/main/java/cz/jzitnik/events/ExitEvent.java
Normal file
7
src/main/java/cz/jzitnik/events/ExitEvent.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package cz.jzitnik.events;
|
||||
|
||||
import cz.jzitnik.utils.events.Event;
|
||||
|
||||
/** Custom event without any handler **/
|
||||
public class ExitEvent implements Event {
|
||||
}
|
||||
12
src/main/java/cz/jzitnik/events/KeyboardPressEvent.java
Normal file
12
src/main/java/cz/jzitnik/events/KeyboardPressEvent.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package cz.jzitnik.events;
|
||||
|
||||
import com.googlecode.lanterna.input.KeyStroke;
|
||||
import cz.jzitnik.utils.events.Event;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class KeyboardPressEvent implements Event {
|
||||
private KeyStroke keyStroke;
|
||||
}
|
||||
15
src/main/java/cz/jzitnik/events/MouseAction.java
Normal file
15
src/main/java/cz/jzitnik/events/MouseAction.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package cz.jzitnik.events;
|
||||
|
||||
import com.googlecode.lanterna.TerminalPosition;
|
||||
import com.googlecode.lanterna.input.MouseActionType;
|
||||
import cz.jzitnik.utils.events.Event;
|
||||
|
||||
public class MouseAction extends com.googlecode.lanterna.input.MouseAction implements Event {
|
||||
public MouseAction(MouseActionType actionType, int button, TerminalPosition position) {
|
||||
super(actionType, button, position);
|
||||
}
|
||||
|
||||
public MouseAction(com.googlecode.lanterna.input.MouseAction mouseAction) {
|
||||
this(mouseAction.getActionType(), mouseAction.getButton(), mouseAction.getPosition());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package cz.jzitnik.events.handlers;
|
||||
|
||||
import cz.jzitnik.annotations.EventHandler;
|
||||
import cz.jzitnik.events.ExitEvent;
|
||||
import cz.jzitnik.states.RunningState;
|
||||
import cz.jzitnik.utils.DependencyManager;
|
||||
import cz.jzitnik.utils.StateManager;
|
||||
import cz.jzitnik.utils.events.AbstractEventHandler;
|
||||
|
||||
@EventHandler(ExitEvent.class)
|
||||
public class ExitEventHandler extends AbstractEventHandler<ExitEvent> {
|
||||
public ExitEventHandler(DependencyManager dm) {
|
||||
super(dm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(ExitEvent event) {
|
||||
StateManager stateManager = dm.getDependencyOrThrow(StateManager.class);
|
||||
RunningState runningState = stateManager.getOrThrow(RunningState.class);
|
||||
runningState.setRunning(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cz.jzitnik.events.handlers;
|
||||
|
||||
import com.googlecode.lanterna.input.KeyStroke;
|
||||
import cz.jzitnik.annotations.EventHandler;
|
||||
import cz.jzitnik.events.ExitEvent;
|
||||
import cz.jzitnik.events.KeyboardPressEvent;
|
||||
import cz.jzitnik.utils.DependencyManager;
|
||||
import cz.jzitnik.utils.events.AbstractEventHandler;
|
||||
import cz.jzitnik.utils.events.EventManager;
|
||||
|
||||
@EventHandler(KeyboardPressEvent.class)
|
||||
public class KeyboardPressEventHandler extends AbstractEventHandler<KeyboardPressEvent> {
|
||||
public KeyboardPressEventHandler(DependencyManager dm) {
|
||||
super(dm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(KeyboardPressEvent event) {
|
||||
EventManager eventManager = dm.getDependencyOrThrow(EventManager.class);
|
||||
|
||||
KeyStroke keyStroke = event.getKeyStroke();
|
||||
|
||||
switch (keyStroke.getKeyType()) {
|
||||
case Escape:
|
||||
eventManager.emitEvent(new ExitEvent());
|
||||
break;
|
||||
case ArrowUp:
|
||||
System.out.println("Up arrow pressed");
|
||||
break;
|
||||
case Character:
|
||||
System.out.println("Key pressed: " + keyStroke.getCharacter());
|
||||
break;
|
||||
default:
|
||||
System.out.println("IDK: " + keyStroke.getKeyType());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cz.jzitnik.events.handlers;
|
||||
|
||||
import cz.jzitnik.annotations.EventHandler;
|
||||
import cz.jzitnik.events.MouseAction;
|
||||
import cz.jzitnik.utils.DependencyManager;
|
||||
import cz.jzitnik.utils.events.AbstractEventHandler;
|
||||
|
||||
@EventHandler(MouseAction.class)
|
||||
public class MouseActionEventHandler extends AbstractEventHandler<MouseAction> {
|
||||
public MouseActionEventHandler(DependencyManager dm) {
|
||||
super(dm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(MouseAction event) {
|
||||
System.out.println("ACTION: " + event);
|
||||
}
|
||||
}
|
||||
10
src/main/java/cz/jzitnik/states/RunningState.java
Normal file
10
src/main/java/cz/jzitnik/states/RunningState.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package cz.jzitnik.states;
|
||||
|
||||
import cz.jzitnik.annotations.State;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@State
|
||||
public class RunningState {
|
||||
private boolean running = true;
|
||||
}
|
||||
142
src/main/java/cz/jzitnik/utils/DependencyManager.java
Normal file
142
src/main/java/cz/jzitnik/utils/DependencyManager.java
Normal file
@@ -0,0 +1,142 @@
|
||||
package cz.jzitnik.utils;
|
||||
|
||||
import cz.jzitnik.annotations.Config;
|
||||
import cz.jzitnik.annotations.Dependency;
|
||||
import cz.jzitnik.annotations.injectors.InjectConfig;
|
||||
import cz.jzitnik.annotations.injectors.InjectDependency;
|
||||
import cz.jzitnik.annotations.injectors.InjectState;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@Slf4j
|
||||
public class DependencyManager {
|
||||
private final HashMap<Class<?>, Object> configs = new HashMap<>();
|
||||
private final HashMap<Class<?>, Object> data = new HashMap<>();
|
||||
|
||||
public <T> T getDependencyOrThrow(Class<T> clazz) {
|
||||
T instance = get(clazz);
|
||||
|
||||
if (instance == null) {
|
||||
throw new RuntimeException("Class was not found!");
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public <T> Optional<T> getDependency(Class<T> clazz) {
|
||||
return Optional.ofNullable(get(clazz));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T get(Class<T> clazz) {
|
||||
return (T) data.get(clazz);
|
||||
}
|
||||
|
||||
public DependencyManager(Reflections reflections) {
|
||||
Set<Class<?>> configClasses = reflections.getTypesAnnotatedWith(Config.class);
|
||||
for (Class<?> configClass : configClasses) {
|
||||
try {
|
||||
Constructor<?> constructor = configClass.getDeclaredConstructor();
|
||||
var instance = constructor.newInstance();
|
||||
configs.put(configClass, instance);
|
||||
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException |
|
||||
IllegalAccessException _) {
|
||||
}
|
||||
}
|
||||
|
||||
Set<Class<?>> classes = reflections.getTypesAnnotatedWith(Dependency.class);
|
||||
|
||||
// Construct all classes
|
||||
for (Class<?> clazz : classes) {
|
||||
for (var constructor : clazz.getDeclaredConstructors()) {
|
||||
var paramTypes = constructor.getParameterTypes();
|
||||
var params = new Object[paramTypes.length];
|
||||
boolean suitable = true;
|
||||
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
Class<?> type = paramTypes[i];
|
||||
if (configs.containsKey(type))
|
||||
params[i] = configs.get(type);
|
||||
else if (type == getClass())
|
||||
params[i] = this;
|
||||
else if (type == Reflections.class)
|
||||
params[i] = reflections;
|
||||
else {
|
||||
suitable = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!suitable) continue;
|
||||
|
||||
constructor.setAccessible(true);
|
||||
try {
|
||||
Object instance = constructor.newInstance(params);
|
||||
Dependency annotation = clazz.getAnnotation(Dependency.class);
|
||||
|
||||
if (annotation.value() != Object.class) {
|
||||
data.put(annotation.value(), instance);
|
||||
} else {
|
||||
data.put(clazz, instance);
|
||||
}
|
||||
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
break; // Found a matching constructor, go to next class
|
||||
}
|
||||
}
|
||||
|
||||
StateManager stateManager = (StateManager) data.get(StateManager.class);
|
||||
for (Object instance: data.values()) {
|
||||
Class<?> clazz = instance.getClass();
|
||||
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
if (field.isAnnotationPresent(InjectDependency.class)) {
|
||||
field.setAccessible(true);
|
||||
|
||||
if (!data.containsKey(field.getType())) continue;
|
||||
|
||||
Object dependency = data.get(field.getType());
|
||||
|
||||
if (!field.getType().isAssignableFrom(dependency.getClass())) continue;
|
||||
|
||||
try {
|
||||
field.set(instance, dependency);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else if (field.isAnnotationPresent(InjectState.class)) {
|
||||
field.setAccessible(true);
|
||||
|
||||
Optional<?> stateOptional = stateManager.get(field.getType());
|
||||
|
||||
if (stateOptional.isEmpty()) continue;
|
||||
|
||||
try {
|
||||
field.set(instance, stateOptional.get());
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else if (field.isAnnotationPresent(InjectConfig.class)) {
|
||||
field.setAccessible(true);
|
||||
Optional<?> config = Optional.ofNullable(configs.get(field.getType()));
|
||||
|
||||
if (config.isEmpty()) continue;
|
||||
|
||||
try {
|
||||
field.set(instance, config.get());
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/main/java/cz/jzitnik/utils/StateManager.java
Normal file
38
src/main/java/cz/jzitnik/utils/StateManager.java
Normal file
@@ -0,0 +1,38 @@
|
||||
// NOTE: [StateManager] cannot use injectors like @InjectDependency or @InjectState
|
||||
package cz.jzitnik.utils;
|
||||
|
||||
import cz.jzitnik.annotations.Dependency;
|
||||
import cz.jzitnik.annotations.State;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
|
||||
@Dependency
|
||||
public class StateManager {
|
||||
private final HashMap<Class<?>, Object> data = new HashMap<>();
|
||||
|
||||
public StateManager(Reflections reflections) {
|
||||
var classes = reflections.getTypesAnnotatedWith(State.class);
|
||||
|
||||
for (Class<?> clazz : classes) {
|
||||
try {
|
||||
var instance = clazz.getDeclaredConstructor().newInstance();
|
||||
data.put(clazz, instance);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
|
||||
NoSuchMethodException _) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Optional<T> get(Class<T> clazz) {
|
||||
return Optional.ofNullable((T) data.get(clazz));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getOrThrow(Class<T> clazz) {
|
||||
return (T) data.get(clazz);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package cz.jzitnik.utils.events;
|
||||
|
||||
import cz.jzitnik.utils.DependencyManager;
|
||||
|
||||
public abstract class AbstractEventHandler<T> {
|
||||
protected final DependencyManager dm;
|
||||
|
||||
public AbstractEventHandler(DependencyManager dm) {
|
||||
this.dm = dm;
|
||||
}
|
||||
|
||||
public abstract void handle(T event);
|
||||
}
|
||||
4
src/main/java/cz/jzitnik/utils/events/Event.java
Normal file
4
src/main/java/cz/jzitnik/utils/events/Event.java
Normal file
@@ -0,0 +1,4 @@
|
||||
package cz.jzitnik.utils.events;
|
||||
|
||||
public interface Event {
|
||||
}
|
||||
74
src/main/java/cz/jzitnik/utils/events/EventManager.java
Normal file
74
src/main/java/cz/jzitnik/utils/events/EventManager.java
Normal file
@@ -0,0 +1,74 @@
|
||||
package cz.jzitnik.utils.events;
|
||||
|
||||
import cz.jzitnik.annotations.Dependency;
|
||||
import cz.jzitnik.annotations.EventHandler;
|
||||
import cz.jzitnik.annotations.injectors.InjectState;
|
||||
import cz.jzitnik.states.RunningState;
|
||||
import cz.jzitnik.utils.DependencyManager;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
@Dependency
|
||||
public class EventManager extends Thread {
|
||||
@InjectState
|
||||
private RunningState runningState;
|
||||
|
||||
private final HashMap<Class<? extends Event>, AbstractEventHandler<? extends Event>> handlers = new HashMap<>();
|
||||
private final BlockingQueue<Event> eventQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Event> AbstractEventHandler<T> getHandler(Class<T> type) {
|
||||
return (AbstractEventHandler<T>) handlers.get(type);
|
||||
}
|
||||
|
||||
public void emitEvent(Event event) {
|
||||
eventQueue.add(event);
|
||||
}
|
||||
|
||||
public EventManager(Reflections reflections, DependencyManager dependencyManager) {
|
||||
setDaemon(true);
|
||||
|
||||
var classes = reflections.getTypesAnnotatedWith(EventHandler.class);
|
||||
|
||||
for (var clazz : classes) {
|
||||
EventHandler eventHandler = clazz.getAnnotation(EventHandler.class);
|
||||
try {
|
||||
var instance = (AbstractEventHandler<? extends Event>) clazz.getDeclaredConstructor(DependencyManager.class).newInstance(dependencyManager);
|
||||
handlers.put(eventHandler.value(), instance);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
|
||||
NoSuchMethodException e) {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (runningState.isRunning()) {
|
||||
try {
|
||||
Event event = eventQueue.take();
|
||||
handleEvent(event);
|
||||
} catch (InterruptedException e) {
|
||||
// Program stops
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Event> void handleEvent(Event event) {
|
||||
T typedEvent = (T) event; // safe because handler is keyed by event.getClass()
|
||||
AbstractEventHandler<T> handler = getHandler((Class<T>) event.getClass());
|
||||
Thread thread = new Thread(() -> handler.handle(typedEvent));
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user