diff --git a/src/main/java/cz/jzitnik/events/RerenderScreen.java b/src/main/java/cz/jzitnik/events/RerenderScreen.java index dbaca6c..5e2250c 100644 --- a/src/main/java/cz/jzitnik/events/RerenderScreen.java +++ b/src/main/java/cz/jzitnik/events/RerenderScreen.java @@ -10,18 +10,11 @@ import java.awt.*; public record RerenderScreen(ScreenPart[] parts) implements Event { public RerenderScreen(ScreenPart part) { - this(new ScreenPart[] { part }); + this(new ScreenPart[]{part}); } public static RerenderScreen full(TerminalSize terminalSize) { - return new RerenderScreen( - new ScreenPart[]{ - new ScreenPart( - new TerminalPosition(0, 0), - new TerminalPosition(terminalSize.getColumns() - 1, terminalSize.getRows() - 1) - ) - } - ); + return new RerenderScreen(new ScreenPart[]{ScreenPart.full(terminalSize)}); } @Data @@ -29,5 +22,20 @@ public record RerenderScreen(ScreenPart[] parts) implements Event { public static class ScreenPart { private TerminalPosition start; private TerminalPosition end; + + public static ScreenPart full(TerminalSize terminalSize) { + return new ScreenPart( + new TerminalPosition(0, 0), + new TerminalPosition(terminalSize.getColumns() - 1, terminalSize.getRows() - 1) + ); + } + + public boolean isWithin(TerminalPosition terminalPosition) { + return + terminalPosition.getColumn() >= start.getColumn() && + terminalPosition.getColumn() <= end.getColumn() && + terminalPosition.getRow() >= start.getRow() && + terminalPosition.getRow() <= end.getRow(); + } } } diff --git a/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java b/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java index 369bf91..c53c2a2 100644 --- a/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java +++ b/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java @@ -9,6 +9,7 @@ import cz.jzitnik.game.GameState; import cz.jzitnik.game.objects.GameObject; import cz.jzitnik.game.objects.Interactable; import cz.jzitnik.utils.DependencyManager; +import cz.jzitnik.utils.UIClickHandlerRepository; import cz.jzitnik.utils.events.AbstractEventHandler; import cz.jzitnik.utils.events.EventManager; @@ -23,6 +24,9 @@ public class MouseActionEventHandler extends AbstractEventHandler { @InjectDependency private EventManager eventManager; + @InjectDependency + private UIClickHandlerRepository uiClickHandlerRepository; + @InjectState private GameState gameState; @@ -38,10 +42,12 @@ public class MouseActionEventHandler extends AbstractEventHandler { case CLICK_RELEASE -> { Optional object = gameState.getCurrentRoom().getObjects().stream().filter(GameObject::isSelected).findFirst(); - if (object.isEmpty()) return; + if (object.isPresent()) { + ((Interactable) object.get()).interact(dm); + return; + } - object.get().setSelected(false); - ((Interactable) object.get()).interact(dm); + uiClickHandlerRepository.handleClick(event); } } } diff --git a/src/main/java/cz/jzitnik/game/GameSetup.java b/src/main/java/cz/jzitnik/game/GameSetup.java index 27e823c..4b129d6 100644 --- a/src/main/java/cz/jzitnik/game/GameSetup.java +++ b/src/main/java/cz/jzitnik/game/GameSetup.java @@ -7,6 +7,7 @@ import cz.jzitnik.game.items.GameItem; import cz.jzitnik.game.items.WoodenSword; import cz.jzitnik.game.objects.Chest; import cz.jzitnik.game.utils.RoomCords; +import cz.jzitnik.utils.DependencyManager; @Dependency public class GameSetup { @@ -16,6 +17,9 @@ public class GameSetup { @InjectDependency private ResourceManager resourceManager; + @InjectDependency + private DependencyManager dependencyManager; + public void setup() { GameRoom mainRoom = new GameRoom(ResourceManager.Resource.ROOM1); GameRoom rightRoom = new GameRoom(ResourceManager.Resource.ROOM2); @@ -24,7 +28,7 @@ public class GameSetup { mainRoom.setRight(rightRoom); rightRoom.setUp(topRightRoom); - Chest chest = new Chest(resourceManager, new RoomCords(100, 45), new GameItem[]{ + Chest chest = new Chest(dependencyManager, resourceManager, new RoomCords(100, 45), new GameItem[]{ new WoodenSword(resourceManager), new WoodenSword(resourceManager), }); diff --git a/src/main/java/cz/jzitnik/game/objects/Chest.java b/src/main/java/cz/jzitnik/game/objects/Chest.java index 6701734..d4bb3bd 100644 --- a/src/main/java/cz/jzitnik/game/objects/Chest.java +++ b/src/main/java/cz/jzitnik/game/objects/Chest.java @@ -3,6 +3,9 @@ package cz.jzitnik.game.objects; import com.google.common.collect.Lists; import com.googlecode.lanterna.TerminalPosition; import com.googlecode.lanterna.TextColor; +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; @@ -17,6 +20,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.events.EventManager; import lombok.extern.slf4j.Slf4j; @@ -24,25 +28,39 @@ import java.awt.image.BufferedImage; import java.util.List; @Slf4j -public final class Chest extends GameObject implements Interactable { +public final class Chest extends GameObject implements Interactable, UIClickHandler { private final List items; + private final DependencyManager dependencyManager; - public Chest(ResourceManager resourceManager, RoomCords cords, GameItem[] items) { + private int listenerHashCode; + + @InjectDependency + private StateManager sm; + @InjectDependency + private ResourceManager resourceManager; + @InjectDependency + private EventManager eventManager; + @InjectDependency + private UIClickHandlerRepository uiClickHandlerRepository; + @InjectState + private GameState gameState; + @InjectState + private ScreenBuffer screenBuffer; + @InjectState + private TerminalState terminalState; + + public Chest(DependencyManager dm, ResourceManager resourceManager, RoomCords cords, GameItem[] items) { super(resourceManager.getResource(ResourceManager.Resource.CHEST), cords, true); this.items = Lists.newArrayList(items); + this.dependencyManager = dm; } @Override public void interact(DependencyManager dm) { - setSelected(true); + dm.inject(this); log.debug("Interacted with chest"); - StateManager sm = dm.getDependencyOrThrow(StateManager.class); - EventManager eventManager = dm.getDependencyOrThrow(EventManager.class); - GameState gameState = sm.getOrThrow(GameState.class); - ScreenBuffer screenBuffer = sm.getOrThrow(ScreenBuffer.class); - TerminalState terminalState = sm.getOrThrow(TerminalState.class); - ResourceManager resourceManager = dm.getDependencyOrThrow(ResourceManager.class); + GameRoom currentRoom = gameState.getCurrentRoom(); Player player = gameState.getPlayer(); BufferedImage playerTexture = RerenderUtils.getPlayer(resourceManager, player); @@ -67,7 +85,7 @@ public final class Chest extends GameObject implements Interactable { TerminalPosition guiEnd = new TerminalPosition((chestGUIStartX + chestUISizeX - 1) / 2, ((chestGUIStartY + chestUISizeY - 1) / 2)); for (int y = chestGUIStartY; y < chestGUIStartY + chestUISizeY; y++) { - for (int x = chestGUIStartX ; x < chestGUIStartX + chestUISizeX; x++) { + for (int x = chestGUIStartX; x < chestGUIStartX + chestUISizeX; x++) { Pixel pixel = new ColoredPixel(TextColor.ANSI.RED); buffer[y + start.getY()][x + start.getX()] = pixel; @@ -77,6 +95,13 @@ public final class Chest extends GameObject implements Interactable { RerenderUtils.rerenderPart(guiStart.getColumn(), guiEnd.getColumn(), guiStart.getRow(), guiEnd.getRow(), start.getX(), start.getY(), currentRoom, room, player, playerTexture, screenBuffer, resourceManager); + this.listenerHashCode = uiClickHandlerRepository.registerCurrentRoomHandler(RerenderScreen.ScreenPart.full(terminalState.getTerminalScreen().getTerminalSize()), this); + eventManager.emitEvent(RerenderScreen.full(terminalState.getTerminalScreen().getTerminalSize())); // TODO: Make this not rerender full screen } + + @Override + public void handleClick(MouseAction mouseAction) { + log.debug("Test"); + } } diff --git a/src/main/java/cz/jzitnik/game/objects/UIClickHandler.java b/src/main/java/cz/jzitnik/game/objects/UIClickHandler.java new file mode 100644 index 0000000..fb617f8 --- /dev/null +++ b/src/main/java/cz/jzitnik/game/objects/UIClickHandler.java @@ -0,0 +1,7 @@ +package cz.jzitnik.game.objects; + +import cz.jzitnik.events.MouseAction; + +public interface UIClickHandler { + void handleClick(MouseAction mouseAction); +} diff --git a/src/main/java/cz/jzitnik/utils/UIClickHandlerRepository.java b/src/main/java/cz/jzitnik/utils/UIClickHandlerRepository.java new file mode 100644 index 0000000..a39f552 --- /dev/null +++ b/src/main/java/cz/jzitnik/utils/UIClickHandlerRepository.java @@ -0,0 +1,66 @@ +package cz.jzitnik.utils; + +import com.googlecode.lanterna.TerminalPosition; +import cz.jzitnik.annotations.Dependency; +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.UIClickHandler; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Dependency +public class UIClickHandlerRepository { + @InjectState + private GameState gameState; + + private final Map> roomSpecificHandlers = new ConcurrentHashMap<>(); + + public int registerCurrentRoomHandler(RerenderScreen.ScreenPart screenPart, UIClickHandler uiClickHandler) { + GameRoom currentRoom = gameState.getCurrentRoom(); + return registerRoomSpecificHandler(currentRoom, screenPart, uiClickHandler); + } + + public int registerRoomSpecificHandler(GameRoom gameRoom, RerenderScreen.ScreenPart screenPart, UIClickHandler uiClickHandler) { + if (!roomSpecificHandlers.containsKey(gameRoom)) { + roomSpecificHandlers.put(gameRoom, new ConcurrentHashMap<>()); + } + + roomSpecificHandlers.get(gameRoom).put(screenPart, uiClickHandler); + + return screenPart.hashCode(); + } + + public void handleClick(MouseAction mouseAction) { + if (!roomSpecificHandlers.containsKey(gameState.getCurrentRoom())) { + return; + } + + Map handlers = roomSpecificHandlers.get(gameState.getCurrentRoom()); + + for (var entry : handlers.entrySet()) { + RerenderScreen.ScreenPart part = entry.getKey(); + UIClickHandler uiClickHandler = entry.getValue(); + + if (part.isWithin(mouseAction.getPosition())) { + uiClickHandler.handleClick(mouseAction); + return; + } + } + } + + public void removeHandlerForCurrentRoom(int screenPartHashCode, UIClickHandler uiClickHandler) { + GameRoom currentRoom = gameState.getCurrentRoom(); + if (!roomSpecificHandlers.containsKey(currentRoom)) return; + Map handlers = roomSpecificHandlers.get(currentRoom); + + for (var key: handlers.keySet()) { + if (key.hashCode() == screenPartHashCode) { + handlers.remove(key, uiClickHandler); + } + } + } +}