From f8f150cdf06aa2311a006a33a302e76cdd8618a8 Mon Sep 17 00:00:00 2001 From: jzitnik-dev Date: Wed, 18 Feb 2026 10:59:51 +0100 Subject: [PATCH] feat: Give item on dialog --- .../common/models/coordinates/RoomCords.java | 8 +++ .../events/handlers/DialogEventHandler.java | 6 +- .../java/cz/jzitnik/client/game/Player.java | 2 +- .../cz/jzitnik/client/game/dialog/OnEnd.java | 63 +++++++++++++++++-- .../client/game/mobs/HittableMobDrops.java | 23 ++++--- .../client/utils/events/EventManager.java | 1 - game/src/main/resources/setup/rooms.yaml | 14 +++-- 7 files changed, 90 insertions(+), 27 deletions(-) diff --git a/common/src/main/java/cz/jzitnik/common/models/coordinates/RoomCords.java b/common/src/main/java/cz/jzitnik/common/models/coordinates/RoomCords.java index 4534fb4..d55c18d 100644 --- a/common/src/main/java/cz/jzitnik/common/models/coordinates/RoomCords.java +++ b/common/src/main/java/cz/jzitnik/common/models/coordinates/RoomCords.java @@ -6,6 +6,7 @@ import lombok.Getter; import lombok.ToString; import lombok.extern.slf4j.Slf4j; +import java.awt.image.BufferedImage; import java.io.Serializable; import java.util.List; @@ -16,6 +17,13 @@ public class RoomCords implements Cloneable, Serializable { private int x; private int y; + public RoomCords calculateCenter(BufferedImage texture) { + return new RoomCords( + x + texture.getWidth() / 2, + y + texture.getHeight() / 2 + ); + } + @JsonCreator public RoomCords( @JsonProperty("x") int x, diff --git a/game/src/main/java/cz/jzitnik/client/events/handlers/DialogEventHandler.java b/game/src/main/java/cz/jzitnik/client/events/handlers/DialogEventHandler.java index cfd7deb..dcd111d 100644 --- a/game/src/main/java/cz/jzitnik/client/events/handlers/DialogEventHandler.java +++ b/game/src/main/java/cz/jzitnik/client/events/handlers/DialogEventHandler.java @@ -251,11 +251,11 @@ public class DialogEventHandler extends AbstractEventHandler { clear(start, size); eventManager.emitEvent(nextDialog); - } else if (onEnd instanceof OnEnd.RunCode(Runnable runnable, OnEnd end)) { + } else if (onEnd instanceof OnEnd.RunCode runCode) { + Runnable runnable = runCode.getRunnable(); dependencyManager.inject(runnable); runnable.run(); - next(end, start, size); - + next(runCode.getOnEnd(), start, size); } else if (onEnd instanceof OnEnd.End) { clear(start, size); dialogState.setCurrentDialog(null); diff --git a/game/src/main/java/cz/jzitnik/client/game/Player.java b/game/src/main/java/cz/jzitnik/client/game/Player.java index 5f01c25..8481c27 100644 --- a/game/src/main/java/cz/jzitnik/client/game/Player.java +++ b/game/src/main/java/cz/jzitnik/client/game/Player.java @@ -28,7 +28,7 @@ public class Player implements GamePlayer { private final int id; public static final int MAX_STAMINA = 20; public static final int MAX_HEALTH = 30; - private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); private final RoomCords playerCords; private final RoomPart collider; diff --git a/game/src/main/java/cz/jzitnik/client/game/dialog/OnEnd.java b/game/src/main/java/cz/jzitnik/client/game/dialog/OnEnd.java index 531b605..147e20f 100644 --- a/game/src/main/java/cz/jzitnik/client/game/dialog/OnEnd.java +++ b/game/src/main/java/cz/jzitnik/client/game/dialog/OnEnd.java @@ -4,8 +4,18 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import cz.jzitnik.client.annotations.injectors.InjectDependency; +import cz.jzitnik.client.annotations.injectors.InjectState; +import cz.jzitnik.client.events.InventoryRerender; import cz.jzitnik.client.game.GameState; +import cz.jzitnik.client.game.Player; import cz.jzitnik.client.game.Requirement; +import cz.jzitnik.client.game.ResourceManager; +import cz.jzitnik.client.game.items.GameItem; +import cz.jzitnik.client.game.mobs.HittableMobDrops; +import cz.jzitnik.client.utils.events.EventManager; +import lombok.Getter; +import lombok.RequiredArgsConstructor; import java.util.Arrays; import java.util.Optional; @@ -18,13 +28,56 @@ import java.util.Optional; @JsonSubTypes.Type(value = OnEnd.Continue.class, name = "continue"), @JsonSubTypes.Type(value = OnEnd.AskQuestion.class, name = "ask_question"), @JsonSubTypes.Type(value = OnEnd.End.class, name = "end"), + @JsonSubTypes.Type(value = OnEnd.GiveItem.class, name = "give_item") }) public interface OnEnd { record End() implements OnEnd { } - record RunCode(Runnable runnable, OnEnd onEnd) implements OnEnd { - } // TODO: Serialize + class GiveItem extends RunCode { + @JsonCreator + public GiveItem( + @JsonProperty("item") GameItem item, + @JsonProperty("then") OnEnd onEnd + ) { + super(new Run(item), onEnd); + } + + @RequiredArgsConstructor + private static class Run implements Runnable { + private final GameItem item; + + @InjectState + private GameState gameState; + + @InjectDependency + private EventManager eventManager; + + @InjectDependency + private ResourceManager resourceManager; + + @Override + public void run() { + Player player = gameState.getPlayer(); + var playerCords = player.getPlayerCords().calculateCenter(player.getTexture(resourceManager)); + + boolean addedIntoInventory = player.addItem(item); + + if (!addedIntoInventory) { + eventManager.emitEvent(HittableMobDrops.dropItem(playerCords.getX(), playerCords.getY(), gameState.getCurrentRoom(), item)); + } else { + eventManager.emitEvent(new InventoryRerender()); + } + } + } + } + + @Getter + @RequiredArgsConstructor + class RunCode implements OnEnd { + private final Runnable runnable; + private final OnEnd onEnd; + } record Continue(Dialog nextDialog) implements OnEnd { @JsonCreator @@ -57,15 +110,13 @@ public interface OnEnd { if (requirement.isPresent()) { Requirement requirement = requirement().get(); if (requirement.itemType() != null) { - if (Arrays.stream(gameState.getPlayer().getInventory()).noneMatch(item -> { + return Arrays.stream(gameState.getPlayer().getInventory()).anyMatch(item -> { if (item == null) { return false; } return item.getType().getItemType().getSimpleName().equals(requirement.itemType()); - })) { - return false; - } + }); } return true; diff --git a/game/src/main/java/cz/jzitnik/client/game/mobs/HittableMobDrops.java b/game/src/main/java/cz/jzitnik/client/game/mobs/HittableMobDrops.java index 06cbece..7cb2086 100644 --- a/game/src/main/java/cz/jzitnik/client/game/mobs/HittableMobDrops.java +++ b/game/src/main/java/cz/jzitnik/client/game/mobs/HittableMobDrops.java @@ -55,10 +55,9 @@ public class HittableMobDrops extends HittableMob { Player player = gameState.getPlayer(); RoomCords enemyCords = getCords(); BufferedImage enemyTexture = getTexture(); - GameRoom currentRoom = gameState.getCurrentRoom(); - int roomX = enemyCords.getX() + enemyTexture.getWidth() / 2; int roomY = enemyCords.getY() + enemyTexture.getHeight() / 2; + GameRoom currentRoom = gameState.getCurrentRoom(); List events = new ArrayList<>(); @@ -71,17 +70,21 @@ public class HittableMobDrops extends HittableMob { events.add(new InventoryRerender()); } } else { - double angle = ThreadLocalRandom.current().nextDouble(0, Math.PI * 2); - double radius = ThreadLocalRandom.current().nextDouble(0, DROP_ITEM_ON_GROUND_RADIUS); - int randomX = roomX + (int) (Math.cos(angle) * radius); - int randomY = roomY + (int) (Math.sin(angle) * radius); - RoomCords itemCords = new RoomCords(randomX, randomY); - DroppedItem droppedItem = new DroppedItem(currentRoom, itemCords, item); - currentRoom.getDroppedItems().add(droppedItem); - events.add(new DroppedItemRerender(droppedItem)); + events.add(dropItem(roomX, roomY, currentRoom, item)); } } eventManager.emitEvent(events, this::afterKill); } + + public static Event dropItem(int x, int y, GameRoom currentRoom, GameItem item) { + double angle = ThreadLocalRandom.current().nextDouble(0, Math.PI * 2); + double radius = ThreadLocalRandom.current().nextDouble(0, DROP_ITEM_ON_GROUND_RADIUS); + int randomX = x + (int) (Math.cos(angle) * radius); + int randomY = y + (int) (Math.sin(angle) * radius); + RoomCords itemCords = new RoomCords(randomX, randomY); + DroppedItem droppedItem = new DroppedItem(currentRoom, itemCords, item); + currentRoom.getDroppedItems().add(droppedItem); + return new DroppedItemRerender(droppedItem); + } } diff --git a/game/src/main/java/cz/jzitnik/client/utils/events/EventManager.java b/game/src/main/java/cz/jzitnik/client/utils/events/EventManager.java index ddcf8d9..1fee7a9 100644 --- a/game/src/main/java/cz/jzitnik/client/utils/events/EventManager.java +++ b/game/src/main/java/cz/jzitnik/client/utils/events/EventManager.java @@ -64,7 +64,6 @@ public class EventManager extends Thread { } } - @SuppressWarnings("unchecked") public EventManager(Reflections reflections, DependencyManager dependencyManager) { this.dependencyManager = dependencyManager; setDaemon(true); diff --git a/game/src/main/resources/setup/rooms.yaml b/game/src/main/resources/setup/rooms.yaml index 8690026..7d6f8bf 100644 --- a/game/src/main/resources/setup/rooms.yaml +++ b/game/src/main/resources/setup/rooms.yaml @@ -78,12 +78,14 @@ item: "quest_item_boss_skin" dialog: text: "Well done. Here is the key." - giveItem: - id: 300 - name: "Cave Exit Key" - type: { name: "quest_item_final_key" } - texture: "KEY" - onEnd: { type: end } + onEnd: + type: "give_item" + item: + id: 800 + name: "Something" + type: { name: "junk" } + texture: "APPLE" + then: { type: end } - answer: "Not yet" dialog: text: "Then go back before it finds you."