1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-06-13 13:04:03 +00:00

Add play time achievements

This commit is contained in:
Greg Considine 2021-03-04 15:24:34 -05:00
parent f827e1ba2f
commit 311a620527
6 changed files with 82 additions and 9 deletions

View File

@ -40,6 +40,9 @@ export const globalConfig = {
assetsSharpness: 1.5,
shapesSharpness: 1.4,
// Achievements
achievementSliceDuration: 30, // Seconds
// Production analytics
statisticsGraphDpi: 2.5,
statisticsGraphSlices: 100,

View File

@ -2,6 +2,7 @@
import { GameRoot } from "./root";
/* typehints:end */
import { globalConfig } from "../core/config";
import { createLogger } from "../core/logging";
import { ACHIEVEMENTS } from "../platform/achievement_provider";
@ -12,6 +13,8 @@ export class AchievementProxy {
constructor(root) {
this.root = root;
this.provider = this.root.app.achievementProvider;
this.lastSlice = 0;
this.disabled = true;
if (!this.provider.hasAchievements()) {
return;
@ -21,13 +24,39 @@ export class AchievementProxy {
}
onLoad() {
if (this.provider.hasLoaded()) {
this.disabled = false;
return;
}
this.provider.onLoad(this.root)
.then(() => {
logger.log("Listening for unlocked achievements");
this.root.signals.achievementUnlocked.dispatch(ACHIEVEMENTS.darkMode);
this.startSlice();
this.disabled = false;
})
.catch(err => {
this.disabled = true;
logger.error("Ignoring achievement signals", err);
})
}
startSlice() {
this.lastSlice = this.root.time.now();
this.root.signals.achievementUnlocked.dispatch(ACHIEVEMENTS.play1h, this.lastSlice);
this.root.signals.achievementUnlocked.dispatch(ACHIEVEMENTS.play10h, this.lastSlice);
this.root.signals.achievementUnlocked.dispatch(ACHIEVEMENTS.play20h, this.lastSlice);
}
update() {
if (this.disabled) {
return;
}
if (this.root.time.now() - this.lastSlice > globalConfig.achievementSliceDuration) {
this.startSlice();
}
}
}

View File

@ -151,6 +151,9 @@ export class GameCore {
// Update analytics
root.productionAnalytics.update();
// Check achievements
root.achievementProxy.update();
}
});
}
@ -276,6 +279,9 @@ export class GameCore {
// Update analytics
root.productionAnalytics.update();
// Check achievements
root.achievementProxy.update();
}
// Update automatic save after everything finished

View File

@ -18,6 +18,9 @@ export const ACHIEVEMENTS = {
paintShape: "paintShape",
place5000Wires: "place5000Wires",
placeBlueprint: "placeBlueprint",
play1h: "play1h",
play10h: "play10h",
play20h: "play20h",
produceLogo: "produceLogo",
produceMsLogo: "produceMsLogo",
produceRocket: "produceRocket",
@ -30,6 +33,9 @@ export const ACHIEVEMENTS = {
};
const DARK_MODE = "dark";
const HOUR_1 = 3600; // Seconds
const HOUR_10 = HOUR_1 * 10;
const HOUR_20 = HOUR_1 * 20;
const SHAPE_BLUEPRINT = "CbCbCbRb:CwCwCwCw";
const SHAPE_LOGO = "RuCw--Cw:----Ru--";
const SHAPE_MS_LOGO = "RgRyRbRr";
@ -60,6 +66,12 @@ export class AchievementProviderInterface {
return Promise.reject();
}
/** @returns {boolean} */
hasLoaded() {
abstract;
return false;
}
/**
* Call to activate an achievement with the provider
* @param {string} key - Maps to an Achievement
@ -114,7 +126,6 @@ export class AchievementCollection {
constructor(activate) {
this.map = new Map();
this.activate = activate;
this.initialized = false;
this.createAndSet(ACHIEVEMENTS.belt500Tiles, {
isValid: this.isBelt500TilesValid,
@ -142,6 +153,9 @@ export class AchievementCollection {
this.createAndSet(ACHIEVEMENTS.placeBlueprint, {
isValid: this.isPlaceBlueprintValid,
});
this.createAndSet(ACHIEVEMENTS.play1h, this.createTimeOptions(HOUR_1));
this.createAndSet(ACHIEVEMENTS.play10h, this.createTimeOptions(HOUR_10));
this.createAndSet(ACHIEVEMENTS.play20h, this.createTimeOptions(HOUR_20));
this.createAndSet(ACHIEVEMENTS.produceLogo, this.createShapeOptions(SHAPE_LOGO));
this.createAndSet(ACHIEVEMENTS.produceRocket, this.createShapeOptions(SHAPE_ROCKET));
this.createAndSet(ACHIEVEMENTS.produceMsLogo, this.createShapeOptions(SHAPE_MS_LOGO));
@ -182,8 +196,6 @@ export class AchievementCollection {
if (!this.hasDefaultReceivers()) {
this.root.signals.achievementUnlocked.remove(this.unlock);
}
this.initialized = true;
}
/**
@ -290,6 +302,13 @@ export class AchievementCollection {
}
}
createTimeOptions (duration) {
return {
isRelevant: () => this.root.time.now() < duration,
isValid: () => this.root.time.now() >= duration,
}
}
/**
* @param {string} key
* @param {Entity} entity

View File

@ -5,6 +5,10 @@ export class NoAchievementProvider extends AchievementProviderInterface {
return false;
}
hasLoaded() {
return false;
}
initialize() {
return Promise.resolve();
}

View File

@ -21,6 +21,9 @@ const ACHIEVEMENT_IDS = {
[ACHIEVEMENTS.paintShape]: "paint_shape",
[ACHIEVEMENTS.place5000Wires]: "place_5000_wires",
[ACHIEVEMENTS.placeBlueprint]: "place_blueprint",
[ACHIEVEMENTS.play1h]: "play_1h",
[ACHIEVEMENTS.play10h]: "play_10h",
[ACHIEVEMENTS.play20h]: "play_20h",
[ACHIEVEMENTS.produceLogo]: "produce_logo",
[ACHIEVEMENTS.produceMsLogo]: "produce_ms_logo",
[ACHIEVEMENTS.produceRocket]: "produce_rocket",
@ -38,26 +41,34 @@ export class SteamAchievementProvider extends AchievementProviderInterface {
super(app);
this.initialized = false;
this.loaded = false;
this.collection = new AchievementCollection(this.activate.bind(this));
logger.log("Collection created with", this.collection.map.size, "achievements");
}
/**
* @returns {boolean}
*/
/** @returns {boolean} */
hasAchievements() {
return true;
}
/** @param {GameRoot} root */
/** @returns {boolean} */
hasLoaded() {
return this.loaded;
}
/**
* @param {GameRoot} root
* @returns {Promise<void>}
*/
onLoad(root) {
if (this.collection.initialized) {
if (this.loaded) {
return Promise.resolve();
}
try {
this.collection.initialize(root);
this.loaded = true;
logger.log(this.collection.map.size, "achievements are relevant and initialized");
return Promise.resolve();
} catch (err) {
@ -66,6 +77,7 @@ export class SteamAchievementProvider extends AchievementProviderInterface {
}
}
/** @returns {Promise<void>} */
initialize() {
if (!G_IS_STANDALONE) {
logger.warn("Steam unavailable. Achievements won't sync.");
@ -87,7 +99,7 @@ export class SteamAchievementProvider extends AchievementProviderInterface {
}
/**
* @param {string} key - An ACHIEVEMENTS key
* @param {string} key
* @returns {Promise<void>}
*/
activate(key) {