mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-06-13 13:04:03 +00:00
[WIP] Add boilerplate for achievement implementation
This commit is contained in:
parent
14d09a7d52
commit
7c69331308
4
.gitignore
vendored
4
.gitignore
vendored
@ -50,3 +50,7 @@ tmp_standalone_files
|
||||
# Local config
|
||||
config.local.js
|
||||
.DS_Store
|
||||
|
||||
# Editor artifacts
|
||||
*.*.swp
|
||||
*.*.swo
|
||||
|
@ -12,6 +12,9 @@ import { getPlatformName, waitNextFrame } from "./core/utils";
|
||||
import { Vector } from "./core/vector";
|
||||
import { AdProviderInterface } from "./platform/ad_provider";
|
||||
import { NoAdProvider } from "./platform/ad_providers/no_ad_provider";
|
||||
import { AchievementsInterface } from "./platform/achievements";
|
||||
import { NoAchievements } from "./platform/achievements/no_achievements";
|
||||
import { Achievements } from "./platform/achievements/achievements";
|
||||
import { AnalyticsInterface } from "./platform/analytics";
|
||||
import { GoogleAnalyticsImpl } from "./platform/browser/google_analytics";
|
||||
import { SoundImplBrowser } from "./platform/browser/sound";
|
||||
@ -85,6 +88,9 @@ export class Application {
|
||||
/** @type {PlatformWrapperInterface} */
|
||||
this.platformWrapper = null;
|
||||
|
||||
/** @type {AchievementsInterface} */
|
||||
this.achievements = null;
|
||||
|
||||
/** @type {AdProviderInterface} */
|
||||
this.adProvider = null;
|
||||
|
||||
@ -137,6 +143,7 @@ export class Application {
|
||||
this.sound = new SoundImplBrowser(this);
|
||||
this.analytics = new GoogleAnalyticsImpl(this);
|
||||
this.gameAnalytics = new ShapezGameAnalytics(this);
|
||||
this.achievements = new NoAchievements(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,10 +3,10 @@ export default {
|
||||
/* dev:start */
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Quickly enters the game and skips the main menu - good for fast iterating
|
||||
// fastGameEnter: true,
|
||||
fastGameEnter: true,
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Skips any delays like transitions between states and such
|
||||
// noArtificialDelays: true,
|
||||
noArtificialDelays: true,
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Disables writing of savegames, useful for testing the same savegame over and over
|
||||
// disableSavegameWrite: true,
|
||||
@ -18,7 +18,7 @@ export default {
|
||||
// showAcceptorEjectors: true,
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Disables the music (Overrides any setting, can cause weird behaviour)
|
||||
// disableMusic: true,
|
||||
disableMusic: true,
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Do not render static map entities (=most buildings)
|
||||
// doNotRenderStatics: true,
|
||||
@ -59,6 +59,9 @@ export default {
|
||||
// Enables ads in the local build (normally they are deactivated there)
|
||||
// testAds: true,
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Allows unlocked achievements to be logged to console in the local build
|
||||
testAchievements: true,
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Disables the automatic switch to an overview when zooming out
|
||||
// disableMapOverview: true,
|
||||
// -----------------------------------------------------------------------------------
|
||||
|
56
src/js/game/achievement_manager.js
Normal file
56
src/js/game/achievement_manager.js
Normal file
@ -0,0 +1,56 @@
|
||||
/* typehints:start */
|
||||
import { GameRoot } from "./root";
|
||||
/* typehints:end */
|
||||
|
||||
import { globalConfig } from "../core/config";
|
||||
import { createLogger } from "../core/logging";
|
||||
|
||||
const logger = createLogger("achievement_manager");
|
||||
|
||||
export class AchievementManager {
|
||||
static getId() {
|
||||
return "AchievementManager";
|
||||
}
|
||||
|
||||
constructor(root) {
|
||||
this.root = root;
|
||||
this.achievements = null;
|
||||
|
||||
if (!this.root.app.achievements.hasAchievements()) {
|
||||
logger.debug("Bypassing achievement set up");
|
||||
// Set adhoc checks to reference a noop, ignore signals.
|
||||
return;
|
||||
}
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init () {
|
||||
return this.root.app.achievements.load()
|
||||
.then(() => {
|
||||
this.achievements = this.root.app.achievements.getAchievements();
|
||||
|
||||
return this.setChecks();
|
||||
})
|
||||
}
|
||||
|
||||
setChecks () {
|
||||
logger.debug("loaded", this.achievements);
|
||||
|
||||
// set checks on achievements
|
||||
|
||||
//this.root.signals.itemProduced.add(this.onItemProduced, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BaseItem} item
|
||||
*/
|
||||
onItemProduced(item) {
|
||||
logger.debug(item);
|
||||
}
|
||||
|
||||
// Have one check function per achievement
|
||||
isPainted () {
|
||||
return
|
||||
}
|
||||
}
|
@ -35,6 +35,7 @@ import { RegularGameMode } from "./modes/regular";
|
||||
import { ProductionAnalytics } from "./production_analytics";
|
||||
import { GameRoot } from "./root";
|
||||
import { ShapeDefinitionManager } from "./shape_definition_manager";
|
||||
import { AchievementManager } from "./achievement_manager";
|
||||
import { SoundProxy } from "./sound_proxy";
|
||||
import { GameTime } from "./time/game_time";
|
||||
|
||||
@ -118,6 +119,7 @@ export class GameCore {
|
||||
root.entityMgr = new EntityManager(root);
|
||||
root.systemMgr = new GameSystemManager(root);
|
||||
root.shapeDefinitionMgr = new ShapeDefinitionManager(root);
|
||||
root.achievementMgr = new AchievementManager(root);
|
||||
root.hubGoals = new HubGoals(root);
|
||||
root.productionAnalytics = new ProductionAnalytics(root);
|
||||
root.buffers = new BufferMaintainer(root);
|
||||
|
@ -8,6 +8,7 @@ import { createLogger } from "../core/logging";
|
||||
import { GameTime } from "./time/game_time";
|
||||
import { EntityManager } from "./entity_manager";
|
||||
import { GameSystemManager } from "./game_system_manager";
|
||||
import { AchievementManager } from "./achievement_manager";
|
||||
import { GameHUD } from "./hud/hud";
|
||||
import { MapView } from "./map_view";
|
||||
import { Camera } from "./camera";
|
||||
@ -119,6 +120,9 @@ export class GameRoot {
|
||||
/** @type {SoundProxy} */
|
||||
this.soundProxy = null;
|
||||
|
||||
/** @type {AchievementManager} */
|
||||
this.achievementMgr = null;
|
||||
|
||||
/** @type {ShapeDefinitionManager} */
|
||||
this.shapeDefinitionMgr = null;
|
||||
|
||||
|
28
src/js/platform/achievements.js
Normal file
28
src/js/platform/achievements.js
Normal file
@ -0,0 +1,28 @@
|
||||
/* typehints:start */
|
||||
import { Application } from "../application";
|
||||
/* typehints:end */
|
||||
|
||||
export class AchievementsInterface {
|
||||
constructor(app) {
|
||||
/** @type {Application} */
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the list of achievements
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
initialize() {
|
||||
abstract;
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if achievements are supported in the current build
|
||||
* @returns {boolean}
|
||||
*/
|
||||
hasAchievements() {
|
||||
abstract;
|
||||
return false;
|
||||
}
|
||||
}
|
79
src/js/platform/achievements/achievements.js
Normal file
79
src/js/platform/achievements/achievements.js
Normal file
@ -0,0 +1,79 @@
|
||||
import { AchievementsInterface } from "../achievements";
|
||||
import { globalConfig } from "../../core/config";
|
||||
import { createLogger } from "../../core/logging";
|
||||
import { newEmptyMap } from "../../core/utils";
|
||||
//import { T } from "../../translations";
|
||||
|
||||
const logger = createLogger("achievements/default");
|
||||
|
||||
// Include API id per key
|
||||
export const ACHIEVEMENTS = {
|
||||
painting: "painting"
|
||||
}
|
||||
|
||||
export class Achievements extends AchievementsInterface {
|
||||
initialize() {
|
||||
this.authTicket = null;
|
||||
this.achievementNames = null;
|
||||
this.achievements = null;
|
||||
this.connected = false;
|
||||
this.connectPromise = Promise.resolve();
|
||||
|
||||
if (globalConfig.debug.testAchievements) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Check for resolve in AchievementManager via load() to not block game state
|
||||
// transition
|
||||
this.connectPromise = this.fetchAuthTicket()
|
||||
.then(() => this.fetchAchievementNames());
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
fetchAuthTicket () {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
fetchAchievementNames () {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
load () {
|
||||
this.achievements = newEmptyMap();
|
||||
|
||||
for (let key in ACHIEVEMENTS) {
|
||||
this.achievements[key] = newEmptyMap();
|
||||
this.achievements[key].unlocked = false;
|
||||
this.achievements[key].invalid = false;
|
||||
}
|
||||
|
||||
return this.connectPromise
|
||||
.then(() => {
|
||||
// factor in game state, save data, then Steam data (if accessible) as
|
||||
// source of truth.
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} key
|
||||
*/
|
||||
fetchAchievement (key) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} key
|
||||
*/
|
||||
unlockAchievement (key) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
getAchievements() {
|
||||
return this.achievements;
|
||||
}
|
||||
|
||||
hasAchievements() {
|
||||
return true;
|
||||
}
|
||||
}
|
11
src/js/platform/achievements/no_achievements.js
Normal file
11
src/js/platform/achievements/no_achievements.js
Normal file
@ -0,0 +1,11 @@
|
||||
import { AchievementsInterface } from "../achievements";
|
||||
|
||||
export class NoAchievements extends AchievementsInterface {
|
||||
initialize() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
hasAchievements() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import { queryParamOptions } from "../../core/query_parameters";
|
||||
import { clamp } from "../../core/utils";
|
||||
import { GamedistributionAdProvider } from "../ad_providers/gamedistribution";
|
||||
import { NoAdProvider } from "../ad_providers/no_ad_provider";
|
||||
import { Achievements } from "../achievements/achievements";
|
||||
import { PlatformWrapperInterface } from "../wrapper";
|
||||
import { StorageImplBrowser } from "./storage";
|
||||
import { StorageImplBrowserIndexedDB } from "./storage_indexed_db";
|
||||
@ -71,6 +72,7 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface {
|
||||
|
||||
return this.detectStorageImplementation()
|
||||
.then(() => this.initializeAdProvider())
|
||||
.then(() => this.initializeAchievements())
|
||||
.then(() => super.initialize());
|
||||
}
|
||||
|
||||
@ -196,6 +198,16 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface {
|
||||
});
|
||||
}
|
||||
|
||||
initializeAchievements() {
|
||||
if (G_IS_STANDALONE || (G_IS_DEV && globalConfig.debug.testAchievements)) {
|
||||
this.app.achievements = new Achievements(this.app);
|
||||
return this.app.achievements.initialize();
|
||||
}
|
||||
|
||||
logger.log("Achievements are not supported in this environment");
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
exitApp() {
|
||||
// Can not exit app
|
||||
}
|
||||
|
@ -1207,6 +1207,11 @@ demo:
|
||||
|
||||
settingNotAvailable: Not available in the demo.
|
||||
|
||||
achievements:
|
||||
painting:
|
||||
displayName: Painting
|
||||
description: Paint a shape
|
||||
|
||||
tips:
|
||||
- The hub will accept any input, not just the current shape!
|
||||
- Make sure your factories are modular - it will pay out!
|
||||
|
35
yarn.lock
35
yarn.lock
@ -5103,14 +5103,6 @@ levn@^0.4.1:
|
||||
prelude-ls "^1.2.1"
|
||||
type-check "~0.4.0"
|
||||
|
||||
line-column@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/line-column/-/line-column-1.0.2.tgz#d25af2936b6f4849172b312e4792d1d987bc34a2"
|
||||
integrity sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI=
|
||||
dependencies:
|
||||
isarray "^1.0.0"
|
||||
isobject "^2.0.0"
|
||||
|
||||
load-bmfont@^1.3.1, load-bmfont@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.0.tgz#75f17070b14a8c785fe7f5bee2e6fd4f98093b6b"
|
||||
@ -5619,10 +5611,10 @@ nan@^2.12.1:
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
|
||||
integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
|
||||
|
||||
nanoid@^3.1.12:
|
||||
version "3.1.12"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654"
|
||||
integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==
|
||||
nanoid@^3.1.20:
|
||||
version "3.1.20"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
|
||||
integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==
|
||||
|
||||
nanomatch@^1.2.9:
|
||||
version "1.2.13"
|
||||
@ -6927,6 +6919,15 @@ postcss-zindex@^4.0.1:
|
||||
postcss "^7.0.0"
|
||||
uniqs "^2.0.0"
|
||||
|
||||
postcss@>=5.0.0:
|
||||
version "8.2.6"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.6.tgz#5d69a974543b45f87e464bc4c3e392a97d6be9fe"
|
||||
integrity sha512-xpB8qYxgPuly166AGlpRjUdEYtmOWx2iCwGmrv4vqZL9YPVviDVPZPRXxnXr6xPZOdxQ9lp3ZBFCRgWJ7LE3Sg==
|
||||
dependencies:
|
||||
colorette "^1.2.1"
|
||||
nanoid "^3.1.20"
|
||||
source-map "^0.6.1"
|
||||
|
||||
postcss@^5.0.2:
|
||||
version "5.2.18"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5"
|
||||
@ -6955,16 +6956,6 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2
|
||||
source-map "^0.6.1"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
postcss@^8.1.1:
|
||||
version "8.1.1"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.1.tgz#c3a287dd10e4f6c84cb3791052b96a5d859c9389"
|
||||
integrity sha512-9DGLSsjooH3kSNjTZUOt2eIj2ZTW0VI2PZ/3My+8TC7KIbH2OKwUlISfDsf63EP4aiRUt3XkEWMWvyJHvJelEg==
|
||||
dependencies:
|
||||
colorette "^1.2.1"
|
||||
line-column "^1.0.2"
|
||||
nanoid "^3.1.12"
|
||||
source-map "^0.6.1"
|
||||
|
||||
prelude-ls@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
||||
|
Loading…
Reference in New Issue
Block a user