import { Container, MenuList, Panel, PixelText, type Scene } from '@rpg/engine';
import type { Game } from '../Game';
import type { SaveData } from './MenuScene';
/**
* Меню сейвов: autosave (только загрузка) + 3 именованных слота
* (загрузка/удаление). Панель поверх меню (push/pop).
*/
export class SaveSlotsScene implements Scene {
private view = new Container();
private menu: MenuList;
constructor(
private game: Game,
private onPick: (save: SaveData) => void,
private onBack: () => void
) {
const panel = new Panel({ width: 240, height: 150 });
panel.position.set((480 - 240) / 2, (270 - 150) / 2);
const title = new PixelText({ text: 'СЕЙВЫ', size: 14, color: 0xd8c79a });
title.anchor.set(0.5);
title.position.set(120, 14);
panel.addChild(title);
this.menu = new MenuList({ width: 200, height: 14, gap: 3, size: 10 });
this.menu.position.set(20, 36);
panel.addChild(this.menu);
this.view.addChild(panel);
this.game.renderer.uiRoot.addChild(this.view);
this.rebuild();
}
enter(): void {}
exit(): void {
this.view.destroy({ children: true });
}
render(): void {}
update(_dt: number): void {
if (this.game.scenes.transitioning) return;
const input = this.game.engine.input;
if (input.isActionJustPressed('menu')) {
this.back();
return;
}
if (input.isActionJustPressed('up')) this.menu.moveCursor(-1);
if (input.isActionJustPressed('down')) this.menu.moveCursor(1);
if (input.isActionJustPressed('advance')) this.menu.activate();
// Delete на выбранном именованном слоте — стереть
if (input.isActionJustPressed('attack')) this.deleteAt(this.menu.index);
}
/** Пересобрать список слотов из SaveManager (listSlots + load). */
private rebuild(): void {
const items: { label: string; onSelect: () => void }[] = [];
const slots = this.game.saves.listSlots();
for (const slot of ['autosave', 'slot1', 'slot2', 'slot3']) {
const exists = slots.includes(slot);
if (!exists) {
items.push({ label: `${this.slotTitle(slot)} — пусто —`, onSelect: () => {} });
continue;
}
const save = this.game.saves.load<SaveData>(slot)!;
const loc = save.location === 'ponds' ? 'пруды' : 'луга';
const date = new Date(save.savedAt);
const when = `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
items.push({
label: `${this.slotTitle(slot)} ${loc} ${when}`,
onSelect: () => {
void this.game.audio.play('sfx/ui_click');
this.onPick(save);
}
});
}
items.push({ label: 'Назад', onSelect: () => this.back() });
this.menu.setItems(items);
}
/** Удалить сейв в выбранной строке (именованные слоты; autosave защищён). */
private deleteAt(index: number): void {
const slot = ['autosave', 'slot1', 'slot2', 'slot3'][index];
if (!slot || slot === 'autosave' || !this.game.saves.listSlots().includes(slot)) return;
this.game.saves.delete(slot);
void this.game.audio.play('sfx/ui_click');
this.rebuild();
}
private slotTitle(slot: string): string {
if (slot === 'autosave') return 'Авто';
return slot.replace('slot', 'Слот ');
}
private back(): void {
void this.game.audio.play('sfx/ui_click');
this.onBack();
}
}