feat: Dropped item disappears in 5 minutes

This commit is contained in:
2026-01-05 22:15:23 +01:00
parent f02a186dc3
commit 4e69859b00
5 changed files with 160 additions and 5 deletions

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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 <T> ScheduledFuture<T> schedule(Callable<T> 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<ScheduleList.Schedule<?>> 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<Schedule<?>> schedules) {
this.schedules = schedules;
}
private ScheduleList() {
this.schedules = new HashSet<>();
}
@Getter
public static class Schedule<T> implements Serializable {
private final ScheduleType type;
private long delay;
private long rate;
private TimeUnit timeUnit;
private long remaining;
private final transient ScheduledFuture<T> future;
protected Schedule(ScheduleType type, long delay, long rate, TimeUnit timeUnit, ScheduledFuture<T> future) {
this.type = type;
this.delay = delay;
this.rate = rate;
this.timeUnit = timeUnit;
this.future = future;
}
}
private final Set<Schedule<?>> schedules;
public <T> ScheduledFuture<T> add(Schedule<T> schedule) {
schedules.add(schedule);
return schedule.future;
}
}
}

View File

@@ -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<Registry> 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);
}