feat(app): main-menu shell loop wiring; gitignore saves/
Replace App.run with a main-menu shell (New Game / Load / Settings / Quit) above the game loop, wire SaveCommand + MenuCommand into the registry with an autosave callback, and remove the now-unused QuitCommand. Migrate GameTest from QuitCommand to MenuCommand. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,23 +11,36 @@ 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.QuitCommand;
|
||||
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.MenuAction;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Entry point for the console version of the game. Loads the world from
|
||||
* YAML, wires up the command registry, and hands control to the
|
||||
* {@link Game} loop.
|
||||
* 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 {
|
||||
@@ -35,31 +48,63 @@ 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);
|
||||
log.error("Fatal error", e);
|
||||
io.write("Fatal error: " + e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Boots the game on the given IO channel. Reusable by both
|
||||
* {@link App} (console) and {@code AppGui} (Swing worker thread).
|
||||
*
|
||||
* @param io the IO channel to use
|
||||
*/
|
||||
/** 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, saves));
|
||||
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, SaveService saves) {
|
||||
WorldLoader.LoadResult loaded = new WorldLoader().load();
|
||||
GameContext ctx = new GameContext(loaded.world(), loaded.player(), io);
|
||||
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");
|
||||
@@ -74,17 +119,18 @@ public final class App {
|
||||
registry.register(new QuestsCommand(), "quests", "log", "journal");
|
||||
registry.register(new TalkCommand(), "talk", "speak");
|
||||
registry.register(new GiveCommand(), "give");
|
||||
registry.register(new HelpCommand(registry), "help", "?");
|
||||
|
||||
QuitCommand quit = new QuitCommand();
|
||||
registry.register(quit, "quit", "exit");
|
||||
registry.register(new SaveCommand(saves), "save");
|
||||
|
||||
Game game = new Game(ctx, registry, new CommandParser());
|
||||
quit.bind(game);
|
||||
|
||||
io.print(Banner.welcome(loaded.world().getTitle()));
|
||||
io.write(loaded.world().getWelcomeMessage());
|
||||
new LookCommand().execute(ctx, java.util.List.of());
|
||||
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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user