-
Notifications
You must be signed in to change notification settings - Fork 0
[Batch 3] Save/load UI + world list screen #382
Copy link
Copy link
Open
Labels
batch-3Batch 3: IntegrationBatch 3: IntegrationbugSomething isn't workingSomething isn't workingdocumentationImprovements or additions to documentationImprovements or additions to documentationenhancementNew feature or requestNew feature or requestgamehotfixquestionFurther information is requestedFurther information is requested
Description
Summary
Add in-game UI for loading saved worlds and creating new worlds that persist. This is the player-facing half of the persistence system.
Depends on: #377 (chunk serialization API) — needs SaveManager.loadChunk() to exist
Current Behavior
The SingleplayerScreen has:
- Seed text input (keyboard typing)
- RANDOM button for random seed
- World type selector (cycles through registered generators)
- CREATE button → creates new
WorldScreenwith seed → generates fresh world
There is no "load existing world" option. No save directory is scanned.
Target Behavior
SingleplayerScreen changes
- Split into two sections: "CREATE NEW WORLD" and "LOAD WORLD"
- "LOAD WORLD" button → navigates to new
WorldListScreen
WorldListScreen (new)
- Scans
~/.config/zigcraft/saves/directory - Lists each world as a row:
- World name (from directory name or level.dat)
- Seed (from level.dat)
- Last played (timestamp from level.dat)
- Generator type (from level.dat)
- Click a world → load it → navigate to
WorldScreen - Delete button with confirmation
- Back button returns to singleplayer
GameSession changes
GameSession.init()currently always generates a fresh world- Add path for loading from save:
init()takes optionalsave_dirparameter - If save_dir provided:
WorldusesSaveManagerto load chunks instead of generating - If no save_dir: current behavior (fresh generation)
Implementation Plan
Step 1: WorldListScreen
// src/game/screens/world_list.zig
const WorldListScreen = struct {
worlds: []WorldEntry,
selected: ?usize,
scroll_offset: f32,
const WorldEntry = struct {
name: []const u8,
seed: u64,
last_played: i64,
generator: []const u8,
dir_path: []const u8,
};
};onEnter(): scan save directory, read eachlevel.dat, populate listupdate(): handle scroll, selection, clickdraw(): render list with UISystem (same pattern as other screens)- Back button, Load button, Delete button
Step 2: SingleplayerScreen modifications
- Add "LOAD WORLD" button below "CREATE"
- On click →
screen_manager.push(WorldListScreen) - Keep existing create flow unchanged
Step 3: GameSession load path
- Add
save_dir: ?[]const u8to session init params - When
save_dir != null: createSaveManager, pass toWorld/WorldStreamer WorldStreamer.generateChunk()tries load before generate (see [Batch 3] Integrate GPU frustum culling into WorldRenderer #379 integration)- World name displayed in HUD or debug overlay
Step 4: Delete world
- Confirmation dialog: "Delete world ''? This cannot be undone."
- On confirm: recursively delete save directory
- Refresh world list
Files to Create
src/game/screens/world_list.zig— new screen
Files to Modify
src/game/screens/singleplayer.zig— add "LOAD WORLD" buttonsrc/game/session.zig— load path, save_dir parametersrc/game/screen.zig— register new screen type (if needed)src/tests.zigorsrc/game/screen_tests.zig— tests for WorldListScreen
Testing
- Create world → close → load world → blocks are where you left them
- World list shows all saves with correct info
- Delete world removes directory and refreshes list
- Cancel delete does nothing
- Loading invalid/corrupt save shows error, doesn't crash
- Empty save directory shows helpful message
- Back button returns to singleplayer screen
Roadmap: docs/PERFORMANCE_ROADMAP.md — Batch 3, Issue 2C
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
batch-3Batch 3: IntegrationBatch 3: IntegrationbugSomething isn't workingSomething isn't workingdocumentationImprovements or additions to documentationImprovements or additions to documentationenhancementNew feature or requestNew feature or requestgamehotfixquestionFurther information is requestedFurther information is requested