From 583caa40bab9916469b260ebdea0a08fd90a4f65 Mon Sep 17 00:00:00 2001 From: jzitnik-dev Date: Sat, 3 Jan 2026 15:48:49 +0100 Subject: [PATCH] refactor: Better API for IO handling --- src/main/java/cz/jzitnik/Game.java | 3 + .../annotations/ui/KeyboardPressHandler.java | 13 ++ .../annotations/ui/KeyboardPressHandlers.java | 12 ++ .../jzitnik/annotations/ui/MouseHandler.java | 12 ++ .../annotations/ui/MouseHandlerType.java | 7 + .../cz/jzitnik/annotations/ui/Render.java | 11 ++ .../java/cz/jzitnik/annotations/ui/UI.java | 11 ++ .../events/handlers/FullRoomDrawHandler.java | 13 +- .../handlers/KeyboardPressEventHandler.java | 23 +-- .../handlers/MouseActionEventHandler.java | 10 +- .../java/cz/jzitnik/game/objects/Chest.java | 8 +- .../game/objects/GlobalUIClickHandler.java | 15 -- .../java/cz/jzitnik/ui/GlobalShortcuts.java | 40 +++++ src/main/java/cz/jzitnik/ui/Inventory.java | 15 +- src/main/java/cz/jzitnik/ui/Stats.java | 4 + .../utils/GlobalIOHandlerRepository.java | 165 ++++++++++++++++++ ...java => UIRoomClickHandlerRepository.java} | 41 +---- 17 files changed, 313 insertions(+), 90 deletions(-) create mode 100644 src/main/java/cz/jzitnik/annotations/ui/KeyboardPressHandler.java create mode 100644 src/main/java/cz/jzitnik/annotations/ui/KeyboardPressHandlers.java create mode 100644 src/main/java/cz/jzitnik/annotations/ui/MouseHandler.java create mode 100644 src/main/java/cz/jzitnik/annotations/ui/MouseHandlerType.java create mode 100644 src/main/java/cz/jzitnik/annotations/ui/Render.java create mode 100644 src/main/java/cz/jzitnik/annotations/ui/UI.java delete mode 100644 src/main/java/cz/jzitnik/game/objects/GlobalUIClickHandler.java create mode 100644 src/main/java/cz/jzitnik/ui/GlobalShortcuts.java create mode 100644 src/main/java/cz/jzitnik/utils/GlobalIOHandlerRepository.java rename src/main/java/cz/jzitnik/utils/{UIClickHandlerRepository.java => UIRoomClickHandlerRepository.java} (80%) diff --git a/src/main/java/cz/jzitnik/Game.java b/src/main/java/cz/jzitnik/Game.java index b0cf666..bc0032e 100644 --- a/src/main/java/cz/jzitnik/Game.java +++ b/src/main/java/cz/jzitnik/Game.java @@ -2,6 +2,7 @@ package cz.jzitnik; import cz.jzitnik.game.setup.GameSetup; import cz.jzitnik.utils.DependencyManager; +import cz.jzitnik.utils.GlobalIOHandlerRepository; import cz.jzitnik.utils.ScheduledTaskManager; import cz.jzitnik.utils.ThreadManager; import org.reflections.Reflections; @@ -15,10 +16,12 @@ public class Game { GameSetup gameSetup = dependencyManager.getDependencyOrThrow(GameSetup.class); ThreadManager threadManager = dependencyManager.getDependencyOrThrow(ThreadManager.class); ScheduledTaskManager scheduledTaskManager = dependencyManager.getDependencyOrThrow(ScheduledTaskManager.class); + GlobalIOHandlerRepository globalIOHandlerRepository = dependencyManager.getDependencyOrThrow(GlobalIOHandlerRepository.class); gameSetup.setup(); threadManager.startAll(); scheduledTaskManager.startAll(); + globalIOHandlerRepository.setup(); cli.run(); } diff --git a/src/main/java/cz/jzitnik/annotations/ui/KeyboardPressHandler.java b/src/main/java/cz/jzitnik/annotations/ui/KeyboardPressHandler.java new file mode 100644 index 0000000..d5e6eaa --- /dev/null +++ b/src/main/java/cz/jzitnik/annotations/ui/KeyboardPressHandler.java @@ -0,0 +1,13 @@ +package cz.jzitnik.annotations.ui; + +import com.googlecode.lanterna.input.KeyType; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@Repeatable(KeyboardPressHandlers.class) +public @interface KeyboardPressHandler { + KeyType keyType() default KeyType.Character; + char character() default '\0'; +} diff --git a/src/main/java/cz/jzitnik/annotations/ui/KeyboardPressHandlers.java b/src/main/java/cz/jzitnik/annotations/ui/KeyboardPressHandlers.java new file mode 100644 index 0000000..b8892ae --- /dev/null +++ b/src/main/java/cz/jzitnik/annotations/ui/KeyboardPressHandlers.java @@ -0,0 +1,12 @@ +package cz.jzitnik.annotations.ui; + +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.METHOD) +public @interface KeyboardPressHandlers { + KeyboardPressHandler[] value(); +} diff --git a/src/main/java/cz/jzitnik/annotations/ui/MouseHandler.java b/src/main/java/cz/jzitnik/annotations/ui/MouseHandler.java new file mode 100644 index 0000000..e18ed7c --- /dev/null +++ b/src/main/java/cz/jzitnik/annotations/ui/MouseHandler.java @@ -0,0 +1,12 @@ +package cz.jzitnik.annotations.ui; + +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.METHOD) +public @interface MouseHandler { + MouseHandlerType value(); +} diff --git a/src/main/java/cz/jzitnik/annotations/ui/MouseHandlerType.java b/src/main/java/cz/jzitnik/annotations/ui/MouseHandlerType.java new file mode 100644 index 0000000..26e46d7 --- /dev/null +++ b/src/main/java/cz/jzitnik/annotations/ui/MouseHandlerType.java @@ -0,0 +1,7 @@ +package cz.jzitnik.annotations.ui; + +public enum MouseHandlerType { + CLICK, + MOVE, + ELSE, +} diff --git a/src/main/java/cz/jzitnik/annotations/ui/Render.java b/src/main/java/cz/jzitnik/annotations/ui/Render.java new file mode 100644 index 0000000..6a2a79c --- /dev/null +++ b/src/main/java/cz/jzitnik/annotations/ui/Render.java @@ -0,0 +1,11 @@ +package cz.jzitnik.annotations.ui; + +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.METHOD) +public @interface Render { +} diff --git a/src/main/java/cz/jzitnik/annotations/ui/UI.java b/src/main/java/cz/jzitnik/annotations/ui/UI.java new file mode 100644 index 0000000..9980fcf --- /dev/null +++ b/src/main/java/cz/jzitnik/annotations/ui/UI.java @@ -0,0 +1,11 @@ +package cz.jzitnik.annotations.ui; + +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 UI { +} diff --git a/src/main/java/cz/jzitnik/events/handlers/FullRoomDrawHandler.java b/src/main/java/cz/jzitnik/events/handlers/FullRoomDrawHandler.java index e64025f..b79171f 100644 --- a/src/main/java/cz/jzitnik/events/handlers/FullRoomDrawHandler.java +++ b/src/main/java/cz/jzitnik/events/handlers/FullRoomDrawHandler.java @@ -21,8 +21,9 @@ import cz.jzitnik.states.TerminalState; import cz.jzitnik.ui.Inventory; import cz.jzitnik.ui.Stats; import cz.jzitnik.utils.DependencyManager; +import cz.jzitnik.utils.GlobalIOHandlerRepository; import cz.jzitnik.utils.RerenderUtils; -import cz.jzitnik.utils.UIClickHandlerRepository; +import cz.jzitnik.utils.UIRoomClickHandlerRepository; import cz.jzitnik.utils.events.AbstractEventHandler; import cz.jzitnik.utils.events.EventManager; import cz.jzitnik.utils.roomtasks.RoomTaskScheduler; @@ -56,11 +57,7 @@ public class FullRoomDrawHandler extends AbstractEventHandler { @InjectDependency private RoomTaskScheduler roomTaskScheduler; @InjectDependency - private UIClickHandlerRepository uiClickHandlerRepository; - @InjectDependency - private Inventory inventory; - @InjectDependency - private Stats stats; + private GlobalIOHandlerRepository globalIOHandlerRepository; public FullRoomDrawHandler(DependencyManager dm) { super(dm); @@ -88,9 +85,7 @@ public class FullRoomDrawHandler extends AbstractEventHandler { RerenderUtils.rerenderPart(0, width - 1, 0, height - 1, startX, startY, currentRoom, room, player, playerTexture, screenBuffer, resourceManager, debugging); if (event.isFullRerender()) { - inventory.renderInventoryRerender(); - stats.rerender(); - uiClickHandlerRepository.registerGlobalHandler(inventory); + globalIOHandlerRepository.renderAll(); } partsToRerender.add(new RerenderScreen.ScreenPart( diff --git a/src/main/java/cz/jzitnik/events/handlers/KeyboardPressEventHandler.java b/src/main/java/cz/jzitnik/events/handlers/KeyboardPressEventHandler.java index 4976253..0292457 100644 --- a/src/main/java/cz/jzitnik/events/handlers/KeyboardPressEventHandler.java +++ b/src/main/java/cz/jzitnik/events/handlers/KeyboardPressEventHandler.java @@ -1,12 +1,12 @@ package cz.jzitnik.events.handlers; -import com.googlecode.lanterna.input.KeyStroke; import cz.jzitnik.annotations.EventHandler; import cz.jzitnik.annotations.injectors.InjectDependency; import cz.jzitnik.annotations.injectors.InjectState; import cz.jzitnik.events.*; import cz.jzitnik.game.GameState; import cz.jzitnik.utils.DependencyManager; +import cz.jzitnik.utils.GlobalIOHandlerRepository; import cz.jzitnik.utils.events.AbstractEventHandler; import cz.jzitnik.utils.events.EventManager; @@ -22,6 +22,9 @@ public class KeyboardPressEventHandler extends AbstractEventHandler eventManager.emitEvent(new PlayerMoveEvent(keyStroke)); - } - break; - default: - break; - } + globalIOHandlerRepository.keyboard(event); } } diff --git a/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java b/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java index e2f49b7..36a0033 100644 --- a/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java +++ b/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java @@ -11,7 +11,7 @@ import cz.jzitnik.game.GameState; import cz.jzitnik.game.utils.Selectable; import cz.jzitnik.states.RenderState; import cz.jzitnik.utils.DependencyManager; -import cz.jzitnik.utils.UIClickHandlerRepository; +import cz.jzitnik.utils.UIRoomClickHandlerRepository; import cz.jzitnik.utils.events.AbstractEventHandler; import cz.jzitnik.utils.events.EventManager; @@ -28,7 +28,7 @@ public class MouseActionEventHandler extends AbstractEventHandler { private EventManager eventManager; @InjectDependency - private UIClickHandlerRepository uiClickHandlerRepository; + private UIRoomClickHandlerRepository uiRoomClickHandlerRepository; @InjectState private GameState gameState; @@ -52,14 +52,14 @@ public class MouseActionEventHandler extends AbstractEventHandler { switch (event.getActionType()) { case MOVE -> { - boolean registered = uiClickHandlerRepository.handleMove(event); + boolean registered = uiRoomClickHandlerRepository.handleMove(event); if (!registered) { eventManager.emitEvent(new MouseMoveEvent(event)); } } case CLICK_RELEASE -> { - boolean clicked = uiClickHandlerRepository.handleClick(event); + boolean clicked = uiRoomClickHandlerRepository.handleClick(event); if (clicked || gameState.getPlayer().isSwinging()) { return; @@ -76,7 +76,7 @@ public class MouseActionEventHandler extends AbstractEventHandler { object.ifPresent(selectable -> selectable.interact(dm)); } - default -> uiClickHandlerRepository.handleElse(event); + default -> uiRoomClickHandlerRepository.handleElse(event); } } } diff --git a/src/main/java/cz/jzitnik/game/objects/Chest.java b/src/main/java/cz/jzitnik/game/objects/Chest.java index bd440fe..ca114bc 100644 --- a/src/main/java/cz/jzitnik/game/objects/Chest.java +++ b/src/main/java/cz/jzitnik/game/objects/Chest.java @@ -26,7 +26,7 @@ import cz.jzitnik.ui.pixels.Pixel; import cz.jzitnik.utils.DependencyManager; import cz.jzitnik.utils.RerenderUtils; import cz.jzitnik.utils.StateManager; -import cz.jzitnik.utils.UIClickHandlerRepository; +import cz.jzitnik.utils.UIRoomClickHandlerRepository; import cz.jzitnik.utils.events.EventManager; import lombok.extern.slf4j.Slf4j; @@ -56,7 +56,7 @@ public final class Chest extends GameObject implements UIClickHandler { @InjectDependency private EventManager eventManager; @InjectDependency - private UIClickHandlerRepository uiClickHandlerRepository; + private UIRoomClickHandlerRepository uiRoomClickHandlerRepository; @InjectState private GameState gameState; @@ -174,7 +174,7 @@ public final class Chest extends GameObject implements UIClickHandler { RerenderScreen.ScreenPart sp = new RerenderScreen.ScreenPart(guiStart, guiEnd); if (!items.isEmpty()) { - listenerHashCode = uiClickHandlerRepository.registerCurrentRoomHandler(sp, this); + listenerHashCode = uiRoomClickHandlerRepository.registerCurrentRoomHandler(sp, this); } eventManager.emitEvent(new RerenderScreen(sp)); @@ -275,7 +275,7 @@ public final class Chest extends GameObject implements UIClickHandler { items.remove(item); if (items.isEmpty()) { - uiClickHandlerRepository.removeHandlerForCurrentRoom(listenerHashCode); + uiRoomClickHandlerRepository.removeHandlerForCurrentRoom(listenerHashCode); } render(true); diff --git a/src/main/java/cz/jzitnik/game/objects/GlobalUIClickHandler.java b/src/main/java/cz/jzitnik/game/objects/GlobalUIClickHandler.java deleted file mode 100644 index a9a5b78..0000000 --- a/src/main/java/cz/jzitnik/game/objects/GlobalUIClickHandler.java +++ /dev/null @@ -1,15 +0,0 @@ -package cz.jzitnik.game.objects; - -import cz.jzitnik.events.MouseAction; - -public interface GlobalUIClickHandler { - boolean handleClick(MouseAction mouseAction); - - default boolean handleMove(MouseAction ignoredMouseAction) { - return false; - } - - default boolean handleElse(MouseAction ignoredMouseAction) { - return false; - } -} diff --git a/src/main/java/cz/jzitnik/ui/GlobalShortcuts.java b/src/main/java/cz/jzitnik/ui/GlobalShortcuts.java new file mode 100644 index 0000000..4434020 --- /dev/null +++ b/src/main/java/cz/jzitnik/ui/GlobalShortcuts.java @@ -0,0 +1,40 @@ +package cz.jzitnik.ui; + +import com.googlecode.lanterna.input.KeyType; +import cz.jzitnik.annotations.Dependency; +import cz.jzitnik.annotations.injectors.InjectDependency; +import cz.jzitnik.annotations.ui.KeyboardPressHandler; +import cz.jzitnik.annotations.ui.UI; +import cz.jzitnik.events.ExitEvent; +import cz.jzitnik.events.FullRedrawEvent; +import cz.jzitnik.events.KeyboardPressEvent; +import cz.jzitnik.events.PlayerMoveEvent; +import cz.jzitnik.utils.events.EventManager; + +@UI +@Dependency +public class GlobalShortcuts { + @InjectDependency + private EventManager eventManager; + + @KeyboardPressHandler(keyType = KeyType.F5) + public boolean refresh(KeyboardPressEvent ignored) { + eventManager.emitEvent(new FullRedrawEvent()); + return true; + } + + @KeyboardPressHandler(keyType = KeyType.Escape) + public boolean exit(KeyboardPressEvent ignored) { + eventManager.emitEvent(new ExitEvent()); + return true; + } + + @KeyboardPressHandler(character = 'w') + @KeyboardPressHandler(character = 'a') + @KeyboardPressHandler(character = 's') + @KeyboardPressHandler(character = 'd') + public boolean move(KeyboardPressEvent event) { + eventManager.emitEvent(new PlayerMoveEvent(event.getKeyStroke())); + return true; + } +} diff --git a/src/main/java/cz/jzitnik/ui/Inventory.java b/src/main/java/cz/jzitnik/ui/Inventory.java index 478b9c3..2d7026f 100644 --- a/src/main/java/cz/jzitnik/ui/Inventory.java +++ b/src/main/java/cz/jzitnik/ui/Inventory.java @@ -6,13 +6,16 @@ import com.googlecode.lanterna.TextColor; import cz.jzitnik.annotations.Dependency; import cz.jzitnik.annotations.injectors.InjectDependency; import cz.jzitnik.annotations.injectors.InjectState; +import cz.jzitnik.annotations.ui.MouseHandler; +import cz.jzitnik.annotations.ui.MouseHandlerType; +import cz.jzitnik.annotations.ui.Render; +import cz.jzitnik.annotations.ui.UI; import cz.jzitnik.events.InventoryRerender; import cz.jzitnik.events.MouseAction; import cz.jzitnik.game.GameState; import cz.jzitnik.game.ResourceManager; import cz.jzitnik.game.items.GameItem; import cz.jzitnik.game.items.types.InteractableItem; -import cz.jzitnik.game.objects.GlobalUIClickHandler; import cz.jzitnik.states.ScreenBuffer; import cz.jzitnik.states.TerminalState; import cz.jzitnik.ui.pixels.ColoredPixel; @@ -33,8 +36,9 @@ import java.util.concurrent.TimeUnit; import java.util.stream.IntStream; @Slf4j +@UI @Dependency -public class Inventory implements GlobalUIClickHandler { +public class Inventory { private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); public static final int ITEMS_X = 3; public static final int ITEMS_Y = 5; @@ -104,7 +108,7 @@ public class Inventory implements GlobalUIClickHandler { offsetX = (maxX / 2) - (INVENTORY_WIDTH / 2); } - @Override + @MouseHandler(MouseHandlerType.CLICK) public boolean handleClick(MouseAction mouseAction) { inventoryState.onNextDragTakeItemOnIndex = -1; @@ -194,7 +198,7 @@ public class Inventory implements GlobalUIClickHandler { return true; } - @Override + @MouseHandler(MouseHandlerType.MOVE) public boolean handleMove(MouseAction mouseAction) { TerminalPosition terminalPosition = calculateActualCords(mouseAction.getPosition()); @@ -216,7 +220,7 @@ public class Inventory implements GlobalUIClickHandler { return true; } - @Override + @MouseHandler(MouseHandlerType.ELSE) public boolean handleElse(MouseAction mouseAction) { TerminalPosition terminalPosition = calculateActualCords(mouseAction.getPosition()); @@ -254,6 +258,7 @@ public class Inventory implements GlobalUIClickHandler { return new TerminalPosition(position.getColumn() - offsetX, position.getRow() * 2 - offsetY); } + @Render public void renderInventoryRerender() { calculateOffset(); var inventory = gameState.getPlayer().getInventory(); diff --git a/src/main/java/cz/jzitnik/ui/Stats.java b/src/main/java/cz/jzitnik/ui/Stats.java index 45a5588..c41b3fc 100644 --- a/src/main/java/cz/jzitnik/ui/Stats.java +++ b/src/main/java/cz/jzitnik/ui/Stats.java @@ -3,6 +3,8 @@ package cz.jzitnik.ui; import com.googlecode.lanterna.TextColor; import cz.jzitnik.annotations.Dependency; import cz.jzitnik.annotations.injectors.InjectState; +import cz.jzitnik.annotations.ui.Render; +import cz.jzitnik.annotations.ui.UI; import cz.jzitnik.game.GameState; import cz.jzitnik.game.Player; import cz.jzitnik.states.ScreenBuffer; @@ -12,6 +14,7 @@ import cz.jzitnik.ui.pixels.Pixel; import lombok.Getter; @Getter +@UI @Dependency public class Stats { public static final int BARS_COUNT = 2; @@ -33,6 +36,7 @@ public class Stats { @InjectState private ScreenBuffer screenBuffer; + @Render public void rerender() { var buffer = screenBuffer.getRenderedBuffer(); diff --git a/src/main/java/cz/jzitnik/utils/GlobalIOHandlerRepository.java b/src/main/java/cz/jzitnik/utils/GlobalIOHandlerRepository.java new file mode 100644 index 0000000..062283b --- /dev/null +++ b/src/main/java/cz/jzitnik/utils/GlobalIOHandlerRepository.java @@ -0,0 +1,165 @@ +package cz.jzitnik.utils; + +import com.googlecode.lanterna.input.KeyType; +import cz.jzitnik.annotations.Dependency; +import cz.jzitnik.annotations.injectors.InjectDependency; +import cz.jzitnik.annotations.ui.KeyboardPressHandler; +import cz.jzitnik.annotations.ui.MouseHandler; +import cz.jzitnik.annotations.ui.Render; +import cz.jzitnik.annotations.ui.UI; +import cz.jzitnik.events.KeyboardPressEvent; +import cz.jzitnik.events.MouseAction; +import lombok.extern.slf4j.Slf4j; +import org.reflections.Reflections; + +import java.lang.reflect.Method; +import java.util.*; +import java.util.function.Predicate; + +@Slf4j +@Dependency +public class GlobalIOHandlerRepository { + private final Reflections reflections; + private final Set> mouseClickHandlers = new HashSet<>(); + private final Set> mouseMoveHandlers = new HashSet<>(); + private final Set> mouseElseHandlers = new HashSet<>(); + private final Map> keyPressHandlers = new HashMap<>(); + private final Map> characterPressHandlers = new HashMap<>(); + private final Set renderers = new HashSet<>(); + + @InjectDependency + private DependencyManager dependencyManager; + + public GlobalIOHandlerRepository(Reflections reflections) { + this.reflections = reflections; + } + + public boolean click(MouseAction mouseEvent) { + for (Predicate handler : mouseClickHandlers) { + if (handler.test(mouseEvent)) { + return true; + } + } + + return false; + } + + public boolean move(MouseAction mouseEvent) { + for (Predicate handler : mouseMoveHandlers) { + if (handler.test(mouseEvent)) { + return true; + } + } + return false; + } + + public boolean mElse(MouseAction mouseEvent) { + for (Predicate handler : mouseElseHandlers) { + if (handler.test(mouseEvent)) { + return true; + } + } + return false; + } + + public boolean keyboard(KeyboardPressEvent keyboardPressEvent) { + KeyType keyType = keyboardPressEvent.getKeyStroke().getKeyType(); + if (keyType == KeyType.Character) { + char character = keyboardPressEvent.getKeyStroke().getCharacter(); + if (characterPressHandlers.containsKey(character)) { + return characterPressHandlers.get(character).test(keyboardPressEvent); + } + } else { + if (keyPressHandlers.containsKey(keyType)) { + return keyPressHandlers.get(keyType).test(keyboardPressEvent); + } + } + + return false; + } + + public void renderAll() { + renderers.forEach(Runnable::run); + } + + public void setup() { + Set> classes = reflections.getTypesAnnotatedWith(UI.class); + for (Class clazz : classes) { + Optional instanceOptional = dependencyManager.getDependency(clazz); + if (instanceOptional.isEmpty()) { + continue; + } + Object instance = instanceOptional.get(); + + Method[] methods = clazz.getDeclaredMethods(); + + for (Method method : methods) { + if (method.getParameterCount() == 0 && method.getReturnType() == void.class && method.isAnnotationPresent(Render.class)) { + Runnable runnable = () -> { + try { + method.invoke(instance); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + }; + renderers.add(runnable); + continue; + } + + if (method.getParameterCount() != 1) { + continue; + } + + if (method.getParameters()[0].getType().equals(MouseAction.class) && method.getReturnType().equals(boolean.class) && method.isAnnotationPresent(MouseHandler.class)) { + MouseHandler annotation = method.getAnnotation(MouseHandler.class); + method.setAccessible(true); + Predicate predicate = event -> { + try { + return (boolean) method.invoke(instance, event); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + }; + assert annotation != null; + (switch (annotation.value()) { + case CLICK -> mouseClickHandlers; + case MOVE -> mouseMoveHandlers; + case ELSE -> mouseElseHandlers; + }).add(predicate); + + continue; + } + + if (method.getParameters().length == 1 && + method.getParameters()[0].getType().equals(KeyboardPressEvent.class)) { + + KeyboardPressHandler[] annotations = + method.getAnnotationsByType(KeyboardPressHandler.class); + + if (annotations.length == 0) { + return; + } + + method.setAccessible(true); + + Predicate predicate = event -> { + try { + return (boolean) method.invoke(instance, event); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + }; + + for (KeyboardPressHandler annotation : annotations) { + if (annotation.keyType() == KeyType.Character) { + characterPressHandlers.put(annotation.character(), predicate); + } else { + keyPressHandlers.put(annotation.keyType(), predicate); + } + } + } + + } + } + } +} diff --git a/src/main/java/cz/jzitnik/utils/UIClickHandlerRepository.java b/src/main/java/cz/jzitnik/utils/UIRoomClickHandlerRepository.java similarity index 80% rename from src/main/java/cz/jzitnik/utils/UIClickHandlerRepository.java rename to src/main/java/cz/jzitnik/utils/UIRoomClickHandlerRepository.java index 5caa79e..70d9e88 100644 --- a/src/main/java/cz/jzitnik/utils/UIClickHandlerRepository.java +++ b/src/main/java/cz/jzitnik/utils/UIRoomClickHandlerRepository.java @@ -2,33 +2,24 @@ package cz.jzitnik.utils; import com.googlecode.lanterna.TerminalPosition; import cz.jzitnik.annotations.Dependency; +import cz.jzitnik.annotations.injectors.InjectDependency; import cz.jzitnik.annotations.injectors.InjectState; import cz.jzitnik.events.MouseAction; import cz.jzitnik.events.RerenderScreen; import cz.jzitnik.game.GameRoom; import cz.jzitnik.game.GameState; -import cz.jzitnik.game.objects.GlobalUIClickHandler; import cz.jzitnik.game.objects.UIClickHandler; import java.util.Map; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @Dependency -public class UIClickHandlerRepository { +public class UIRoomClickHandlerRepository { private final Map> roomSpecificHandlers = new ConcurrentHashMap<>(); - private final Set globalHandlers = ConcurrentHashMap.newKeySet(); @InjectState private GameState gameState; - - public int registerGlobalHandler(GlobalUIClickHandler handler) { - globalHandlers.add(handler); - return handler.hashCode(); - } - - public void removeGlobalHandler(int hashCode) { - globalHandlers.removeIf(handler -> handler.hashCode() == hashCode); - } + @InjectDependency + private GlobalIOHandlerRepository globalIOHandlerRepository; public int registerCurrentRoomHandler(RerenderScreen.ScreenPart screenPart, UIClickHandler uiClickHandler) { GameRoom currentRoom = gameState.getCurrentRoom(); @@ -62,13 +53,7 @@ public class UIClickHandlerRepository { } } - for (var handler : globalHandlers) { - if (handler.handleClick(mouseAction)) { - return true; - } - } - - return false; + return globalIOHandlerRepository.click(mouseAction); } public boolean handleElse(MouseAction mouseAction) { @@ -88,13 +73,7 @@ public class UIClickHandlerRepository { } } - for (var handler : globalHandlers) { - if (handler.handleElse(mouseAction)) { - return true; - } - } - - return false; + return globalIOHandlerRepository.mElse(mouseAction); } public boolean handleMove(MouseAction mouseAction) { @@ -113,13 +92,7 @@ public class UIClickHandlerRepository { } } - for (var handler : globalHandlers) { - if (handler.handleMove(mouseAction)) { - return true; - } - } - - return false; + return globalIOHandlerRepository.move(mouseAction); } public void removeHandlerForCurrentRoom(int screenPartHashCode) {