diff --git a/src/main/java/cz/jzitnik/Main.java b/src/main/java/cz/jzitnik/Main.java index 2aa20ba..1131fba 100644 --- a/src/main/java/cz/jzitnik/Main.java +++ b/src/main/java/cz/jzitnik/Main.java @@ -3,9 +3,7 @@ package cz.jzitnik; import cz.jzitnik.game.GameSaver; import cz.jzitnik.game.logic.CustomLogicProvider; import cz.jzitnik.game.mobs.EntityLogicProvider; -import cz.jzitnik.game.threads.HealthRegenerationThread; -import cz.jzitnik.game.threads.HungerDrainThread; -import cz.jzitnik.game.threads.InputHandlerThread; +import cz.jzitnik.game.threads.ThreadProvider; import cz.jzitnik.game.ui.*; import cz.jzitnik.game.SpriteLoader; import cz.jzitnik.tui.ScreenRenderer; @@ -32,16 +30,11 @@ public class Main { final boolean[] isRunning = { true }; - Thread inputHandlerThread = new InputHandlerThread(game, terminal, screenRenderer, isRunning); - Thread healingThread = new HealthRegenerationThread(game.getPlayer()); - Thread hungerDrainThread = new HungerDrainThread(game.getPlayer()); EntityLogicProvider entityLogicProvider = new EntityLogicProvider(); CustomLogicProvider customLogicProvider = new CustomLogicProvider(); - // Start all threads - healingThread.start(); - hungerDrainThread.start(); - inputHandlerThread.start(); + ThreadProvider threadProvider = new ThreadProvider(game, screenRenderer, terminal, isRunning); + threadProvider.start(); while (isRunning[0]) { try { diff --git a/src/main/java/cz/jzitnik/game/annotations/ThreadAnnotation.java b/src/main/java/cz/jzitnik/game/annotations/ThreadAnnotation.java new file mode 100644 index 0000000..9a2a6fc --- /dev/null +++ b/src/main/java/cz/jzitnik/game/annotations/ThreadAnnotation.java @@ -0,0 +1,11 @@ +package cz.jzitnik.game.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.TYPE) +public @interface ThreadAnnotation { +} diff --git a/src/main/java/cz/jzitnik/game/mobs/EntitySpawnProvider.java b/src/main/java/cz/jzitnik/game/mobs/EntitySpawnProvider.java index 481f278..f0b55a6 100644 --- a/src/main/java/cz/jzitnik/game/mobs/EntitySpawnProvider.java +++ b/src/main/java/cz/jzitnik/game/mobs/EntitySpawnProvider.java @@ -6,9 +6,6 @@ import java.util.Set; import cz.jzitnik.game.Game; import cz.jzitnik.game.annotations.EntitySpawn; -import cz.jzitnik.game.entities.Block; -import lombok.AllArgsConstructor; -import lombok.Getter; import org.jline.terminal.Terminal; import org.reflections.Reflections; @@ -21,7 +18,6 @@ public class EntitySpawnProvider { int playerY = playerLocation[1]; for (EntitySpawnInterface entitySpawnInterface : spawnList) { - entitySpawnInterface.spawn(playerX, playerY, game, terminal); } } diff --git a/src/main/java/cz/jzitnik/game/threads/ThreadProvider.java b/src/main/java/cz/jzitnik/game/threads/ThreadProvider.java new file mode 100644 index 0000000..08351a8 --- /dev/null +++ b/src/main/java/cz/jzitnik/game/threads/ThreadProvider.java @@ -0,0 +1,74 @@ +package cz.jzitnik.game.threads; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import cz.jzitnik.game.Game; +import cz.jzitnik.game.annotations.ThreadAnnotation; +import cz.jzitnik.game.entities.Player; +import cz.jzitnik.tui.ScreenRenderer; + +import org.jline.terminal.Terminal; +import org.reflections.Reflections; + +public class ThreadProvider { + private final Game game; + private final ScreenRenderer screenRenderer; + private final Terminal terminal; + private final boolean[] isRunning; + private final List list = new ArrayList<>(); + + public void start() { + for (Thread thread : list) { + thread.start(); + } + } + + public ThreadProvider(Game game, ScreenRenderer screenRenderer, Terminal terminal, boolean[] isRunning) { + this.game = game; + this.screenRenderer = screenRenderer; + this.terminal = terminal; + this.isRunning = isRunning; + registerHandlers(); + } + + private void registerHandlers() { + Reflections reflections = new Reflections("cz.jzitnik.game.threads"); + Set> handlerClasses = reflections.getTypesAnnotatedWith(ThreadAnnotation.class); + + for (Class clazz : handlerClasses) { + if (Thread.class.isAssignableFrom(clazz)) { + try { + for (var constructor : clazz.getDeclaredConstructors()) { + var paramTypes = constructor.getParameterTypes(); + var params = new Object[paramTypes.length]; + boolean suitable = true; + + for (int i = 0; i < paramTypes.length; i++) { + Class type = paramTypes[i]; + if (type == Game.class) params[i] = game; + else if (type == ScreenRenderer.class) params[i] = screenRenderer; + else if (type == Terminal.class) params[i] = terminal; + else if (type == boolean[].class) params[i] = isRunning; + else if (type == Player.class) params[i] = game.getPlayer(); + else { + suitable = false; + break; + } + } + + if (suitable) { + constructor.setAccessible(true); + Thread instance = (Thread) constructor.newInstance(params); + list.add(instance); + break; // Found a matching constructor, go to next class + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } +} diff --git a/src/main/java/cz/jzitnik/game/threads/HealthRegenerationThread.java b/src/main/java/cz/jzitnik/game/threads/list/HealthRegenerationThread.java similarity index 80% rename from src/main/java/cz/jzitnik/game/threads/HealthRegenerationThread.java rename to src/main/java/cz/jzitnik/game/threads/list/HealthRegenerationThread.java index 451b523..d7f7bc5 100644 --- a/src/main/java/cz/jzitnik/game/threads/HealthRegenerationThread.java +++ b/src/main/java/cz/jzitnik/game/threads/list/HealthRegenerationThread.java @@ -1,9 +1,11 @@ -package cz.jzitnik.game.threads; +package cz.jzitnik.game.threads.list; +import cz.jzitnik.game.annotations.ThreadAnnotation; import cz.jzitnik.game.entities.Player; import lombok.AllArgsConstructor; @AllArgsConstructor +@ThreadAnnotation public class HealthRegenerationThread extends Thread { private final Player player; diff --git a/src/main/java/cz/jzitnik/game/threads/HungerDrainThread.java b/src/main/java/cz/jzitnik/game/threads/list/HungerDrainThread.java similarity index 79% rename from src/main/java/cz/jzitnik/game/threads/HungerDrainThread.java rename to src/main/java/cz/jzitnik/game/threads/list/HungerDrainThread.java index 397f44a..28deca4 100644 --- a/src/main/java/cz/jzitnik/game/threads/HungerDrainThread.java +++ b/src/main/java/cz/jzitnik/game/threads/list/HungerDrainThread.java @@ -1,9 +1,11 @@ -package cz.jzitnik.game.threads; +package cz.jzitnik.game.threads.list; +import cz.jzitnik.game.annotations.ThreadAnnotation; import cz.jzitnik.game.entities.Player; import lombok.AllArgsConstructor; @AllArgsConstructor +@ThreadAnnotation public class HungerDrainThread extends Thread { private final Player player; diff --git a/src/main/java/cz/jzitnik/game/threads/InputHandlerThread.java b/src/main/java/cz/jzitnik/game/threads/list/InputHandlerThread.java similarity index 95% rename from src/main/java/cz/jzitnik/game/threads/InputHandlerThread.java rename to src/main/java/cz/jzitnik/game/threads/list/InputHandlerThread.java index 6647246..0e92837 100644 --- a/src/main/java/cz/jzitnik/game/threads/InputHandlerThread.java +++ b/src/main/java/cz/jzitnik/game/threads/list/InputHandlerThread.java @@ -1,4 +1,4 @@ -package cz.jzitnik.game.threads; +package cz.jzitnik.game.threads.list; import cz.jzitnik.game.Game; import cz.jzitnik.game.blocks.Chest; @@ -9,8 +9,11 @@ import cz.jzitnik.tui.ScreenRenderer; import org.jline.terminal.MouseEvent; import org.jline.terminal.Terminal; import java.io.IOException; +import java.nio.BufferUnderflowException; import java.util.Optional; +import cz.jzitnik.game.annotations.ThreadAnnotation; +@ThreadAnnotation public class InputHandlerThread extends Thread { private final Game game; private final Terminal terminal; @@ -91,7 +94,7 @@ public class InputHandlerThread extends Thread { } } } - } catch (IOException e) { + } catch (IOException | BufferUnderflowException e) { e.printStackTrace(); } } diff --git a/src/main/java/cz/jzitnik/game/threads/list/NoHungerThread.java b/src/main/java/cz/jzitnik/game/threads/list/NoHungerThread.java new file mode 100644 index 0000000..1e1028c --- /dev/null +++ b/src/main/java/cz/jzitnik/game/threads/list/NoHungerThread.java @@ -0,0 +1,25 @@ +package cz.jzitnik.game.threads.list; + +import cz.jzitnik.game.annotations.ThreadAnnotation; +import cz.jzitnik.game.entities.Player; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +@ThreadAnnotation +public class NoHungerThread extends Thread { + private final Player player; + + @Override + public void run() { + while (true) { + try { + Thread.sleep(6000); + if (player.getHunger() == 0) { + player.setHealth(player.getHunger() - 1); + } + } catch (InterruptedException e) { + break; + } + } + } +}