Allow naming savegames

This commit is contained in:
tobspr 2020-08-28 22:15:12 +02:00
parent a095cd6324
commit 728f4ae253
5 changed files with 1383 additions and 1297 deletions

View File

@ -285,13 +285,13 @@
@include S(border-radius, $globalBorderRadius);
@include S(padding, 5px);
display: grid;
grid-template-columns: 1fr auto auto;
grid-template-columns: 1fr 1fr auto auto;
grid-template-rows: auto auto;
@include S(grid-column-gap, 4px);
@include S(grid-row-gap, 1px);
.playtime {
grid-column: 1 / 2;
grid-column: 2 / 3;
grid-row: 2 / 3;
@include SuperSmallText;
opacity: 0.5;
@ -299,13 +299,23 @@
.level {
grid-column: 1 / 2;
grid-row: 2 / 3;
@include SuperSmallText;
opacity: 0.5;
}
.name {
grid-column: 1 / 3;
grid-row: 1 / 2;
@include PlainText;
display: inline-flex;
align-items: center;
}
button.resumeGame,
button.downloadGame,
button.deleteGame {
button.deleteGame,
button.renameGame {
padding: 0;
align-self: center;
justify-self: center;
@ -314,7 +324,7 @@
}
button.downloadGame {
grid-column: 2 / 3;
grid-column: 3 / 4;
grid-row: 1 / 2;
background-color: $colorBlueBright;
background-image: uiResource("icons/download.png");
@ -326,7 +336,7 @@
}
button.deleteGame {
grid-column: 2 / 3;
grid-column: 3 / 4;
grid-row: 2 / 3;
background-color: $colorRedBright;
@include IncreasedClickArea(0px);
@ -337,8 +347,26 @@
background-size: 60%;
}
button.renameGame {
background-color: transparent;
@include IncreasedClickArea(2px);
background-image: uiResource("icons/edit_key.png");
@include S(width, 10px);
@include S(height, 10px);
align-self: center;
justify-self: center;
background-size: 90%;
opacity: 0.25;
@include S(margin-left, 4px);
&:hover {
opacity: 0.35;
}
}
button.resumeGame {
grid-column: 3 / 4;
grid-column: 4 / 5;
grid-row: 1 / 3;
margin: 0;
@include S(width, 32px);

View File

@ -37,7 +37,7 @@ export class SavegameManager extends ReadWriteProxy {
}
getCurrentVersion() {
return 1001;
return 1002;
}
/**
@ -64,6 +64,13 @@ export class SavegameManager extends ReadWriteProxy {
data.version = 1001;
}
if (data.version < 1002) {
data.savegames.forEach(savegame => {
savegame.name = null;
});
data.version = 1002;
}
return ExplainedResult.good();
}

View File

@ -27,6 +27,7 @@
* version: number,
* internalId: string,
* level: number
* name: string|null
* }} SavegameMetadata
*
* @typedef {{

View File

@ -14,6 +14,8 @@ import { ReadWriteProxy } from "../core/read_write_proxy";
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
import { T } from "../translations";
import { getApplicationSettingById } from "../profile/application_settings";
import { FormElementInput } from "../core/modal_dialog_forms";
import { DialogWithForm } from "../core/modal_dialog_elements";
/**
* @typedef {import("../savegame/savegame_typedefs").SavegameMetadata} SavegameMetadata
@ -392,6 +394,13 @@ export class MainMenuState extends GameState {
: T.mainMenu.savegameLevelUnknown
);
const name = makeDiv(
elem,
null,
["name"],
games[i].name ? games[i].name : T.mainMenu.savegameUnnamed
);
const deleteButton = document.createElement("button");
deleteButton.classList.add("styledButton", "deleteGame");
elem.appendChild(deleteButton);
@ -400,6 +409,10 @@ export class MainMenuState extends GameState {
downloadButton.classList.add("styledButton", "downloadGame");
elem.appendChild(downloadButton);
const renameButton = document.createElement("button");
renameButton.classList.add("styledButton", "renameGame");
name.appendChild(renameButton);
const resumeButton = document.createElement("button");
resumeButton.classList.add("styledButton", "resumeGame");
elem.appendChild(resumeButton);
@ -407,10 +420,41 @@ export class MainMenuState extends GameState {
this.trackClicks(deleteButton, () => this.deleteGame(games[i]));
this.trackClicks(downloadButton, () => this.downloadGame(games[i]));
this.trackClicks(resumeButton, () => this.resumeGame(games[i]));
this.trackClicks(renameButton, () => this.requestRenameSavegame(games[i]));
}
}
}
/**
* @param {SavegameMetadata} game
*/
requestRenameSavegame(game) {
const regex = /^[a-zA-Z0-9_\- ]{1,20}$/;
const nameInput = new FormElementInput({
id: "nameInput",
label: null,
placeholder: "",
defaultValue: game.name || "",
validator: val => val.match(regex),
});
const dialog = new DialogWithForm({
app: this.app,
title: T.dialogs.renameSavegame.title,
desc: T.dialogs.renameSavegame.desc,
formElements: [nameInput],
buttons: ["cancel:bad:escape", "ok:good:enter"],
});
this.dialogs.internalShowDialog(dialog);
// When confirmed, save the name
dialog.buttonSignals.ok.add(() => {
game.name = nameInput.getValue();
this.app.savegameMgr.writeAsync();
this.renderSavegames();
});
}
/**
* @param {SavegameMetadata} game
*/
@ -473,7 +517,8 @@ export class MainMenuState extends GameState {
const savegame = this.app.savegameMgr.getSavegameById(game.internalId);
savegame.readAsync().then(() => {
const data = ReadWriteProxy.serializeObject(savegame.currentData);
generateFileDownload(savegame.filename, data);
const filename = (game.name || "unnamed") + ".bin";
generateFileDownload(filename, data);
});
}

View File

@ -157,6 +157,7 @@ mainMenu:
savegameLevel: Level <x>
savegameLevelUnknown: Unknown Level
savegameUnnamed: Unnamed
dialogs:
buttons:
@ -274,6 +275,10 @@ dialogs:
title: Export screenshot
desc: You requested to export your base as a screenshot. Please note that this can be quite slow for a big base and even crash your game!
renameSavegame:
title: Rename Savegame
desc: You can rename your savegame here.
ingame:
# This is shown in the top left corner and displays useful keybindings in
# every situation