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

[WIP] Implement painting, cutting, rotating achievements (to log only)

This commit is contained in:
Greg Considine 2021-02-22 16:02:52 -05:00
parent 261c7a4070
commit 85999f3f8b
5 changed files with 122 additions and 83 deletions

View File

@ -8,49 +8,29 @@ import { createLogger } from "../core/logging";
const logger = createLogger("achievement_manager"); const logger = createLogger("achievement_manager");
export class AchievementManager { export class AchievementManager {
static getId() {
return "AchievementManager";
}
constructor(root) { constructor(root) {
this.root = root; this.root = root;
this.achievements = null; this.achievements = this.root.app.achievements;
if (!this.root.app.achievements.hasAchievements()) { this.load()
logger.debug("Bypassing achievement set up");
// Set adhoc checks to reference a noop, ignore signals.
return;
}
this.init();
} }
init () { load () {
return this.root.app.achievements.load() return this.achievements.load()
.then(() => { .then(() => {
this.achievements = this.root.app.achievements.getAchievements(); if (!this.achievements.hasAchievements()) {
logger.log("Achievements disabled");
return;
}
return this.setChecks(); logger.log("There are", this.achievements.count, "achievements");
})
.catch(err => {
logger.error("Achievements failed to load", err);
}) })
} }
setChecks () { unlock (key) {
logger.debug("loaded", this.achievements); this.achievements.unlock(key);
// 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
} }
} }

View File

@ -4,6 +4,7 @@ import { enumColors } from "./colors";
import { ShapeItem } from "./items/shape_item"; import { ShapeItem } from "./items/shape_item";
import { GameRoot } from "./root"; import { GameRoot } from "./root";
import { enumSubShape, ShapeDefinition } from "./shape_definition"; import { enumSubShape, ShapeDefinition } from "./shape_definition";
import { ACHIEVEMENTS } from "../platform/achievements";
const logger = createLogger("shape_definition_manager"); const logger = createLogger("shape_definition_manager");
@ -96,6 +97,8 @@ export class ShapeDefinitionManager extends BasicSerializableObject {
const rightSide = definition.cloneFilteredByQuadrants([2, 3]); const rightSide = definition.cloneFilteredByQuadrants([2, 3]);
const leftSide = definition.cloneFilteredByQuadrants([0, 1]); const leftSide = definition.cloneFilteredByQuadrants([0, 1]);
this.root.achievementMgr.unlock(ACHIEVEMENTS.cutting);
return /** @type {[ShapeDefinition, ShapeDefinition]} */ (this.operationCache[key] = [ return /** @type {[ShapeDefinition, ShapeDefinition]} */ (this.operationCache[key] = [
this.registerOrReturnHandle(rightSide), this.registerOrReturnHandle(rightSide),
this.registerOrReturnHandle(leftSide), this.registerOrReturnHandle(leftSide),
@ -137,6 +140,8 @@ export class ShapeDefinitionManager extends BasicSerializableObject {
const rotated = definition.cloneRotateCW(); const rotated = definition.cloneRotateCW();
this.root.achievementMgr.unlock(ACHIEVEMENTS.rotating);
return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle(
rotated rotated
)); ));
@ -203,9 +208,14 @@ export class ShapeDefinitionManager extends BasicSerializableObject {
*/ */
shapeActionPaintWith(definition, color) { shapeActionPaintWith(definition, color) {
const key = "paint/" + definition.getHash() + "/" + color; const key = "paint/" + definition.getHash() + "/" + color;
logger.debug("shapePainted", definition, color);
if (this.operationCache[key]) { if (this.operationCache[key]) {
logger.debug("shapePaintedCache", definition, color);
return /** @type {ShapeDefinition} */ (this.operationCache[key]); return /** @type {ShapeDefinition} */ (this.operationCache[key]);
} }
this.root.achievementMgr.unlock(ACHIEVEMENTS.painting);
const colorized = definition.cloneAndPaintWith(color); const colorized = definition.cloneAndPaintWith(color);
return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle(
colorized colorized

View File

@ -2,6 +2,14 @@
import { Application } from "../application"; import { Application } from "../application";
/* typehints:end */ /* typehints:end */
export const ACHIEVEMENTS = {
painting: "painting",
cutting: "cutting",
rotating: "rotating",
stacking: "stacking",
blueprints: "blueprints",
}
export class AchievementsInterface { export class AchievementsInterface {
constructor(app) { constructor(app) {
/** @type {Application} */ /** @type {Application} */
@ -9,7 +17,30 @@ export class AchievementsInterface {
} }
/** /**
* Initializes the list of achievements * Load achievements into an initial state, bypassing unlocked and/or
* irrelevant achievements where possible.
*
* @params key
* @returns {Promise<void>}
*/
load() {
abstract;
return Promise.reject();
}
/**
* Call to unlock an achievement
* @params [key] - A property within the ACHIEVEMENTS enum or empty if
* bypassing.
* @returns {(undefined|Promise)}
*/
unlock(key) {
abstract;
return Promise.reject();
}
/**
* Initializes the list of achievements.
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
initialize() { initialize() {

View File

@ -1,76 +1,87 @@
import { AchievementsInterface } from "../achievements"; import { ACHIEVEMENTS, AchievementsInterface } from "../achievements";
import { globalConfig } from "../../core/config"; import { globalConfig } from "../../core/config";
import { createLogger } from "../../core/logging"; import { createLogger } from "../../core/logging";
import { newEmptyMap } from "../../core/utils";
//import { T } from "../../translations";
const logger = createLogger("achievements/default"); const logger = createLogger("achievements/steam");
// Include API id per key const IDS = {
export const ACHIEVEMENTS = { painting: "<id>",
painting: "painting" cutting: "<id>",
rotating: "<id>",
stacking: "<id>",
blueprints: "<id>"
} }
export class Achievements extends AchievementsInterface { export class Achievements extends AchievementsInterface {
initialize() { initialize() {
this.authTicket = null; this.map = new Map();
this.achievementNames = null; this.type = "Steam";
this.achievements = null; this.count = 0;
this.connected = false;
this.connectPromise = Promise.resolve();
if (globalConfig.debug.testAchievements) { logger.log("Initializing", this.type, "achievements");
return Promise.resolve();
for (let key in ACHIEVEMENTS) {
this.map[key] = new Map();
this.map[key].id = IDS[key];
this.map[key].key = key;
this.map[key].unlocked = false;
this.map[key].relevant = true;
this.count++;
} }
// Check for resolve in AchievementManager via load() to not block game state this.logOnly = globalConfig.debug.testAchievements;
// transition
this.connectPromise = this.fetchAuthTicket()
.then(() => this.fetchAchievementNames());
return Promise.resolve(); return Promise.resolve();
} }
fetchAuthTicket () {
return Promise.resolve();
}
fetchAchievementNames () {
return Promise.resolve();
}
load () { load () {
this.achievements = newEmptyMap(); // TODO: inspect safe file and update achievements
// Consider removing load since there's no async behavior anticipated
return Promise.resolve();
}
for (let key in ACHIEVEMENTS) { /**
this.achievements[key] = newEmptyMap(); * @param {string} key
this.achievements[key].unlocked = false; */
this.achievements[key].invalid = false; unlock (key) {
let achievement = this.map[key];
if (!achievement) {
logger.error("Achievement does not exist:", key);
return;
} }
return this.connectPromise if (!achievement.relevant) {
logger.debug("Achievement unlocked/irrelevant:", key);
return;
}
achievement.activate = achievement.activate || this.activate(achievement)
.then(() => { .then(() => {
// factor in game state, save data, then Steam data (if accessible) as achievement.unlocked = true;
// source of truth. achievement.relevant = false;
logger.log("Achievement unlocked:", key);
}) })
.catch(err => {
logger.error("Failed to unlock achievement", err);
})
.finally(() => {
achievement.activate = null;
})
} }
/** activate (achievement) {
* @param {string} key if (this.logOnly) {
*/ return Promise.resolve();
fetchAchievement (key) { }
return Promise.resolve();
}
/** return new Promise((resolve, reject) => {
* @param {string} key //TODO: Implement greenworks activate
*/
unlockAchievement (key) {
return Promise.resolve();
}
getAchievements() { return resolve();
return this.achievements; });
} }
hasAchievements() { hasAchievements() {

View File

@ -5,7 +5,14 @@ export class NoAchievements extends AchievementsInterface {
return Promise.resolve(); return Promise.resolve();
} }
load() {
return Promise.resolve();
}
hasAchievements() { hasAchievements() {
return false; return false;
} }
unlock() {
}
} }