diff --git a/src/main/java/cz/jzitnik/config/CoreLogic.java b/src/main/java/cz/jzitnik/config/CoreLogic.java new file mode 100644 index 0000000..4d056e7 --- /dev/null +++ b/src/main/java/cz/jzitnik/config/CoreLogic.java @@ -0,0 +1,10 @@ +package cz.jzitnik.config; + +import cz.jzitnik.annotations.Config; +import lombok.Getter; + +@Config +@Getter +public class CoreLogic { + private final int itemDropDisappearMinutes = 5; +} diff --git a/src/main/java/cz/jzitnik/game/objects/DroppedItem.java b/src/main/java/cz/jzitnik/game/objects/DroppedItem.java index b0070b0..f1add18 100644 --- a/src/main/java/cz/jzitnik/game/objects/DroppedItem.java +++ b/src/main/java/cz/jzitnik/game/objects/DroppedItem.java @@ -2,6 +2,7 @@ package cz.jzitnik.game.objects; import cz.jzitnik.events.DroppedItemRerender; import cz.jzitnik.events.InventoryRerender; +import cz.jzitnik.game.GameRoom; import cz.jzitnik.game.GameState; import cz.jzitnik.game.items.GameItem; import cz.jzitnik.game.utils.RoomCords; @@ -19,6 +20,7 @@ import java.io.Serializable; @Getter @RequiredArgsConstructor public final class DroppedItem implements Selectable, Serializable { + private final GameRoom room; private final RoomCords cords; private final GameItem item; @Setter diff --git a/src/main/java/cz/jzitnik/ui/Inventory.java b/src/main/java/cz/jzitnik/ui/Inventory.java index 75a1d49..b27892c 100644 --- a/src/main/java/cz/jzitnik/ui/Inventory.java +++ b/src/main/java/cz/jzitnik/ui/Inventory.java @@ -4,9 +4,11 @@ import com.googlecode.lanterna.TerminalPosition; import com.googlecode.lanterna.TerminalSize; import com.googlecode.lanterna.TextColor; import cz.jzitnik.annotations.Dependency; +import cz.jzitnik.annotations.injectors.InjectConfig; import cz.jzitnik.annotations.injectors.InjectDependency; import cz.jzitnik.annotations.injectors.InjectState; import cz.jzitnik.annotations.ui.*; +import cz.jzitnik.config.CoreLogic; import cz.jzitnik.events.DroppedItemRerender; import cz.jzitnik.events.InventoryRerender; import cz.jzitnik.events.KeyboardPressEvent; @@ -23,6 +25,7 @@ import cz.jzitnik.ui.pixels.Pixel; import cz.jzitnik.ui.utils.Grid; import cz.jzitnik.utils.DependencyManager; import cz.jzitnik.utils.RerenderUtils; +import cz.jzitnik.utils.ScheduledSerializedTaskManager; import cz.jzitnik.utils.StateManager; import cz.jzitnik.utils.events.EventManager; import lombok.Getter; @@ -39,7 +42,7 @@ import java.util.stream.IntStream; @UI @Dependency public class Inventory { - private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); public static final int ITEMS_X = 3; public static final int ITEMS_Y = 5; private static final int OUTER_BORDER_WIDTH = 2; @@ -92,7 +95,11 @@ public class Inventory { @InjectDependency private DependencyManager dependencyManager; @InjectDependency + private ScheduledSerializedTaskManager scheduledSerializedTaskManager; + @InjectDependency private StateManager stateManager; + @InjectConfig + private CoreLogic coreLogic; @Getter private int offsetX; @Getter @@ -118,7 +125,15 @@ public class Inventory { var player = gameState.getPlayer(); var inventory = player.getInventory(); var currentRoom = gameState.getCurrentRoom(); - DroppedItem droppedItem = new DroppedItem(player.getPlayerCords().clone(), inventory[inventoryState.selectedItem]); + // Create timer + DroppedItem droppedItem = new DroppedItem(currentRoom, player.getPlayerCords().clone(), inventory[inventoryState.selectedItem]); + scheduledSerializedTaskManager.schedule(() -> { + droppedItem.getRoom().getDroppedItems().remove(droppedItem); + + if (droppedItem.getRoom() == currentRoom) { + eventManager.emitEvent(new DroppedItemRerender(droppedItem)); + } + }, coreLogic.getItemDropDisappearMinutes(), TimeUnit.MINUTES); currentRoom.getDroppedItems().add(droppedItem); inventory[inventoryState.selectedItem] = null; inventoryState.selectedItem = -1; diff --git a/src/main/java/cz/jzitnik/utils/ScheduledSerializedTaskManager.java b/src/main/java/cz/jzitnik/utils/ScheduledSerializedTaskManager.java new file mode 100644 index 0000000..600e3df --- /dev/null +++ b/src/main/java/cz/jzitnik/utils/ScheduledSerializedTaskManager.java @@ -0,0 +1,129 @@ +package cz.jzitnik.utils; + +import cz.jzitnik.annotations.Dependency; +import cz.jzitnik.annotations.injectors.InjectDependency; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +// THIS WILL DEFINITELY NEED MORE TESTING + +@Slf4j +@Dependency +public class ScheduledSerializedTaskManager { + @InjectDependency + private ScheduledTaskManager scheduledTaskManager; + private final ScheduleList scheduleList = new ScheduleList(); + + public ScheduledFuture scheduleAtFixedRate(Runnable runnable, long rate, TimeUnit rateUnit) { + return scheduleAtFixedRate(runnable, 0, rate, rateUnit); + } + + public ScheduledFuture scheduleAtFixedRate(Runnable runnable, long initialDelay, long rate, TimeUnit rateUnit) { + return scheduleList.add( + new ScheduleList.Schedule<>( + ScheduleList.ScheduleType.REPEAT_AT_FIXED_RATE, + initialDelay, + rate, + rateUnit, + scheduledTaskManager.scheduler.scheduleAtFixedRate(runnable, initialDelay, rate, rateUnit) + ) + ); + } + + public ScheduledFuture schedule(Runnable runnable, long delay, TimeUnit unit) { + return scheduleList.add( + new ScheduleList.Schedule<>( + ScheduleList.ScheduleType.SCHEDULE, + delay, + 0, + unit, + scheduledTaskManager.scheduler.schedule(runnable, delay, unit) + ) + ); + } + + public ScheduledFuture schedule(Callable runnable, long delay, TimeUnit unit) { + return scheduleList.add( + new ScheduleList.Schedule<>( + ScheduleList.ScheduleType.SCHEDULE, + delay, + 0, + unit, + scheduledTaskManager.scheduler.schedule(runnable, delay, unit) + ) + ); + } + + // TODO: When saving the game run this to get all scheduled serialized tasks + public ScheduleList getScheduleList() { + Set> newList = new HashSet<>(); + + for (ScheduleList.Schedule schedule : scheduleList.schedules) { + if (schedule.future.state() != Future.State.RUNNING) { + continue; + } + + // Use milliseconds or something cuz when we have minutes it will be rounded a lot in the getDelay function + schedule.delay = TimeUnit.MILLISECONDS.convert(schedule.delay, schedule.timeUnit); + schedule.rate = TimeUnit.MILLISECONDS.convert(schedule.rate, schedule.timeUnit); + schedule.timeUnit = TimeUnit.MILLISECONDS; + schedule.remaining = schedule.future.getDelay(TimeUnit.MILLISECONDS); + + newList.add(schedule); + } + + return new ScheduleList(newList); + } + + // TODO: Create some function that will resume all the schedules from the [ScheduleList] class + + @Getter + public static class ScheduleList implements Serializable { + protected enum ScheduleType { + REPEAT_AT_FIXED_RATE, + SCHEDULE, + } + + private ScheduleList(Set> schedules) { + this.schedules = schedules; + } + + private ScheduleList() { + this.schedules = new HashSet<>(); + } + + @Getter + public static class Schedule implements Serializable { + private final ScheduleType type; + private long delay; + private long rate; + private TimeUnit timeUnit; + private long remaining; + private final transient ScheduledFuture future; + + protected Schedule(ScheduleType type, long delay, long rate, TimeUnit timeUnit, ScheduledFuture future) { + this.type = type; + this.delay = delay; + this.rate = rate; + this.timeUnit = timeUnit; + this.future = future; + } + } + + private final Set> schedules; + + public ScheduledFuture add(Schedule schedule) { + schedules.add(schedule); + + return schedule.future; + } + } +} diff --git a/src/main/java/cz/jzitnik/utils/ScheduledTaskManager.java b/src/main/java/cz/jzitnik/utils/ScheduledTaskManager.java index 801c418..f2a8808 100644 --- a/src/main/java/cz/jzitnik/utils/ScheduledTaskManager.java +++ b/src/main/java/cz/jzitnik/utils/ScheduledTaskManager.java @@ -16,7 +16,7 @@ import java.util.concurrent.TimeUnit; @Slf4j @Dependency public class ScheduledTaskManager { - private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(new ThreadPoolConfig().getTaskThreadCount()); + final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(new ThreadPoolConfig().getTaskThreadCount()); private final HashSet instances = new HashSet<>(); private final DependencyManager dependencyManager; @@ -34,7 +34,6 @@ public class ScheduledTaskManager { assert annotation != null; instances.add(new Registry(instance, annotation)); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { throw new RuntimeException(e); @@ -49,7 +48,7 @@ public class ScheduledTaskManager { } } - public ScheduledFuture tempScheduleFixedRate(Runnable runnable, int rate, TimeUnit rateUnit) { + public ScheduledFuture tempScheduleFixedRate(Runnable runnable, long rate, TimeUnit rateUnit) { return scheduler.scheduleAtFixedRate(runnable, 0, rate, rateUnit); }