1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2024-10-27 20:34:29 +00:00

Unlock all levels when having a legacy savegame

This commit is contained in:
tobspr 2020-10-07 15:02:27 +02:00
parent fa27d1681f
commit 7dccc1a844
5 changed files with 533 additions and 416 deletions

View File

@ -1,5 +1,3 @@
import { queryParamOptions } from "./query_parameters";
export const IS_DEBUG = export const IS_DEBUG =
G_IS_DEV && G_IS_DEV &&
typeof window !== "undefined" && typeof window !== "undefined" &&
@ -9,6 +7,8 @@ export const IS_DEBUG =
export const SUPPORT_TOUCH = false; export const SUPPORT_TOUCH = false;
export const IS_MAC = navigator.platform.toLowerCase().indexOf("mac") >= 0;
const smoothCanvas = true; const smoothCanvas = true;
export const THIRDPARTY_URLS = { export const THIRDPARTY_URLS = {

View File

@ -1,4 +1,5 @@
import { Application } from "../application"; import { Application } from "../application";
import { IS_MAC } from "./config";
import { ExplainedResult } from "./explained_result"; import { ExplainedResult } from "./explained_result";
import { queryParamOptions } from "./query_parameters"; import { queryParamOptions } from "./query_parameters";
import { ReadWriteProxy } from "./read_write_proxy"; import { ReadWriteProxy } from "./read_write_proxy";
@ -9,6 +10,8 @@ export class RestrictionManager extends ReadWriteProxy {
*/ */
constructor(app) { constructor(app) {
super(app, "restriction-flags.bin"); super(app, "restriction-flags.bin");
this.currentData = this.getDefaultData();
} }
// -- RW Proxy Impl // -- RW Proxy Impl
@ -24,6 +27,7 @@ export class RestrictionManager extends ReadWriteProxy {
*/ */
getDefaultData() { getDefaultData() {
return { return {
version: this.getCurrentVersion(),
savegameV1119Imported: false, savegameV1119Imported: false,
}; };
} }
@ -42,17 +46,53 @@ export class RestrictionManager extends ReadWriteProxy {
return ExplainedResult.good(); return ExplainedResult.good();
} }
initialize() {
return this.readAsync().then(() => {
if (this.currentData.savegameV1119Imported) {
console.warn("Levelunlock is granted to current user due to past savegame");
}
});
}
// -- End RW Proxy Impl // -- End RW Proxy Impl
/**
* Checks if there are any savegames from the 1.1.19 version
*/
onHasLegacySavegamesChanged(has119Savegames = false) {
if (has119Savegames && !this.currentData.savegameV1119Imported) {
this.currentData.savegameV1119Imported = true;
console.warn("Current user now has access to all levels due to 1119 savegame");
return this.writeAsync();
}
return Promise.resolve();
}
/** /**
* Returns if the app is currently running as the limited version * Returns if the app is currently running as the limited version
* @returns {boolean} * @returns {boolean}
*/ */
isLimitedVersion() { isLimitedVersion() {
return queryParamOptions.fullVersion if (IS_MAC) {
? false // On mac, the full version is always active
: (!G_IS_DEV && !G_IS_STANDALONE) || return false;
(typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0); }
if (G_IS_STANDALONE) {
// Standalone is never limited
return false;
}
if (queryParamOptions.fullVersion) {
// Full version is activated via flag
return false;
}
if (G_IS_DEV) {
return typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0;
}
return true;
} }
/** /**
@ -94,4 +134,20 @@ export class RestrictionManager extends ReadWriteProxy {
getHasExtendedSettings() { getHasExtendedSettings() {
return !this.isLimitedVersion(); return !this.isLimitedVersion();
} }
/**
* Returns if all upgrades are available
* @returns {boolean}
*/
getHasExtendedUpgrades() {
return !this.isLimitedVersion() || this.currentData.savegameV1119Imported;
}
/**
* Returns if all levels & freeplay is available
* @returns {boolean}
*/
getHasExtendedLevelsAndFreeplay() {
return !this.isLimitedVersion() || this.currentData.savegameV1119Imported;
}
} }

View File

@ -1,4 +1,3 @@
import { IS_DEMO } from "../../core/config";
import { findNiceIntegerValue } from "../../core/utils"; import { findNiceIntegerValue } from "../../core/utils";
import { GameMode } from "../game_mode"; import { GameMode } from "../game_mode";
import { ShapeDefinition } from "../shape_definition"; import { ShapeDefinition } from "../shape_definition";
@ -9,12 +8,17 @@ const finalGameShape = "RuCw--Cw:----Ru--";
const preparementShape = "CpRpCp--:SwSwSwSw"; const preparementShape = "CpRpCp--:SwSwSwSw";
const blueprintShape = "CbCbCbRb:CwCwCwCw"; const blueprintShape = "CbCbCbRb:CwCwCwCw";
// Tiers need % of the previous tier as requirement too
const tierGrowth = 2.5;
/**
* Generates all upgrades
* @returns {Object<string, import("../game_mode").UpgradeTiers>} */
function generateUpgrades(limitedVersion = false) {
const fixedImprovements = [0.5, 0.5, 1, 1, 2, 1, 1]; const fixedImprovements = [0.5, 0.5, 1, 1, 2, 1, 1];
const numEndgameUpgrades = limitedVersion ? 0 : 1000 - fixedImprovements.length - 1;
// @FIXME @TODO function generateInfiniteUnlocks() {
const numEndgameUpgrades = !IS_DEMO ? 20 - fixedImprovements.length - 1 : 0;
function generateEndgameUpgrades() {
return new Array(numEndgameUpgrades).fill(null).map((_, i) => ({ return new Array(numEndgameUpgrades).fill(null).map((_, i) => ({
required: [ required: [
{ shape: preparementShape, amount: 30000 + i * 10000 }, { shape: preparementShape, amount: 30000 + i * 10000 },
@ -25,12 +29,12 @@ function generateEndgameUpgrades() {
})); }));
} }
// Fill in endgame upgrades
for (let i = 0; i < numEndgameUpgrades; ++i) { for (let i = 0; i < numEndgameUpgrades; ++i) {
fixedImprovements.push(0.1); fixedImprovements.push(0.1);
} }
/** @type {Object<string, import("../game_mode").UpgradeTiers>} */ const upgrades = {
const cachedUpgrades = {
belt: [ belt: [
{ {
required: [{ shape: "CuCuCuCu", amount: 60 }], required: [{ shape: "CuCuCuCu", amount: 60 }],
@ -58,7 +62,7 @@ const cachedUpgrades = {
], ],
excludePrevious: true, excludePrevious: true,
}, },
...generateEndgameUpgrades(), ...generateInfiniteUnlocks(),
], ],
miner: [ miner: [
@ -88,7 +92,7 @@ const cachedUpgrades = {
], ],
excludePrevious: true, excludePrevious: true,
}, },
...generateEndgameUpgrades(), ...generateInfiniteUnlocks(),
], ],
processors: [ processors: [
@ -118,7 +122,7 @@ const cachedUpgrades = {
], ],
excludePrevious: true, excludePrevious: true,
}, },
...generateEndgameUpgrades(), ...generateInfiniteUnlocks(),
], ],
painting: [ painting: [
@ -148,16 +152,13 @@ const cachedUpgrades = {
], ],
excludePrevious: true, excludePrevious: true,
}, },
...generateEndgameUpgrades(), ...generateInfiniteUnlocks(),
], ],
}; };
// Tiers need % of the previous tier as requirement too
const tierGrowth = 2.5;
// Automatically generate tier levels // Automatically generate tier levels
for (const upgradeId in cachedUpgrades) { for (const upgradeId in upgrades) {
const upgradeTiers = cachedUpgrades[upgradeId]; const upgradeTiers = upgrades[upgradeId];
let currentTierRequirements = []; let currentTierRequirements = [];
for (let i = 0; i < upgradeTiers.length; ++i) { for (let i = 0; i < upgradeTiers.length; ++i) {
@ -188,8 +189,8 @@ for (const upgradeId in cachedUpgrades) {
// VALIDATE // VALIDATE
if (G_IS_DEV) { if (G_IS_DEV) {
for (const upgradeId in cachedUpgrades) { for (const upgradeId in upgrades) {
cachedUpgrades[upgradeId].forEach(tier => { upgrades[upgradeId].forEach(tier => {
tier.required.forEach(({ shape }) => { tier.required.forEach(({ shape }) => {
try { try {
ShapeDefinition.fromShortKey(shape); ShapeDefinition.fromShortKey(shape);
@ -201,6 +202,14 @@ if (G_IS_DEV) {
} }
} }
return upgrades;
}
/**
* Generates the level definitions
* @param {boolean} limitedVersion
*/
export function generateLevelDefinitions(limitedVersion = false) {
const levelDefinitions = [ const levelDefinitions = [
// 1 // 1
// Circle // Circle
@ -304,7 +313,7 @@ const levelDefinitions = [
}, },
// DEMO STOPS HERE // DEMO STOPS HERE
...(IS_DEMO ...(limitedVersion
? [ ? [
{ {
shape: "RpRpRpRp:CwCwCwCw", shape: "RpRpRpRp:CwCwCwCw",
@ -427,13 +436,28 @@ if (G_IS_DEV) {
}); });
} }
return levelDefinitions;
}
const fullVersionUpgrades = generateUpgrades(false);
const demoVersionUpgrades = generateUpgrades(true);
const fullVersionLevels = generateLevelDefinitions(false);
const demoVersionLevels = generateLevelDefinitions(true);
export class RegularGameMode extends GameMode { export class RegularGameMode extends GameMode {
constructor(root) { constructor(root) {
super(root); super(root);
} }
getUpgrades() { getUpgrades() {
return cachedUpgrades; return this.root.app.restrictionMgr.getHasExtendedUpgrades()
? fullVersionUpgrades
: demoVersionUpgrades;
}
getIsFreeplayAvailable() {
return this.root.app.restrictionMgr.getHasExtendedLevelsAndFreeplay();
} }
getBlueprintShapeKey() { getBlueprintShapeKey() {
@ -441,6 +465,8 @@ export class RegularGameMode extends GameMode {
} }
getLevelDefinitions() { getLevelDefinitions() {
return levelDefinitions; return this.root.app.restrictionMgr.getHasExtendedLevelsAndFreeplay()
? fullVersionLevels
: demoVersionLevels;
} }
} }

View File

@ -89,6 +89,14 @@ export class SavegameManager extends ReadWriteProxy {
return new Savegame(this.app, { internalId, metaDataRef: metadata }); return new Savegame(this.app, { internalId, metaDataRef: metadata });
} }
/**
* Returns if this manager has any savegame of a 1.1.19 version, which
* enables all levels
*/
getHasAnyLegacySavegames() {
return this.currentData.savegames.some(savegame => savegame.version === 1005 || savegame.level > 14);
}
/** /**
* Deletes a savegame * Deletes a savegame
* @param {SavegameMetadata} game * @param {SavegameMetadata} game
@ -142,7 +150,9 @@ export class SavegameManager extends ReadWriteProxy {
}); });
this.currentData.savegames.push(metaData); this.currentData.savegames.push(metaData);
this.sortSavegames();
// Notice: This is async and happening in the background
this.updateAfterSavegamesChanged();
return new Savegame(this.app, { return new Savegame(this.app, {
internalId: id, internalId: id,
@ -150,8 +160,16 @@ export class SavegameManager extends ReadWriteProxy {
}); });
} }
/**
* Attempts to import a savegame
* @param {object} data
*/
importSavegame(data) { importSavegame(data) {
const savegame = this.createNewSavegame(); const savegame = this.createNewSavegame();
// Track legacy savegames
const isOldSavegame = data.version < 1006;
const migrationResult = savegame.migrate(data); const migrationResult = savegame.migrate(data);
if (migrationResult.isBad()) { if (migrationResult.isBad()) {
return Promise.reject("Failed to migrate: " + migrationResult.reason); return Promise.reject("Failed to migrate: " + migrationResult.reason);
@ -163,7 +181,19 @@ export class SavegameManager extends ReadWriteProxy {
return Promise.reject("Verification failed: " + verification.result); return Promise.reject("Verification failed: " + verification.result);
} }
return savegame.writeSavegameAndMetadata().then(() => this.sortSavegames()); return savegame
.writeSavegameAndMetadata()
.then(() => this.updateAfterSavegamesChanged())
.then(() => this.app.restrictionMgr.onHasLegacySavegamesChanged(isOldSavegame));
}
/**
* Hook after the savegames got changed
*/
updateAfterSavegamesChanged() {
return this.sortSavegames()
.then(() => this.writeAsync())
.then(() => this.app.restrictionMgr.onHasLegacySavegamesChanged(this.getHasAnyLegacySavegames()));
} }
/** /**
@ -212,7 +242,7 @@ export class SavegameManager extends ReadWriteProxy {
if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) { if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) {
return Promise.resolve(); return Promise.resolve();
} }
return this.sortSavegames().then(() => this.writeAsync()); return this.updateAfterSavegamesChanged();
}); });
} }
} }

View File

@ -145,6 +145,11 @@ export class PreloadState extends GameState {
this.app.backgroundResourceLoader.startLoading(); this.app.backgroundResourceLoader.startLoading();
}) })
.then(() => this.setStatus("Initializing restrictions"))
.then(() => {
return this.app.restrictionMgr.initialize();
})
.then(() => this.setStatus("Initializing savegame")) .then(() => this.setStatus("Initializing savegame"))
.then(() => { .then(() => {
return this.app.savegameMgr.initialize().catch(err => { return this.app.savegameMgr.initialize().catch(err => {