package thb.jeanluc.adventure; import lombok.extern.slf4j.Slf4j; import thb.jeanluc.adventure.command.CommandParser; import thb.jeanluc.adventure.command.CommandRegistry; import thb.jeanluc.adventure.command.impl.DropCommand; import thb.jeanluc.adventure.command.impl.ExamineCommand; import thb.jeanluc.adventure.command.impl.GiveCommand; import thb.jeanluc.adventure.command.impl.GoCommand; import thb.jeanluc.adventure.command.impl.HelpCommand; import thb.jeanluc.adventure.command.impl.InventoryCommand; import thb.jeanluc.adventure.command.impl.LookCommand; import thb.jeanluc.adventure.command.impl.MapCommand; import thb.jeanluc.adventure.command.impl.MenuCommand; import thb.jeanluc.adventure.command.impl.QuestsCommand; import thb.jeanluc.adventure.command.impl.ReadCommand; import thb.jeanluc.adventure.command.impl.SaveCommand; import thb.jeanluc.adventure.command.impl.TakeCommand; import thb.jeanluc.adventure.command.impl.TalkCommand; import thb.jeanluc.adventure.command.impl.UseCommand; import thb.jeanluc.adventure.game.Game; import thb.jeanluc.adventure.game.GameContext; import thb.jeanluc.adventure.game.GameSession; import thb.jeanluc.adventure.io.ConsoleIO; import thb.jeanluc.adventure.io.GameIO; import thb.jeanluc.adventure.io.text.Banner; import thb.jeanluc.adventure.loader.WorldLoader; import thb.jeanluc.adventure.menu.MainMenu; import thb.jeanluc.adventure.menu.SettingsMenu; import thb.jeanluc.adventure.save.SaveException; import thb.jeanluc.adventure.save.SaveService; import thb.jeanluc.adventure.save.SaveSlotInfo; import thb.jeanluc.adventure.save.Settings; import thb.jeanluc.adventure.save.SettingsStore; import java.util.List; /** * Console entry point. Loads settings, then runs the main-menu shell loop: * New Game / Load / Settings / Quit. Each game runs the shared {@link Game} * loop and returns here when the player saves-and-exits, reaches an ending, * or input ends. Shared by console and GUI via {@link #run(GameIO)}. */ @Slf4j public final class App { private App() { } /** Standard JVM entry point. @param args ignored */ public static void main(String[] args) { GameIO io = new ConsoleIO(); try { run(io); } catch (RuntimeException e) { log.error("Fatal error during game startup", e); io.write("Fatal error: " + e.getMessage()); System.exit(1); } } /** Runs the menu shell on the given IO until the player quits. */ public static void run(GameIO io) { SaveService saves = new SaveService(); SettingsStore settingsStore = new SettingsStore(); Settings settings = settingsStore.load(); ConsoleIO consoleIo = io instanceof ConsoleIO c ? c : null; SettingsMenu.apply(settings, consoleIo); boolean running = true; while (running) { switch (MainMenu.show(io)) { case NEW_GAME -> play(io, saves, newSession(io)); case LOAD -> { SaveSlotInfo slot = MainMenu.pickSlot(io, saves); if (slot != null) { try { play(io, saves, saves.load(slot.slug())); } catch (SaveException e) { io.write("Could not load: " + e.getUserMessage()); } } } case SETTINGS -> settings = SettingsMenu.show(io, settings, settingsStore, consoleIo); case QUIT -> running = false; } } io.write("Farewell."); } /** Loads a fresh world and binds it to a newly named session. */ private static GameSession newSession(GameIO io) { WorldLoader.LoadResult loaded = new WorldLoader().load(); String name = MainMenu.promptName(io, "Manor"); return new GameSession(loaded.world(), loaded.player(), name); } /** Builds the registry, runs one game to completion, autosaving to its slot. */ private static void play(GameIO io, SaveService saves, GameSession session) { GameContext ctx = new GameContext(session, io); ctx.setSaveCallback(() -> { try { saves.save(session); } catch (SaveException e) { log.warn("Autosave failed", e); } }); CommandRegistry registry = new CommandRegistry(); registry.register(new GoCommand(), "go", "move", "walk"); registry.register(new LookCommand(), "look", "l"); registry.register(new InventoryCommand(), "inventory", "inv", "i"); registry.register(new TakeCommand(), "take", "pick", "get"); registry.register(new DropCommand(), "drop", "put"); registry.register(new UseCommand(), "use"); registry.register(new ReadCommand(), "read"); registry.register(new ExamineCommand(), "examine", "x", "inspect"); registry.register(new MapCommand(), "map", "m"); registry.register(new QuestsCommand(), "quests", "log", "journal"); registry.register(new TalkCommand(), "talk", "speak"); registry.register(new GiveCommand(), "give"); registry.register(new SaveCommand(saves), "save"); Game game = new Game(ctx, registry, new CommandParser()); MenuCommand menu = new MenuCommand(saves); menu.bind(game); registry.register(menu, "menu", "quit", "exit"); registry.register(new HelpCommand(registry), "help", "?"); io.print(Banner.welcome(session.getWorld().getTitle())); io.write(session.getWorld().getWelcomeMessage()); new LookCommand().execute(ctx, List.of()); game.run(); } }