1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2026-03-02 03:39:21 +00:00

Add ability to import savegames, add game menu, multiple smaller improvements

This commit is contained in:
tobspr
2020-05-16 17:57:25 +02:00
parent c1d720ca52
commit 224bc6c7e5
31 changed files with 1422 additions and 47 deletions

View File

@@ -1,8 +1,15 @@
import { GameState } from "../core/game_state";
import { cachebust } from "../core/cachebust";
import { globalConfig } from "../core/config";
import { makeDiv, formatSecondsToTimeAgo, generateFileDownload } from "../core/utils";
import {
makeDiv,
formatSecondsToTimeAgo,
generateFileDownload,
removeAllChildren,
waitNextFrame,
} from "../core/utils";
import { ReadWriteProxy } from "../core/read_write_proxy";
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
export class MainMenuState extends GameState {
constructor() {
@@ -10,23 +17,62 @@ export class MainMenuState extends GameState {
}
getInnerHTML() {
const bannerHtml = `
<h3>This is a Demo Version</h3>
<p>Get <strong>shapez.io on steam</strong> for:</p>
<ul>
<li>No advertisements and demo banners.</li>
<li>Unlimited savegame slots.</li>
<li>Supporting the developer ❤️</li>
</ul>
<a href="https://steam.shapez.io" class="steamLink" target="_blank">Get shapez.io on steam!</a>
`;
return `
<video autoplay muted loop class="fullscreenBackgroundVideo">
<source src="${cachebust("res/bg_render.webm")}" type="video/webm">
</video>
<div class="logo">
<img src="${cachebust("res/logo.png")}" alt="shapez.io Logo">
</div>
<div class="betaWarning">
This game is still under development - Please report any issues!
${
G_IS_STANDALONE
? ""
: `
<div class="demoBadge"></div>
`
}
</div>
<div class="mainContainer">
<button class="playButton styledButton">Play</button>
<div class="mainWrapper">
${
G_IS_STANDALONE
? ""
: `
<div class="standaloneBanner leftSide">${bannerHtml}</div>
`
}
<div class="mainContainer">
<button class="playButton styledButton">Play</button>
<button class="importButton styledButton">Import savegame</button>
</div>
${
G_IS_STANDALONE
? ""
: `
<div class="standaloneBanner rightSide">${bannerHtml}</div>
`
}
</div>
<div class="footer">
@@ -45,6 +91,60 @@ export class MainMenuState extends GameState {
`;
}
requestImportSavegame() {
var input = document.createElement("input");
input.type = "file";
input.accept = ".bin";
input.onchange = e => {
const file = input.files[0];
if (file) {
waitNextFrame().then(() => {
const closeLoader = this.dialogs.showLoadingDialog();
const reader = new FileReader();
reader.addEventListener("load", event => {
const contents = event.target.result;
let realContent;
try {
realContent = ReadWriteProxy.deserializeObject(contents);
} catch (err) {
closeLoader();
this.dialogs.showWarning(
"Import error",
"Failed to import your savegame:<br><br>" + err
);
return;
}
this.app.savegameMgr.importSavegame(realContent).then(
() => {
closeLoader();
this.dialogs.showWarning("Imported", "Your savegame has been imported.");
this.renderSavegames();
},
err => {
closeLoader();
this.dialogs.showWarning(
"Import error",
"Failed to import savegame. Please check the console output."
);
}
);
});
reader.addEventListener("error", error => {
console.error(error);
alert("Failed to read file: " + error);
});
reader.readAsText(file, "utf-8");
});
}
};
input.click();
}
onBackButton() {
this.app.platformWrapper.exitApp();
}
@@ -54,8 +154,13 @@ export class MainMenuState extends GameState {
alert("Error while loading game: " + payload.loadError);
}
this.dialogs = new HUDModalDialogs(null, this.app);
const dialogsElement = document.body.querySelector(".modalDialogParent");
this.dialogs.initializeToElement(dialogsElement);
const qs = this.htmlElement.querySelector.bind(this.htmlElement);
this.trackClicks(qs(".mainContainer .playButton"), this.onPlayButtonClicked);
this.trackClicks(qs(".mainContainer .importButton"), this.requestImportSavegame);
if (G_IS_DEV && globalConfig.debug.fastGameEnter) {
this.onPlayButtonClicked();
@@ -76,6 +181,10 @@ export class MainMenuState extends GameState {
}
renderSavegames() {
const oldContainer = this.htmlElement.querySelector(".mainContainer .savegames");
if (oldContainer) {
oldContainer.remove();
}
const games = this.app.savegameMgr.getSavegamesMetaData();
if (games.length > 0) {
const parent = makeDiv(this.htmlElement.querySelector(".mainContainer"), null, ["savegames"]);
@@ -91,6 +200,10 @@ export class MainMenuState extends GameState {
formatSecondsToTimeAgo((new Date().getTime() - games[i].lastUpdate) / 1000.0)
);
const deleteButton = document.createElement("button");
deleteButton.classList.add("styledButton", "deleteGame");
elem.appendChild(deleteButton);
const downloadButton = document.createElement("button");
downloadButton.classList.add("styledButton", "downloadGame");
elem.appendChild(downloadButton);
@@ -99,6 +212,7 @@ export class MainMenuState extends GameState {
resumeBtn.classList.add("styledButton", "resumeGame");
elem.appendChild(resumeBtn);
this.trackClicks(deleteButton, () => this.deleteGame(games[i]));
this.trackClicks(downloadButton, () => this.downloadGame(games[i]));
this.trackClicks(resumeBtn, () => this.resumeGame(games[i]));
}
@@ -117,6 +231,28 @@ export class MainMenuState extends GameState {
});
}
/**
* @param {object} game
*/
deleteGame(game) {
const signals = this.dialogs.showWarning(
"Confirm Deletion",
"Are you sure you want to delete the game?",
["delete:bad", "cancel:good"]
);
signals.delete.add(() => {
this.app.savegameMgr.deleteSavegame(game).then(
() => {
this.renderSavegames();
},
err => {
this.dialogs.showWarning("Failed to delete", "Error: " + err);
}
);
});
}
/**
* @param {object} game
*/
@@ -138,6 +274,6 @@ export class MainMenuState extends GameState {
}
onLeave() {
// this.dialogs.cleanup();
this.dialogs.cleanup();
}
}

View File

@@ -67,10 +67,6 @@ export class PreloadState extends GameState {
.then(() => this.setStatus("Creating platform wrapper"))
.then(() => this.app.platformWrapper.initialize())
.then(() => this.setStatus("Initializing libraries"))
.then(() => this.app.analytics.initialize())
.then(() => this.app.gameAnalytics.initialize())
.then(() => this.setStatus("Initializing local storage"))
.then(() => {
const wrapper = this.app.platformWrapper;
@@ -95,6 +91,10 @@ export class PreloadState extends GameState {
return this.app.storage.initialize();
})
.then(() => this.setStatus("Initializing libraries"))
.then(() => this.app.analytics.initialize())
.then(() => this.app.gameAnalytics.initialize())
.then(() => this.setStatus("Initializing settings"))
.then(() => {
return this.app.settings.initialize();