feat: Click handler repository

This commit is contained in:
2025-12-16 16:58:39 +01:00
parent e1404ea928
commit 862baf9809
6 changed files with 139 additions and 23 deletions

View File

@@ -14,14 +14,7 @@ public record RerenderScreen(ScreenPart[] parts) implements Event {
} }
public static RerenderScreen full(TerminalSize terminalSize) { public static RerenderScreen full(TerminalSize terminalSize) {
return new RerenderScreen( return new RerenderScreen(new ScreenPart[]{ScreenPart.full(terminalSize)});
new ScreenPart[]{
new ScreenPart(
new TerminalPosition(0, 0),
new TerminalPosition(terminalSize.getColumns() - 1, terminalSize.getRows() - 1)
)
}
);
} }
@Data @Data
@@ -29,5 +22,20 @@ public record RerenderScreen(ScreenPart[] parts) implements Event {
public static class ScreenPart { public static class ScreenPart {
private TerminalPosition start; private TerminalPosition start;
private TerminalPosition end; 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();
}
} }
} }

View File

@@ -9,6 +9,7 @@ import cz.jzitnik.game.GameState;
import cz.jzitnik.game.objects.GameObject; import cz.jzitnik.game.objects.GameObject;
import cz.jzitnik.game.objects.Interactable; import cz.jzitnik.game.objects.Interactable;
import cz.jzitnik.utils.DependencyManager; import cz.jzitnik.utils.DependencyManager;
import cz.jzitnik.utils.UIClickHandlerRepository;
import cz.jzitnik.utils.events.AbstractEventHandler; import cz.jzitnik.utils.events.AbstractEventHandler;
import cz.jzitnik.utils.events.EventManager; import cz.jzitnik.utils.events.EventManager;
@@ -23,6 +24,9 @@ public class MouseActionEventHandler extends AbstractEventHandler<MouseAction> {
@InjectDependency @InjectDependency
private EventManager eventManager; private EventManager eventManager;
@InjectDependency
private UIClickHandlerRepository uiClickHandlerRepository;
@InjectState @InjectState
private GameState gameState; private GameState gameState;
@@ -38,10 +42,12 @@ public class MouseActionEventHandler extends AbstractEventHandler<MouseAction> {
case CLICK_RELEASE -> { case CLICK_RELEASE -> {
Optional<GameObject> object = gameState.getCurrentRoom().getObjects().stream().filter(GameObject::isSelected).findFirst(); Optional<GameObject> object = gameState.getCurrentRoom().getObjects().stream().filter(GameObject::isSelected).findFirst();
if (object.isEmpty()) return; if (object.isPresent()) {
object.get().setSelected(false);
((Interactable) object.get()).interact(dm); ((Interactable) object.get()).interact(dm);
return;
}
uiClickHandlerRepository.handleClick(event);
} }
} }
} }

View File

@@ -7,6 +7,7 @@ import cz.jzitnik.game.items.GameItem;
import cz.jzitnik.game.items.WoodenSword; import cz.jzitnik.game.items.WoodenSword;
import cz.jzitnik.game.objects.Chest; import cz.jzitnik.game.objects.Chest;
import cz.jzitnik.game.utils.RoomCords; import cz.jzitnik.game.utils.RoomCords;
import cz.jzitnik.utils.DependencyManager;
@Dependency @Dependency
public class GameSetup { public class GameSetup {
@@ -16,6 +17,9 @@ public class GameSetup {
@InjectDependency @InjectDependency
private ResourceManager resourceManager; private ResourceManager resourceManager;
@InjectDependency
private DependencyManager dependencyManager;
public void setup() { public void setup() {
GameRoom mainRoom = new GameRoom(ResourceManager.Resource.ROOM1); GameRoom mainRoom = new GameRoom(ResourceManager.Resource.ROOM1);
GameRoom rightRoom = new GameRoom(ResourceManager.Resource.ROOM2); GameRoom rightRoom = new GameRoom(ResourceManager.Resource.ROOM2);
@@ -24,7 +28,7 @@ public class GameSetup {
mainRoom.setRight(rightRoom); mainRoom.setRight(rightRoom);
rightRoom.setUp(topRightRoom); 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),
new WoodenSword(resourceManager), new WoodenSword(resourceManager),
}); });

View File

@@ -3,6 +3,9 @@ package cz.jzitnik.game.objects;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.googlecode.lanterna.TerminalPosition; import com.googlecode.lanterna.TerminalPosition;
import com.googlecode.lanterna.TextColor; 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.events.RerenderScreen;
import cz.jzitnik.game.GameRoom; import cz.jzitnik.game.GameRoom;
import cz.jzitnik.game.GameState; import cz.jzitnik.game.GameState;
@@ -17,6 +20,7 @@ import cz.jzitnik.ui.pixels.Pixel;
import cz.jzitnik.utils.DependencyManager; import cz.jzitnik.utils.DependencyManager;
import cz.jzitnik.utils.RerenderUtils; import cz.jzitnik.utils.RerenderUtils;
import cz.jzitnik.utils.StateManager; import cz.jzitnik.utils.StateManager;
import cz.jzitnik.utils.UIClickHandlerRepository;
import cz.jzitnik.utils.events.EventManager; import cz.jzitnik.utils.events.EventManager;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -24,25 +28,39 @@ import java.awt.image.BufferedImage;
import java.util.List; import java.util.List;
@Slf4j @Slf4j
public final class Chest extends GameObject implements Interactable { public final class Chest extends GameObject implements Interactable, UIClickHandler {
private final List<GameItem> items; private final List<GameItem> 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); super(resourceManager.getResource(ResourceManager.Resource.CHEST), cords, true);
this.items = Lists.newArrayList(items); this.items = Lists.newArrayList(items);
this.dependencyManager = dm;
} }
@Override @Override
public void interact(DependencyManager dm) { public void interact(DependencyManager dm) {
setSelected(true); dm.inject(this);
log.debug("Interacted with chest"); 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(); GameRoom currentRoom = gameState.getCurrentRoom();
Player player = gameState.getPlayer(); Player player = gameState.getPlayer();
BufferedImage playerTexture = RerenderUtils.getPlayer(resourceManager, player); BufferedImage playerTexture = RerenderUtils.getPlayer(resourceManager, player);
@@ -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); 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 eventManager.emitEvent(RerenderScreen.full(terminalState.getTerminalScreen().getTerminalSize())); // TODO: Make this not rerender full screen
} }
@Override
public void handleClick(MouseAction mouseAction) {
log.debug("Test");
}
} }

View File

@@ -0,0 +1,7 @@
package cz.jzitnik.game.objects;
import cz.jzitnik.events.MouseAction;
public interface UIClickHandler {
void handleClick(MouseAction mouseAction);
}

View File

@@ -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<GameRoom, Map<RerenderScreen.ScreenPart, UIClickHandler>> 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<RerenderScreen.ScreenPart, UIClickHandler> 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<RerenderScreen.ScreenPart, UIClickHandler> handlers = roomSpecificHandlers.get(currentRoom);
for (var key: handlers.keySet()) {
if (key.hashCode() == screenPartHashCode) {
handlers.remove(key, uiClickHandler);
}
}
}
}