feat: Room Task Scheduler for mob logic
This commit is contained in:
11
src/main/java/cz/jzitnik/annotations/PostInit.java
Normal file
11
src/main/java/cz/jzitnik/annotations/PostInit.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package cz.jzitnik.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface PostInit {
|
||||
}
|
||||
@@ -5,6 +5,6 @@ import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Config
|
||||
public class EventThreadPoolConfig {
|
||||
private final int threadCount = 8;
|
||||
public class Logging {
|
||||
private final boolean showPlayerCordsLogs = false;
|
||||
}
|
||||
11
src/main/java/cz/jzitnik/config/ThreadPoolConfig.java
Normal file
11
src/main/java/cz/jzitnik/config/ThreadPoolConfig.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package cz.jzitnik.config;
|
||||
|
||||
import cz.jzitnik.annotations.Config;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Config
|
||||
public class ThreadPoolConfig {
|
||||
private final int eventThreadCount = 8;
|
||||
private final int taskThreadCount = 6;
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import cz.jzitnik.utils.DependencyManager;
|
||||
import cz.jzitnik.utils.StateManager;
|
||||
import cz.jzitnik.utils.ThreadManager;
|
||||
import cz.jzitnik.utils.events.AbstractEventHandler;
|
||||
import cz.jzitnik.utils.roomtasks.RoomTaskScheduler;
|
||||
|
||||
@EventHandler(ExitEvent.class)
|
||||
public class ExitEventHandler extends AbstractEventHandler<ExitEvent> {
|
||||
@@ -18,6 +19,9 @@ public class ExitEventHandler extends AbstractEventHandler<ExitEvent> {
|
||||
@InjectState
|
||||
private RunningState runningState;
|
||||
|
||||
@InjectDependency
|
||||
private RoomTaskScheduler roomTaskScheduler;
|
||||
|
||||
public ExitEventHandler(DependencyManager dm) {
|
||||
super(dm);
|
||||
}
|
||||
@@ -25,6 +29,7 @@ public class ExitEventHandler extends AbstractEventHandler<ExitEvent> {
|
||||
@Override
|
||||
public void handle(ExitEvent event) {
|
||||
threadManager.shutdownAll();
|
||||
roomTaskScheduler.finalShutdown();
|
||||
runningState.setRunning(false);
|
||||
System.exit(0); // Pls don't blame me
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import cz.jzitnik.utils.DependencyManager;
|
||||
import cz.jzitnik.utils.RerenderUtils;
|
||||
import cz.jzitnik.utils.events.AbstractEventHandler;
|
||||
import cz.jzitnik.utils.events.EventManager;
|
||||
import cz.jzitnik.utils.roomtasks.RoomTaskScheduler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
@@ -52,6 +53,9 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
|
||||
@InjectConfig
|
||||
private Debugging debugging;
|
||||
|
||||
@InjectDependency
|
||||
private RoomTaskScheduler roomTaskScheduler;
|
||||
|
||||
public FullRoomDrawHandler(DependencyManager dm) {
|
||||
super(dm);
|
||||
}
|
||||
@@ -86,6 +90,7 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
|
||||
if (renderState.isFirstRender() || event.isFullRerender()) {
|
||||
eventManager.emitEvent(RerenderScreen.full(terminalSize));
|
||||
renderState.setFirstRender(false);
|
||||
roomTaskScheduler.setupNewSchedulers(currentRoom);
|
||||
} else {
|
||||
eventManager.emitEvent(new RerenderScreen(partsToRerender.toArray(RerenderScreen.ScreenPart[]::new)));
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import cz.jzitnik.annotations.injectors.InjectConfig;
|
||||
import cz.jzitnik.annotations.injectors.InjectDependency;
|
||||
import cz.jzitnik.annotations.injectors.InjectState;
|
||||
import cz.jzitnik.config.Debugging;
|
||||
import cz.jzitnik.config.Logging;
|
||||
import cz.jzitnik.config.PlayerConfig;
|
||||
import cz.jzitnik.events.PlayerMoveEvent;
|
||||
import cz.jzitnik.events.RerenderScreen;
|
||||
@@ -58,6 +59,9 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
|
||||
@InjectState
|
||||
private RenderState renderState;
|
||||
|
||||
@InjectConfig
|
||||
private Logging logging;
|
||||
|
||||
@Override
|
||||
public void handle(PlayerMoveEvent event) {
|
||||
if (renderState.isTerminalTooSmall()) {
|
||||
@@ -121,7 +125,9 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
|
||||
}
|
||||
int newPlayerX = playerCords.getX();
|
||||
int newPlayerY = playerCords.getY();
|
||||
log.debug("x: {}, y: {}", newPlayerX, newPlayerY);
|
||||
if (logging.isShowPlayerCordsLogs()) {
|
||||
log.debug("x: {}, y: {}", newPlayerX, newPlayerY);
|
||||
}
|
||||
BufferedImage playerTexture = RerenderUtils.getPlayer(resourceManager, player);
|
||||
int forStartX = Math.min(originalPlayerX, newPlayerX);
|
||||
int forStartY = Math.min(originalPlayerY, newPlayerY);
|
||||
|
||||
@@ -11,6 +11,7 @@ import cz.jzitnik.game.utils.RoomCords;
|
||||
import cz.jzitnik.utils.DependencyManager;
|
||||
import cz.jzitnik.utils.events.AbstractEventHandler;
|
||||
import cz.jzitnik.utils.events.EventManager;
|
||||
import cz.jzitnik.utils.roomtasks.RoomTaskScheduler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@@ -26,6 +27,9 @@ public class RoomChangeEventHandler extends AbstractEventHandler<RoomChangeEvent
|
||||
@InjectDependency
|
||||
private EventManager eventManager;
|
||||
|
||||
@InjectDependency
|
||||
private RoomTaskScheduler roomTaskScheduler;
|
||||
|
||||
@Override
|
||||
public void handle(RoomChangeEvent event) {
|
||||
RoomCords playerCords = gameState.getPlayer().getPlayerCords();
|
||||
@@ -49,6 +53,7 @@ public class RoomChangeEventHandler extends AbstractEventHandler<RoomChangeEvent
|
||||
}
|
||||
|
||||
gameState.setCurrentRoom(newRoom);
|
||||
roomTaskScheduler.setupNewSchedulers(newRoom);
|
||||
eventManager.emitEvent(new FullRoomDraw());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cz.jzitnik.game;
|
||||
|
||||
import cz.jzitnik.game.objects.GameObject;
|
||||
import cz.jzitnik.game.objects.Mob;
|
||||
import cz.jzitnik.ui.pixels.Empty;
|
||||
import cz.jzitnik.ui.pixels.Pixel;
|
||||
import lombok.Getter;
|
||||
@@ -17,6 +18,7 @@ public class GameRoom {
|
||||
private final Pixel[][] overrideBuffer;
|
||||
private final ResourceManager.Resource texture;
|
||||
private final List<GameObject> objects = new ArrayList<>();
|
||||
private final List<Mob> mobs = new ArrayList<>();
|
||||
private final List<GameRoomPart> colliders = new ArrayList<>();
|
||||
|
||||
public GameRoom(ResourceManager.Resource texture) {
|
||||
@@ -41,6 +43,10 @@ public class GameRoom {
|
||||
objects.add(gameObject);
|
||||
}
|
||||
|
||||
public void addMob(Mob mob) {
|
||||
mobs.add(mob);
|
||||
}
|
||||
|
||||
public void addCollider(GameRoomPart collider) {
|
||||
colliders.add(collider);
|
||||
}
|
||||
|
||||
11
src/main/java/cz/jzitnik/game/objects/Mob.java
Normal file
11
src/main/java/cz/jzitnik/game/objects/Mob.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package cz.jzitnik.game.objects;
|
||||
|
||||
import cz.jzitnik.utils.roomtasks.RoomTask;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public abstract class Mob {
|
||||
private final RoomTask task;
|
||||
}
|
||||
@@ -6,9 +6,17 @@ import cz.jzitnik.game.ResourceManager;
|
||||
import cz.jzitnik.game.items.GameItem;
|
||||
import cz.jzitnik.game.items.WoodenSword;
|
||||
import cz.jzitnik.game.objects.Chest;
|
||||
import cz.jzitnik.game.objects.Mob;
|
||||
import cz.jzitnik.game.utils.RoomCords;
|
||||
import cz.jzitnik.states.SoundState;
|
||||
import cz.jzitnik.utils.DependencyManager;
|
||||
import cz.jzitnik.utils.StateManager;
|
||||
import cz.jzitnik.utils.roomtasks.RoomTask;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Slf4j
|
||||
public class MainRoom extends GameRoom {
|
||||
public MainRoom(DependencyManager dependencyManager, ResourceManager resourceManager) {
|
||||
super(ResourceManager.Resource.ROOM1);
|
||||
@@ -23,5 +31,14 @@ public class MainRoom extends GameRoom {
|
||||
new RoomCords(135, 15)
|
||||
));
|
||||
addObject(chest);
|
||||
|
||||
SoundState soundState = dependencyManager.getDependencyOrThrow(StateManager.class).getOrThrow(SoundState.class);
|
||||
Mob testMob = new Mob(new RoomTask(
|
||||
() -> log.debug("Sound: {}", soundState.getSoundVolume()),
|
||||
1,
|
||||
TimeUnit.SECONDS
|
||||
)) {};
|
||||
|
||||
addMob(testMob);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ public abstract class VideoPlayScreen extends Screen {
|
||||
} finally {
|
||||
if (tempVideo != null && tempVideo.exists()) {
|
||||
if (!tempVideo.delete()) {
|
||||
System.err.println("Warning: failed to delete temp video file " + tempVideo.getAbsolutePath());
|
||||
log.error("Warning: failed to delete temp video file {}", tempVideo.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@ import cz.jzitnik.annotations.ThreadRegistry;
|
||||
import cz.jzitnik.annotations.injectors.InjectState;
|
||||
import cz.jzitnik.states.SoundState;
|
||||
import cz.jzitnik.utils.ShutdownableThread;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.sound.sampled.*;
|
||||
|
||||
@Slf4j
|
||||
@ThreadRegistry
|
||||
public class MicrophoneThread extends ShutdownableThread {
|
||||
@InjectState
|
||||
@@ -20,7 +22,7 @@ public class MicrophoneThread extends ShutdownableThread {
|
||||
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
|
||||
|
||||
if (!AudioSystem.isLineSupported(info)) {
|
||||
System.err.println("Line not supported: " + info);
|
||||
log.error("Line not supported: {}", info);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -42,7 +44,7 @@ public class MicrophoneThread extends ShutdownableThread {
|
||||
}
|
||||
}
|
||||
} catch (LineUnavailableException e) {
|
||||
System.err.println("Microphone line unavailable: " + e.getMessage());
|
||||
log.error("Microphone line unavailable: {}", e.getMessage());
|
||||
} finally {
|
||||
if (line != null) {
|
||||
line.stop();
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.google.common.collect.ClassToInstanceMap;
|
||||
import com.google.common.collect.MutableClassToInstanceMap;
|
||||
import cz.jzitnik.annotations.Config;
|
||||
import cz.jzitnik.annotations.Dependency;
|
||||
import cz.jzitnik.annotations.PostInit;
|
||||
import cz.jzitnik.annotations.injectors.InjectConfig;
|
||||
import cz.jzitnik.annotations.injectors.InjectDependency;
|
||||
import cz.jzitnik.annotations.injectors.InjectState;
|
||||
@@ -16,6 +17,7 @@ import org.reflections.Reflections;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
@Slf4j
|
||||
@@ -153,5 +155,24 @@ public class DependencyManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Method method : instance.getClass().getDeclaredMethods()) {
|
||||
if (!method.isAnnotationPresent(PostInit.class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method.getParameterCount() != 0) {
|
||||
throw new IllegalStateException("@PostInit method must have no parameters: " + method);
|
||||
}
|
||||
|
||||
try {
|
||||
method.setAccessible(true);
|
||||
method.invoke(instance);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Failed to invoke @PostInit method: " + method, e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,11 @@ import cz.jzitnik.annotations.Dependency;
|
||||
import cz.jzitnik.annotations.EventHandler;
|
||||
import cz.jzitnik.annotations.injectors.InjectConfig;
|
||||
import cz.jzitnik.annotations.injectors.InjectState;
|
||||
import cz.jzitnik.config.EventThreadPoolConfig;
|
||||
import cz.jzitnik.config.ThreadPoolConfig;
|
||||
import cz.jzitnik.states.RunningState;
|
||||
import cz.jzitnik.utils.DependencyManager;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.reflections.Reflections;
|
||||
import org.w3c.dom.events.EventException;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
@@ -21,7 +20,7 @@ public class EventManager extends Thread {
|
||||
@InjectState
|
||||
private RunningState runningState;
|
||||
@InjectConfig
|
||||
private EventThreadPoolConfig eventThreadPoolConfig;
|
||||
private ThreadPoolConfig threadPoolConfig;
|
||||
|
||||
private ExecutorService eventExecutor;
|
||||
private final HashMap<Class<? extends Event>, AbstractEventHandler<? extends Event>> handlers = new HashMap<>();
|
||||
@@ -62,7 +61,7 @@ public class EventManager extends Thread {
|
||||
dependencyManager.inject(instance);
|
||||
}
|
||||
|
||||
eventExecutor = Executors.newFixedThreadPool(eventThreadPoolConfig.getThreadCount());
|
||||
eventExecutor = Executors.newFixedThreadPool(threadPoolConfig.getEventThreadCount());
|
||||
while (runningState.isRunning()) {
|
||||
try {
|
||||
Event event = eventQueue.take();
|
||||
|
||||
6
src/main/java/cz/jzitnik/utils/roomtasks/RoomTask.java
Normal file
6
src/main/java/cz/jzitnik/utils/roomtasks/RoomTask.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package cz.jzitnik.utils.roomtasks;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public record RoomTask(Runnable task, long rate, TimeUnit rateUnit) {
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package cz.jzitnik.utils.roomtasks;
|
||||
|
||||
import cz.jzitnik.annotations.Dependency;
|
||||
import cz.jzitnik.annotations.PostInit;
|
||||
import cz.jzitnik.annotations.injectors.InjectConfig;
|
||||
import cz.jzitnik.config.ThreadPoolConfig;
|
||||
import cz.jzitnik.game.GameRoom;
|
||||
import cz.jzitnik.game.objects.Mob;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Slf4j
|
||||
@Dependency
|
||||
public class RoomTaskScheduler {
|
||||
ScheduledExecutorService scheduler;
|
||||
@InjectConfig
|
||||
private ThreadPoolConfig threadPoolConfig;
|
||||
|
||||
private boolean firstRun = true;
|
||||
|
||||
@PostInit
|
||||
public void initExecutor() {
|
||||
scheduler = Executors.newScheduledThreadPool(threadPoolConfig.getTaskThreadCount());
|
||||
}
|
||||
|
||||
private void shutdownAll() {
|
||||
scheduler.shutdown();
|
||||
|
||||
try {
|
||||
if (!scheduler.awaitTermination(1, TimeUnit.SECONDS)) {
|
||||
scheduler.shutdownNow();
|
||||
if (!scheduler.awaitTermination(1, TimeUnit.SECONDS)) {
|
||||
log.error("Pool did not terminate");
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
scheduler.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public void finalShutdown() {
|
||||
shutdownAll();
|
||||
}
|
||||
|
||||
public void setupNewSchedulers(GameRoom currentRoom) {
|
||||
if (!firstRun) {
|
||||
shutdownAll();
|
||||
initExecutor();
|
||||
}
|
||||
|
||||
for (Mob mob : currentRoom.getMobs()) {
|
||||
RoomTask task = mob.getTask();
|
||||
scheduler.scheduleAtFixedRate(task.task(), 0, task.rate(), task.rateUnit());
|
||||
}
|
||||
|
||||
firstRun = false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user