diff --git a/build.gradle b/build.gradle index f66a205..da868fa 100644 --- a/build.gradle +++ b/build.gradle @@ -8,3 +8,9 @@ version '0.0.10' repositories { mavenCentral() } + +dependencies { + implementation 'javax.inject:javax.inject:1' + implementation 'com.google.dagger:dagger:2.44.2' + annotationProcessor 'com.google.dagger:dagger-compiler:2.44.2' +} diff --git a/src/main/java/com/vamk/tbg/Bootstrap.java b/src/main/java/com/vamk/tbg/Bootstrap.java new file mode 100644 index 0000000..4d24102 --- /dev/null +++ b/src/main/java/com/vamk/tbg/Bootstrap.java @@ -0,0 +1,93 @@ +package com.vamk.tbg; + +import com.vamk.tbg.command.CommandManager; +import com.vamk.tbg.config.Config; +import com.vamk.tbg.config.Keys; +import com.vamk.tbg.game.Game; +import com.vamk.tbg.game.GameState; +import com.vamk.tbg.ui.GameWindow; +import com.vamk.tbg.util.LogUtil; +import com.vamk.tbg.util.SerialUtil; + +import javax.inject.Inject; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.CompletableFuture; +import java.util.logging.Logger; + +public class Bootstrap { + private static final Logger LOGGER = LogUtil.getLogger(Bootstrap.class); + private final Config config; + private final Game game; + private final CommandManager cmdManager; + private final GameWindow window; + + @Inject + public Bootstrap(Config config, Game game, CommandManager cmdManager, GameWindow.Factory windowFactory) { + this.config = config; + this.game = game; + this.cmdManager = cmdManager; + this.window = windowFactory.create(this::handleForceShutdown); + } + + /** + * Tries to load the configuration. If that fails, exit. + * After that, register the command listener (if dev mode + * is enabled), then launch the game. Once the game loop + * finishes, dismantle the window and the command manager + * and exit. + */ + public void launch() { + try { + this.config.load(); + } catch (Exception ex) { + LOGGER.severe("Failed to load configuration, exiting"); + ex.printStackTrace(); + System.exit(-1); + } + + // Setup command listener on a separate thread + if (this.config.get(Keys.DEV_MODE)) CompletableFuture.runAsync(this.cmdManager::listen); + + attemptRestore(); + this.game.launch(); + this.window.dispose(); + this.cmdManager.stop(); + } + + /** + * Tries to read a previous game state from the configured + * file. If the file doesn't exist, return. Otherwise, + * load the state and import it into {@link this#game}. + */ + private void attemptRestore() { + File file = new File(this.config.get(Keys.BACKUP_LOCATION)); + if (!file.exists()) return; + + try { + GameState state = SerialUtil.readObject(GameState.class, file); + this.game.importState(state); + file.delete(); + } catch (ClassNotFoundException | IOException ex) { + LOGGER.severe("Failed to read game state from file"); + ex.printStackTrace(); + } + } + + /** + * This method will be called if the opened JFrame is closed. + * The current game state will be written to the configured + * file. If the file already exists, the contents of it + * will be replaced. + */ + private void handleForceShutdown() { + LOGGER.info("Force shutdown initiated, writing game state to file"); + GameState state = this.game.exportState(); + try { + SerialUtil.writeObject(state, new File(this.config.get(Keys.BACKUP_LOCATION))); + } catch (IOException ex) { + LOGGER.severe("Failed to write game state to file"); + ex.printStackTrace(); + } + } +} diff --git a/src/main/java/com/vamk/tbg/Main.java b/src/main/java/com/vamk/tbg/Main.java index f60590d..c64fca3 100644 --- a/src/main/java/com/vamk/tbg/Main.java +++ b/src/main/java/com/vamk/tbg/Main.java @@ -1,100 +1,12 @@ package com.vamk.tbg; -import com.vamk.tbg.command.CommandManager; -import com.vamk.tbg.config.Config; -import com.vamk.tbg.config.Keys; -import com.vamk.tbg.game.Game; -import com.vamk.tbg.game.GameState; -import com.vamk.tbg.signal.SignalDispatcher; -import com.vamk.tbg.ui.GameWindow; -import com.vamk.tbg.util.LogUtil; -import com.vamk.tbg.util.SerialUtil; - -import java.io.File; -import java.io.IOException; -import java.util.concurrent.CompletableFuture; -import java.util.logging.Logger; +import com.vamk.tbg.di.DaggerGameComponent; +import com.vamk.tbg.di.GameComponent; public class Main { public static void main(String[] args) { - new Bootstrap().launch(); - } - - private static final class Bootstrap { - private static final Logger LOGGER = LogUtil.getLogger(Bootstrap.class); - private final Config config; - private final Game game; - private final GameWindow window; - private final CommandManager cmdManager; - - private Bootstrap() { - SignalDispatcher dispatcher = new SignalDispatcher(); - this.config = new Config(); - this.game = new Game(dispatcher, this.config); - this.window = new GameWindow(dispatcher, this.config, this::handleForceShutdown); - this.cmdManager = new CommandManager(this.game); - } - - /** - * Tries to load the configuration. If that fails, exit. - * After that, register the command listener (if dev mode - * is enabled), then launch the game. Once the game loop - * finishes, dismantle the window and the command manager - * and exit. - */ - private void launch() { - try { - this.config.load(); - } catch (Exception ex) { - LOGGER.severe("Failed to load configuration, exiting"); - ex.printStackTrace(); - System.exit(-1); - } - - // Setup command listener on a separate thread - if (this.config.get(Keys.DEV_MODE)) CompletableFuture.runAsync(this.cmdManager::listen); - - attemptRestore(); - this.game.launch(); - this.window.dispose(); - this.cmdManager.stop(); - } - - /** - * Tries to read a previous game state from the configured - * file. If the file doesn't exist, return. Otherwise, - * load the state and import it into {@link this#game}. - */ - private void attemptRestore() { - File file = new File(this.config.get(Keys.BACKUP_LOCATION)); - if (!file.exists()) return; - - try { - GameState state = SerialUtil.readObject(GameState.class, file); - this.game.importState(state); - file.delete(); - } catch (ClassNotFoundException | IOException ex) { - LOGGER.severe("Failed to read game state from file"); - ex.printStackTrace(); - } - } - - /** - * This method will be called if the opened JFrame is closed. - * The current game state will be written to the configured - * file. If the file already exists, the contents of it - * will be replaced. - */ - private void handleForceShutdown() { - LOGGER.info("Force shutdown initiated, writing game state to file"); - GameState state = this.game.exportState(); - try { - SerialUtil.writeObject(state, new File(this.config.get(Keys.BACKUP_LOCATION))); - } catch (IOException ex) { - LOGGER.severe("Failed to write game state to file"); - ex.printStackTrace(); - } - } + GameComponent component = DaggerGameComponent.create(); + component.bootstrap().launch(); } } diff --git a/src/main/java/com/vamk/tbg/combat/BuffMove.java b/src/main/java/com/vamk/tbg/combat/BuffMove.java index cad2643..dd3ea59 100644 --- a/src/main/java/com/vamk/tbg/combat/BuffMove.java +++ b/src/main/java/com/vamk/tbg/combat/BuffMove.java @@ -7,6 +7,7 @@ import com.vamk.tbg.game.MoveContext; import com.vamk.tbg.util.LogUtil; +import javax.inject.Inject; import java.util.EnumSet; import java.util.logging.Logger; @@ -20,6 +21,7 @@ public class BuffMove extends AbstractBuffMove { StatusEffect.REGENERATION, StatusEffect.LIFESTEAL, StatusEffect.CAFFEINATED ); + @Inject public BuffMove(Config config) { super("BUFF", false, config, Keys.BUFF_CHANCES, POTENTIAL_EFFECTS); } diff --git a/src/main/java/com/vamk/tbg/combat/CureMove.java b/src/main/java/com/vamk/tbg/combat/CureMove.java index 7dec265..2ade51f 100644 --- a/src/main/java/com/vamk/tbg/combat/CureMove.java +++ b/src/main/java/com/vamk/tbg/combat/CureMove.java @@ -5,11 +5,13 @@ import com.vamk.tbg.game.MoveContext; import com.vamk.tbg.util.LogUtil; +import javax.inject.Inject; import java.util.logging.Logger; public class CureMove extends AbstractMove { private static final Logger LOGGER = LogUtil.getLogger(CureMove.class); + @Inject public CureMove() { super("CURE", false); } diff --git a/src/main/java/com/vamk/tbg/combat/DamageMove.java b/src/main/java/com/vamk/tbg/combat/DamageMove.java index a2b81d0..6718073 100644 --- a/src/main/java/com/vamk/tbg/combat/DamageMove.java +++ b/src/main/java/com/vamk/tbg/combat/DamageMove.java @@ -8,6 +8,7 @@ import com.vamk.tbg.util.LogUtil; import com.vamk.tbg.util.RandomUtil; +import javax.inject.Inject; import java.util.Map; import java.util.logging.Logger; @@ -20,6 +21,7 @@ public class DamageMove extends AbstractMove { private static final Logger LOGGER = LogUtil.getLogger(DamageMove.class); private final Config config; + @Inject public DamageMove(Config config) { super("DAMAGE", true); this.config = config; diff --git a/src/main/java/com/vamk/tbg/combat/DebuffMove.java b/src/main/java/com/vamk/tbg/combat/DebuffMove.java index d9f7dd5..4028b88 100644 --- a/src/main/java/com/vamk/tbg/combat/DebuffMove.java +++ b/src/main/java/com/vamk/tbg/combat/DebuffMove.java @@ -7,6 +7,7 @@ import com.vamk.tbg.game.MoveContext; import com.vamk.tbg.util.LogUtil; +import javax.inject.Inject; import java.util.EnumSet; import java.util.logging.Logger; @@ -21,6 +22,7 @@ public class DebuffMove extends AbstractBuffMove { StatusEffect.BLEEDING, StatusEffect.CONFUSED, StatusEffect.FROZEN ); + @Inject public DebuffMove(Config config) { super("DEBUFF", true, config, Keys.DEBUFF_CHANCES, POTENTIAL_EFFECTS); } diff --git a/src/main/java/com/vamk/tbg/combat/HealAllMove.java b/src/main/java/com/vamk/tbg/combat/HealAllMove.java index 814cd63..2558fd5 100644 --- a/src/main/java/com/vamk/tbg/combat/HealAllMove.java +++ b/src/main/java/com/vamk/tbg/combat/HealAllMove.java @@ -6,6 +6,7 @@ import com.vamk.tbg.game.MoveContext; import com.vamk.tbg.util.LogUtil; +import javax.inject.Inject; import java.util.Map; import java.util.logging.Logger; @@ -18,6 +19,7 @@ public class HealAllMove extends AbstractMove { private static final Logger LOGGER = LogUtil.getLogger(HealAllMove.class); private final Config config; + @Inject public HealAllMove(Config config) { super("HEAL_ALL", false); this.config = config; diff --git a/src/main/java/com/vamk/tbg/combat/HealMove.java b/src/main/java/com/vamk/tbg/combat/HealMove.java index 5103367..5c1d2a3 100644 --- a/src/main/java/com/vamk/tbg/combat/HealMove.java +++ b/src/main/java/com/vamk/tbg/combat/HealMove.java @@ -7,6 +7,7 @@ import com.vamk.tbg.util.LogUtil; import com.vamk.tbg.util.RandomUtil; +import javax.inject.Inject; import java.util.Map; import java.util.logging.Logger; @@ -18,6 +19,7 @@ public class HealMove extends AbstractMove { private static final Logger LOGGER = LogUtil.getLogger(HealMove.class); private final Config config; + @Inject public HealMove(Config config) { super("HEAL", false); this.config = config; diff --git a/src/main/java/com/vamk/tbg/combat/SplashDamageMove.java b/src/main/java/com/vamk/tbg/combat/SplashDamageMove.java index c348b65..2735e65 100644 --- a/src/main/java/com/vamk/tbg/combat/SplashDamageMove.java +++ b/src/main/java/com/vamk/tbg/combat/SplashDamageMove.java @@ -8,6 +8,7 @@ import com.vamk.tbg.util.LogUtil; import com.vamk.tbg.util.RandomUtil; +import javax.inject.Inject; import java.util.Map; import java.util.logging.Logger; @@ -20,6 +21,7 @@ public class SplashDamageMove extends AbstractMove { private static final Logger LOGGER = LogUtil.getLogger(SplashDamageMove.class); private final Config config; + @Inject public SplashDamageMove(Config config) { super("SPLASH_DAMAGE", true); this.config = config; diff --git a/src/main/java/com/vamk/tbg/command/CommandManager.java b/src/main/java/com/vamk/tbg/command/CommandManager.java index 193e244..af1ccd3 100644 --- a/src/main/java/com/vamk/tbg/command/CommandManager.java +++ b/src/main/java/com/vamk/tbg/command/CommandManager.java @@ -1,27 +1,19 @@ package com.vamk.tbg.command; -import com.vamk.tbg.command.impl.DamageCommand; -import com.vamk.tbg.command.impl.HealCommand; -import com.vamk.tbg.command.impl.KillCommand; -import com.vamk.tbg.command.impl.ListCommand; -import com.vamk.tbg.command.impl.ListEffectsCommand; -import com.vamk.tbg.command.impl.ListMovesCommand; -import com.vamk.tbg.command.impl.RemoveEffectCommand; -import com.vamk.tbg.command.impl.SetEffectCommand; import com.vamk.tbg.command.mapper.ArgumentMapper; -import com.vamk.tbg.command.mapper.EntityMapper; -import com.vamk.tbg.command.mapper.IntMapper; -import com.vamk.tbg.command.mapper.StatusEffectMapper; -import com.vamk.tbg.game.Game; +import com.vamk.tbg.di.qualifier.CommandSet; +import com.vamk.tbg.di.qualifier.MapperSet; import com.vamk.tbg.util.CollectionUtil; import com.vamk.tbg.util.LogFormatter; import com.vamk.tbg.util.LogUtil; +import javax.inject.Inject; import java.util.Arrays; import java.util.LinkedList; import java.util.Map; import java.util.Queue; import java.util.Scanner; +import java.util.Set; import java.util.StringJoiner; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -54,24 +46,11 @@ public class CommandManager { /* This state will be changed by this#listen and this#stop */ private boolean listening; - public CommandManager(Game game) { - this.knownMappers = CollectionUtil.mapOf( - ArgumentMapper::type, - new EntityMapper(game), - new IntMapper(), - new StatusEffectMapper() - ); - this.knownCommands = CollectionUtil.mapOf( - Command::getName, - new DamageCommand(), - new HealCommand(), - new KillCommand(), - new ListCommand(game), - new ListEffectsCommand(), - new ListMovesCommand(), - new RemoveEffectCommand(), - new SetEffectCommand() - ); + @Inject + public CommandManager(@MapperSet Set> mappers, + @CommandSet Set commands) { + this.knownMappers = CollectionUtil.mapOf(ArgumentMapper::type, mappers); + this.knownCommands = CollectionUtil.mapOf(Command::getName, commands); } /** diff --git a/src/main/java/com/vamk/tbg/command/impl/DamageCommand.java b/src/main/java/com/vamk/tbg/command/impl/DamageCommand.java index 9dca8cb..e4c902f 100644 --- a/src/main/java/com/vamk/tbg/command/impl/DamageCommand.java +++ b/src/main/java/com/vamk/tbg/command/impl/DamageCommand.java @@ -6,8 +6,11 @@ import com.vamk.tbg.command.CommandException; import com.vamk.tbg.game.Entity; +import javax.inject.Inject; + public class DamageCommand extends Command { + @Inject public DamageCommand() { super( "dmg", diff --git a/src/main/java/com/vamk/tbg/command/impl/HealCommand.java b/src/main/java/com/vamk/tbg/command/impl/HealCommand.java index 693f005..6298522 100644 --- a/src/main/java/com/vamk/tbg/command/impl/HealCommand.java +++ b/src/main/java/com/vamk/tbg/command/impl/HealCommand.java @@ -6,12 +6,15 @@ import com.vamk.tbg.command.CommandException; import com.vamk.tbg.game.Entity; +import javax.inject.Inject; + /** * Heals the specified entity by the specified amount. If * no amount was given, the entity gets fully healed. */ public class HealCommand extends Command { + @Inject public HealCommand() { super( "heal", diff --git a/src/main/java/com/vamk/tbg/command/impl/KillCommand.java b/src/main/java/com/vamk/tbg/command/impl/KillCommand.java index e6bef4e..74279a3 100644 --- a/src/main/java/com/vamk/tbg/command/impl/KillCommand.java +++ b/src/main/java/com/vamk/tbg/command/impl/KillCommand.java @@ -6,8 +6,11 @@ import com.vamk.tbg.command.CommandException; import com.vamk.tbg.game.Entity; +import javax.inject.Inject; + public class KillCommand extends Command { + @Inject public KillCommand() { super( "kill", diff --git a/src/main/java/com/vamk/tbg/command/impl/ListCommand.java b/src/main/java/com/vamk/tbg/command/impl/ListCommand.java index 8c2db8b..0580854 100644 --- a/src/main/java/com/vamk/tbg/command/impl/ListCommand.java +++ b/src/main/java/com/vamk/tbg/command/impl/ListCommand.java @@ -5,11 +5,13 @@ import com.vamk.tbg.game.Entity; import com.vamk.tbg.game.Game; +import javax.inject.Inject; import java.util.stream.Collectors; public class ListCommand extends Command { private final Game game; + @Inject public ListCommand(Game game) { super( "list", diff --git a/src/main/java/com/vamk/tbg/command/impl/ListEffectsCommand.java b/src/main/java/com/vamk/tbg/command/impl/ListEffectsCommand.java index 1519565..ea43ed2 100644 --- a/src/main/java/com/vamk/tbg/command/impl/ListEffectsCommand.java +++ b/src/main/java/com/vamk/tbg/command/impl/ListEffectsCommand.java @@ -7,12 +7,14 @@ import com.vamk.tbg.effect.StatusEffect; import com.vamk.tbg.game.Entity; +import javax.inject.Inject; import java.util.Arrays; import java.util.Set; import java.util.stream.Collectors; public class ListEffectsCommand extends Command { + @Inject public ListEffectsCommand() { super( "ls-eff", diff --git a/src/main/java/com/vamk/tbg/command/impl/ListMovesCommand.java b/src/main/java/com/vamk/tbg/command/impl/ListMovesCommand.java index b1fe96e..624ff59 100644 --- a/src/main/java/com/vamk/tbg/command/impl/ListMovesCommand.java +++ b/src/main/java/com/vamk/tbg/command/impl/ListMovesCommand.java @@ -7,10 +7,12 @@ import com.vamk.tbg.command.CommandException; import com.vamk.tbg.game.Entity; +import javax.inject.Inject; import java.util.stream.Collectors; public class ListMovesCommand extends Command { + @Inject public ListMovesCommand() { super( "ls-mov", diff --git a/src/main/java/com/vamk/tbg/command/impl/RemoveEffectCommand.java b/src/main/java/com/vamk/tbg/command/impl/RemoveEffectCommand.java index 8c1d928..7553b0e 100644 --- a/src/main/java/com/vamk/tbg/command/impl/RemoveEffectCommand.java +++ b/src/main/java/com/vamk/tbg/command/impl/RemoveEffectCommand.java @@ -7,8 +7,11 @@ import com.vamk.tbg.effect.StatusEffect; import com.vamk.tbg.game.Entity; +import javax.inject.Inject; + public class RemoveEffectCommand extends Command { + @Inject public RemoveEffectCommand() { super( "rem-eff", diff --git a/src/main/java/com/vamk/tbg/command/impl/SetEffectCommand.java b/src/main/java/com/vamk/tbg/command/impl/SetEffectCommand.java index 5c69e07..53fce02 100644 --- a/src/main/java/com/vamk/tbg/command/impl/SetEffectCommand.java +++ b/src/main/java/com/vamk/tbg/command/impl/SetEffectCommand.java @@ -7,8 +7,11 @@ import com.vamk.tbg.effect.StatusEffect; import com.vamk.tbg.game.Entity; +import javax.inject.Inject; + public class SetEffectCommand extends Command { + @Inject public SetEffectCommand() { super( "set-eff", diff --git a/src/main/java/com/vamk/tbg/command/mapper/EntityMapper.java b/src/main/java/com/vamk/tbg/command/mapper/EntityMapper.java index 4d88e70..c3b81dc 100644 --- a/src/main/java/com/vamk/tbg/command/mapper/EntityMapper.java +++ b/src/main/java/com/vamk/tbg/command/mapper/EntityMapper.java @@ -3,12 +3,15 @@ import com.vamk.tbg.game.Entity; import com.vamk.tbg.game.Game; +import javax.inject.Inject; + /** * A mapper that converts strings into {@link Entity} objects. */ public class EntityMapper implements ArgumentMapper { private final Game game; + @Inject public EntityMapper(Game game) { this.game = game; } diff --git a/src/main/java/com/vamk/tbg/command/mapper/IntMapper.java b/src/main/java/com/vamk/tbg/command/mapper/IntMapper.java index d79990e..4619496 100644 --- a/src/main/java/com/vamk/tbg/command/mapper/IntMapper.java +++ b/src/main/java/com/vamk/tbg/command/mapper/IntMapper.java @@ -1,10 +1,15 @@ package com.vamk.tbg.command.mapper; +import javax.inject.Inject; + /** * A mapper that converts strings into ints. */ public class IntMapper implements ArgumentMapper { + @Inject + public IntMapper() {} + @Override public Class type() { return Integer.class; diff --git a/src/main/java/com/vamk/tbg/command/mapper/StatusEffectMapper.java b/src/main/java/com/vamk/tbg/command/mapper/StatusEffectMapper.java index 9dd0228..a55aa70 100644 --- a/src/main/java/com/vamk/tbg/command/mapper/StatusEffectMapper.java +++ b/src/main/java/com/vamk/tbg/command/mapper/StatusEffectMapper.java @@ -2,6 +2,7 @@ import com.vamk.tbg.effect.StatusEffect; +import javax.inject.Inject; import java.util.Arrays; /** @@ -9,6 +10,9 @@ */ public class StatusEffectMapper implements ArgumentMapper { + @Inject + public StatusEffectMapper() {} + @Override public Class type() { return StatusEffect.class; diff --git a/src/main/java/com/vamk/tbg/config/Config.java b/src/main/java/com/vamk/tbg/config/Config.java index 712e2dd..91721be 100644 --- a/src/main/java/com/vamk/tbg/config/Config.java +++ b/src/main/java/com/vamk/tbg/config/Config.java @@ -2,6 +2,8 @@ import com.vamk.tbg.Main; +import javax.inject.Inject; +import javax.inject.Singleton; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -13,6 +15,7 @@ * A simple configuration class. The parsed entries are * stored in the internalConfig map. */ +@Singleton public class Config { private static final String LOCATION = "/config.txt"; private static final String COMMENT_SIGN = "#"; @@ -20,6 +23,8 @@ public class Config { /* Store parsed entries in this map */ private final Map internalConfig; + + @Inject public Config() { this.internalConfig = new HashMap<>(); } diff --git a/src/main/java/com/vamk/tbg/di/GameComponent.java b/src/main/java/com/vamk/tbg/di/GameComponent.java new file mode 100644 index 0000000..f88aca7 --- /dev/null +++ b/src/main/java/com/vamk/tbg/di/GameComponent.java @@ -0,0 +1,22 @@ +package com.vamk.tbg.di; + +import com.vamk.tbg.Bootstrap; +import com.vamk.tbg.di.module.ArgumentMapperModule; +import com.vamk.tbg.di.module.CommandModule; +import com.vamk.tbg.di.module.EffectHandlerModule; +import com.vamk.tbg.di.module.MoveModule; +import dagger.Component; + +import javax.inject.Singleton; + +@Singleton +@Component(modules = { + ArgumentMapperModule.class, + CommandModule.class, + EffectHandlerModule.class, + MoveModule.class +}) +public interface GameComponent { + + Bootstrap bootstrap(); +} diff --git a/src/main/java/com/vamk/tbg/di/module/ArgumentMapperModule.java b/src/main/java/com/vamk/tbg/di/module/ArgumentMapperModule.java new file mode 100644 index 0000000..5094ca6 --- /dev/null +++ b/src/main/java/com/vamk/tbg/di/module/ArgumentMapperModule.java @@ -0,0 +1,29 @@ +package com.vamk.tbg.di.module; + +import com.vamk.tbg.command.mapper.ArgumentMapper; +import com.vamk.tbg.command.mapper.EntityMapper; +import com.vamk.tbg.command.mapper.IntMapper; +import com.vamk.tbg.command.mapper.StatusEffectMapper; +import com.vamk.tbg.di.qualifier.MapperSet; +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoSet; + +@Module +public interface ArgumentMapperModule { + + @Binds + @IntoSet + @MapperSet + ArgumentMapper bindEntityMapper(EntityMapper mapper); + + @Binds + @IntoSet + @MapperSet + ArgumentMapper bindIntMapper(IntMapper mapper); + + @Binds + @IntoSet + @MapperSet + ArgumentMapper bindStatusEffectMapper(StatusEffectMapper mapper); +} diff --git a/src/main/java/com/vamk/tbg/di/module/CommandModule.java b/src/main/java/com/vamk/tbg/di/module/CommandModule.java new file mode 100644 index 0000000..1dd5822 --- /dev/null +++ b/src/main/java/com/vamk/tbg/di/module/CommandModule.java @@ -0,0 +1,57 @@ +package com.vamk.tbg.di.module; + +import com.vamk.tbg.command.Command; +import com.vamk.tbg.command.impl.DamageCommand; +import com.vamk.tbg.command.impl.HealCommand; +import com.vamk.tbg.command.impl.KillCommand; +import com.vamk.tbg.command.impl.ListCommand; +import com.vamk.tbg.command.impl.ListEffectsCommand; +import com.vamk.tbg.command.impl.ListMovesCommand; +import com.vamk.tbg.command.impl.RemoveEffectCommand; +import com.vamk.tbg.command.impl.SetEffectCommand; +import com.vamk.tbg.di.qualifier.CommandSet; +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoSet; + +@Module +public interface CommandModule { + + @Binds + @IntoSet + @CommandSet + Command bindDamageCommand(DamageCommand command); + + @Binds + @IntoSet + @CommandSet + Command bindHealCommand(HealCommand command); + + @Binds + @IntoSet + @CommandSet + Command bindKillCommand(KillCommand command); + + @Binds + @IntoSet + Command bindListCommand(ListCommand command); + + @Binds + @IntoSet + Command bindListEffectCommand(ListEffectsCommand command); + + @Binds + @IntoSet + @CommandSet + Command bindListMovesCommand(ListMovesCommand command); + + @Binds + @IntoSet + @CommandSet + Command bindRemoveEffectCommand(RemoveEffectCommand command); + + @Binds + @IntoSet + @CommandSet + Command bindSetEffectCommand(SetEffectCommand command); +} diff --git a/src/main/java/com/vamk/tbg/di/module/EffectHandlerModule.java b/src/main/java/com/vamk/tbg/di/module/EffectHandlerModule.java new file mode 100644 index 0000000..7c197a8 --- /dev/null +++ b/src/main/java/com/vamk/tbg/di/module/EffectHandlerModule.java @@ -0,0 +1,23 @@ +package com.vamk.tbg.di.module; + +import com.vamk.tbg.di.qualifier.EffectHandlerSet; +import com.vamk.tbg.effect.BleedingEffectHandler; +import com.vamk.tbg.effect.RegenEffectHandler; +import com.vamk.tbg.effect.StatusEffectHandler; +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoSet; + +@Module +public interface EffectHandlerModule { + + @Binds + @IntoSet + @EffectHandlerSet + StatusEffectHandler bindBleedingHandler(BleedingEffectHandler handler); + + @Binds + @IntoSet + @EffectHandlerSet + StatusEffectHandler bindRegenHandler(RegenEffectHandler handler); +} diff --git a/src/main/java/com/vamk/tbg/di/module/MoveModule.java b/src/main/java/com/vamk/tbg/di/module/MoveModule.java new file mode 100644 index 0000000..203cbc3 --- /dev/null +++ b/src/main/java/com/vamk/tbg/di/module/MoveModule.java @@ -0,0 +1,53 @@ +package com.vamk.tbg.di.module; + +import com.vamk.tbg.combat.BuffMove; +import com.vamk.tbg.combat.CureMove; +import com.vamk.tbg.combat.DamageMove; +import com.vamk.tbg.combat.DebuffMove; +import com.vamk.tbg.combat.HealAllMove; +import com.vamk.tbg.combat.HealMove; +import com.vamk.tbg.combat.Move; +import com.vamk.tbg.combat.SplashDamageMove; +import com.vamk.tbg.di.qualifier.MoveSet; +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoSet; + +@Module +public interface MoveModule { + + @Binds + @IntoSet + @MoveSet + Move bindBuffMove(BuffMove move); + + @Binds + @IntoSet + @MoveSet + Move bindCureMove(CureMove move); + + @Binds + @IntoSet + @MoveSet + Move bindDamageMove(DamageMove move); + + @Binds + @IntoSet + @MoveSet + Move bindDebuffMove(DebuffMove move); + + @Binds + @IntoSet + @MoveSet + Move bindHealAllMove(HealAllMove move); + + @Binds + @IntoSet + @MoveSet + Move bindHealMove(HealMove move); + + @Binds + @IntoSet + @MoveSet + Move bindSplashDamageMove(SplashDamageMove move); +} diff --git a/src/main/java/com/vamk/tbg/di/qualifier/CommandSet.java b/src/main/java/com/vamk/tbg/di/qualifier/CommandSet.java new file mode 100644 index 0000000..40d464e --- /dev/null +++ b/src/main/java/com/vamk/tbg/di/qualifier/CommandSet.java @@ -0,0 +1,9 @@ +package com.vamk.tbg.di.qualifier; + +import javax.inject.Qualifier; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface CommandSet {} diff --git a/src/main/java/com/vamk/tbg/di/qualifier/EffectHandlerSet.java b/src/main/java/com/vamk/tbg/di/qualifier/EffectHandlerSet.java new file mode 100644 index 0000000..2f226b4 --- /dev/null +++ b/src/main/java/com/vamk/tbg/di/qualifier/EffectHandlerSet.java @@ -0,0 +1,9 @@ +package com.vamk.tbg.di.qualifier; + +import javax.inject.Qualifier; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface EffectHandlerSet {} diff --git a/src/main/java/com/vamk/tbg/di/qualifier/MapperSet.java b/src/main/java/com/vamk/tbg/di/qualifier/MapperSet.java new file mode 100644 index 0000000..bae475d --- /dev/null +++ b/src/main/java/com/vamk/tbg/di/qualifier/MapperSet.java @@ -0,0 +1,9 @@ +package com.vamk.tbg.di.qualifier; + +import javax.inject.Qualifier; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface MapperSet {} diff --git a/src/main/java/com/vamk/tbg/di/qualifier/MoveSet.java b/src/main/java/com/vamk/tbg/di/qualifier/MoveSet.java new file mode 100644 index 0000000..f693947 --- /dev/null +++ b/src/main/java/com/vamk/tbg/di/qualifier/MoveSet.java @@ -0,0 +1,9 @@ +package com.vamk.tbg.di.qualifier; + +import javax.inject.Qualifier; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface MoveSet {} diff --git a/src/main/java/com/vamk/tbg/effect/BleedingEffectHandler.java b/src/main/java/com/vamk/tbg/effect/BleedingEffectHandler.java index 7b9c979..5bd6326 100644 --- a/src/main/java/com/vamk/tbg/effect/BleedingEffectHandler.java +++ b/src/main/java/com/vamk/tbg/effect/BleedingEffectHandler.java @@ -6,6 +6,7 @@ import com.vamk.tbg.util.LogUtil; import com.vamk.tbg.util.RandomUtil; +import javax.inject.Inject; import java.util.logging.Logger; /** @@ -15,6 +16,7 @@ public class BleedingEffectHandler implements StatusEffectHandler { private static final Logger LOGGER = LogUtil.getLogger(BleedingEffectHandler.class); private final Config config; + @Inject public BleedingEffectHandler(Config config) { this.config = config; } diff --git a/src/main/java/com/vamk/tbg/effect/RegenEffectHandler.java b/src/main/java/com/vamk/tbg/effect/RegenEffectHandler.java index 505f3a3..9629d6f 100644 --- a/src/main/java/com/vamk/tbg/effect/RegenEffectHandler.java +++ b/src/main/java/com/vamk/tbg/effect/RegenEffectHandler.java @@ -6,6 +6,7 @@ import com.vamk.tbg.util.LogUtil; import com.vamk.tbg.util.RandomUtil; +import javax.inject.Inject; import java.util.logging.Logger; /** @@ -15,6 +16,7 @@ public class RegenEffectHandler implements StatusEffectHandler { private static final Logger LOGGER = LogUtil.getLogger(RegenEffectHandler.class); private final Config config; + @Inject public RegenEffectHandler(Config config) { this.config = config; } diff --git a/src/main/java/com/vamk/tbg/game/Game.java b/src/main/java/com/vamk/tbg/game/Game.java index 92ff686..3493226 100644 --- a/src/main/java/com/vamk/tbg/game/Game.java +++ b/src/main/java/com/vamk/tbg/game/Game.java @@ -1,17 +1,10 @@ package com.vamk.tbg.game; -import com.vamk.tbg.combat.BuffMove; -import com.vamk.tbg.combat.CureMove; -import com.vamk.tbg.combat.DamageMove; -import com.vamk.tbg.combat.DebuffMove; -import com.vamk.tbg.combat.HealAllMove; -import com.vamk.tbg.combat.HealMove; import com.vamk.tbg.combat.Move; -import com.vamk.tbg.combat.SplashDamageMove; import com.vamk.tbg.config.Config; import com.vamk.tbg.config.Keys; -import com.vamk.tbg.effect.BleedingEffectHandler; -import com.vamk.tbg.effect.RegenEffectHandler; +import com.vamk.tbg.di.qualifier.EffectHandlerSet; +import com.vamk.tbg.di.qualifier.MoveSet; import com.vamk.tbg.effect.StatusEffect; import com.vamk.tbg.effect.StatusEffectHandler; import com.vamk.tbg.signal.SignalDispatcher; @@ -24,6 +17,8 @@ import com.vamk.tbg.util.LogUtil; import com.vamk.tbg.util.RandomUtil; +import javax.inject.Inject; +import javax.inject.Singleton; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -36,34 +31,29 @@ * itself as well as creating all entities, dealing with * serialization and more. */ +@Singleton public class Game { private static final Logger LOGGER = LogUtil.getLogger(Game.class); - private final Map moves; private final SignalDispatcher dispatcher; private final Config config; + private final Map moves; + private final Set effectHandlers; private final Entity.Factory entityFactory; private final List entities; - private final Set effectHandlers; private Cursor cursor; private boolean importedState = false; - public Game(SignalDispatcher dispatcher, Config config) { - this.moves = CollectionUtil.mapOf( - Move::getId, - new BuffMove(config), - new CureMove(), - new DebuffMove(config), - new DamageMove(config), - new HealAllMove(config), - new HealMove(config), - new SplashDamageMove(config) - ); - + @Inject + public Game(SignalDispatcher dispatcher, + Config config, + @MoveSet Set moves, + @EffectHandlerSet Set effectHandlers) { this.dispatcher = dispatcher; this.config = config; + this.moves = CollectionUtil.mapOf(Move::getId, moves); + this.effectHandlers = effectHandlers; this.entityFactory = new Entity.Factory(dispatcher, this.moves); this.entities = new ArrayList<>(); - this.effectHandlers = Set.of(new BleedingEffectHandler(config), new RegenEffectHandler(config)); } /** diff --git a/src/main/java/com/vamk/tbg/signal/SignalDispatcher.java b/src/main/java/com/vamk/tbg/signal/SignalDispatcher.java index 85cc8a2..24d9b8e 100644 --- a/src/main/java/com/vamk/tbg/signal/SignalDispatcher.java +++ b/src/main/java/com/vamk/tbg/signal/SignalDispatcher.java @@ -2,6 +2,8 @@ import com.vamk.tbg.util.LogUtil; +import javax.inject.Inject; +import javax.inject.Singleton; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -14,10 +16,12 @@ * (aka subscribe) to certain signals, and when a signal is * dispatched, all subscribers are notified. */ +@Singleton public class SignalDispatcher { private static final Logger LOGGER = LogUtil.getLogger(SignalDispatcher.class); private final Map, List>> handlers; + @Inject public SignalDispatcher() { this.handlers = new HashMap<>(); } diff --git a/src/main/java/com/vamk/tbg/ui/ButtonContainer.java b/src/main/java/com/vamk/tbg/ui/ButtonContainer.java index e711af5..f0847ef 100644 --- a/src/main/java/com/vamk/tbg/ui/ButtonContainer.java +++ b/src/main/java/com/vamk/tbg/ui/ButtonContainer.java @@ -10,6 +10,7 @@ import com.vamk.tbg.signal.impl.GameReadySignal; import com.vamk.tbg.signal.impl.UserReadySignal; +import javax.inject.Inject; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JSeparator; @@ -35,6 +36,7 @@ public class ButtonContainer extends JPanel { private Entity currentEntity; private Move move; + @Inject public ButtonContainer(SignalDispatcher dispatcher, Config config) { this.dispatcher = dispatcher; this.config = config; diff --git a/src/main/java/com/vamk/tbg/ui/EntityDataContainer.java b/src/main/java/com/vamk/tbg/ui/EntityDataContainer.java index e8ef50e..3aec0f2 100644 --- a/src/main/java/com/vamk/tbg/ui/EntityDataContainer.java +++ b/src/main/java/com/vamk/tbg/ui/EntityDataContainer.java @@ -8,6 +8,7 @@ import com.vamk.tbg.signal.impl.EntityPlaysSignal; import com.vamk.tbg.signal.impl.GameReadySignal; +import javax.inject.Inject; import javax.swing.JPanel; import java.awt.GridLayout; import java.io.Serial; @@ -24,6 +25,7 @@ public class EntityDataContainer extends JPanel { private static final long serialVersionUID = -7455891810519039109L; private final Map entityData; + @Inject public EntityDataContainer(SignalDispatcher dispatcher) { dispatcher.subscribe(GameReadySignal.class, this::onGameReady); dispatcher.subscribe(EntityDeathSignal.class, this::onEntityDeath); diff --git a/src/main/java/com/vamk/tbg/ui/GameWindow.java b/src/main/java/com/vamk/tbg/ui/GameWindow.java index 79417a8..bc69da9 100644 --- a/src/main/java/com/vamk/tbg/ui/GameWindow.java +++ b/src/main/java/com/vamk/tbg/ui/GameWindow.java @@ -1,8 +1,10 @@ package com.vamk.tbg.ui; -import com.vamk.tbg.config.Config; import com.vamk.tbg.signal.SignalDispatcher; import com.vamk.tbg.signal.impl.EntityPlaysSignal; +import dagger.assisted.Assisted; +import dagger.assisted.AssistedFactory; +import dagger.assisted.AssistedInject; import javax.swing.JFrame; import javax.swing.JLabel; @@ -23,7 +25,11 @@ public class GameWindow extends JFrame implements WindowListener { private final JLabel entityLabel; private final Runnable shutdownHook; - public GameWindow(SignalDispatcher dispatcher, Config config, Runnable shutdownHook) { + @AssistedInject + public GameWindow(SignalDispatcher dispatcher, + ButtonContainer btnContainer, + EntityDataContainer edContainer, + @Assisted Runnable shutdownHook) { this.entityLabel = new JLabel(); this.entityLabel.setFont(new Font("Tahoma", Font.BOLD, 20)); // Change the default font size this.entityLabel.setHorizontalAlignment(JLabel.CENTER); @@ -37,9 +43,9 @@ public GameWindow(SignalDispatcher dispatcher, Config config, Runnable shutdownH setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(1000, 1000); setLayout(new GridLayout(3, 1)); - add(new ButtonContainer(dispatcher, config)); + add(btnContainer); add(this.entityLabel); - add(new EntityDataContainer(dispatcher)); + add(edContainer); setVisible(true); dispatcher.subscribe(EntityPlaysSignal.class, this::onEntityPlays); } @@ -71,4 +77,10 @@ public void windowActivated(WindowEvent event) {} @Override public void windowDeactivated(WindowEvent event) {} + + @AssistedFactory + public interface Factory { + + GameWindow create(Runnable shutdownHook); + } } diff --git a/src/main/java/com/vamk/tbg/util/CollectionUtil.java b/src/main/java/com/vamk/tbg/util/CollectionUtil.java index e6a7429..818e04a 100644 --- a/src/main/java/com/vamk/tbg/util/CollectionUtil.java +++ b/src/main/java/com/vamk/tbg/util/CollectionUtil.java @@ -1,11 +1,10 @@ package com.vamk.tbg.util; +import java.util.Collection; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; -import java.util.stream.Stream; -// TODO once dagger is in place, this class is not needed anymore. public final class CollectionUtil { private CollectionUtil() {} @@ -16,8 +15,7 @@ private CollectionUtil() {} * @see com.vamk.tbg.command.CommandManager * @see com.vamk.tbg.game.Game */ - @SafeVarargs - public static Map mapOf(Function keyMapper, V... values) { - return Stream.of(values).collect(Collectors.toMap(keyMapper, Function.identity())); + public static > Map mapOf(Function keyMapper, C values) { + return values.stream().collect(Collectors.toMap(keyMapper, Function.identity())); } }