2020-09-19 15:55:36 +00:00
|
|
|
import { createLogger } from "../core/logging";
|
|
|
|
import { BasicSerializableObject } from "../savegame/serialization";
|
|
|
|
import { enumColors } from "./colors";
|
|
|
|
import { ShapeItem } from "./items/shape_item";
|
|
|
|
import { GameRoot } from "./root";
|
|
|
|
import { enumSubShape, ShapeDefinition } from "./shape_definition";
|
Achievements (#1087)
* [WIP] Add boilerplate for achievement implementation
* Add config.local.template.js and rm cached copy of config.local.js
* [WIP] Implement painting, cutting, rotating achievements (to log only)
* [WIP] Refactor achievements, jsdoc fixes, add npm script
- Refactor achievements to make use of Signals
- Move implemented achievement interfaces to appropriate
platform folders (SteamAchievements in currently in use
in browser wrapper for testing)
- Fix invalid jsdocs
- Add dev-standalone script to package.json scripts
* Add steam/greenworks IPC calls and optional private-artifact dependency
* Include private artifacts in standalone builds
* Uncomment appid include
* [WIP] Add steam overlay fix, add hash to artifact dependency
* Update electron, greenworks. Add task to add local config if not present
* Add more achievements, refactor achievement code
* Add receiver flexibility and more achievements
- Add check to see if necessary to create achievement and add receiver
- Add remove receiver functionality when achievement is unlocked
* Add achievements and accommodations for switching states
- Fix startup code to avoid clobbering achievements on state switch
- Add a few more achievements
* Add achievements, ids. Update names, keys for consistency
* Add play time achievements
* [WIP] Add more achievements
* Add more achievements. Add bulk achievement check signal
* [WIP] Add achievements. Start savefile migration
* Add achievements. Add savefile migration
* Remove superfluous achievement stat
* Update lock files, fix merge conflict
2021-03-10 06:33:39 +00:00
|
|
|
import { ACHIEVEMENTS } from "../platform/achievement_provider";
|
2020-09-19 15:55:36 +00:00
|
|
|
|
|
|
|
const logger = createLogger("shape_definition_manager");
|
|
|
|
|
|
|
|
export class ShapeDefinitionManager extends BasicSerializableObject {
|
|
|
|
static getId() {
|
|
|
|
return "ShapeDefinitionManager";
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param {GameRoot} root
|
|
|
|
*/
|
|
|
|
constructor(root) {
|
|
|
|
super();
|
|
|
|
this.root = root;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Store a cache from key -> definition
|
|
|
|
* @type {Object<string, ShapeDefinition>}
|
|
|
|
*/
|
|
|
|
this.shapeKeyToDefinition = {};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Store a cache from key -> item
|
|
|
|
*/
|
|
|
|
this.shapeKeyToItem = {};
|
|
|
|
|
2020-10-11 06:18:55 +00:00
|
|
|
// Caches operations in the form of 'operation/def1[/def2]'
|
2020-09-19 15:55:36 +00:00
|
|
|
/** @type {Object.<string, Array<ShapeDefinition>|ShapeDefinition>} */
|
|
|
|
this.operationCache = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a shape instance from a given short key
|
|
|
|
* @param {string} hash
|
|
|
|
* @returns {ShapeDefinition}
|
|
|
|
*/
|
|
|
|
getShapeFromShortKey(hash) {
|
|
|
|
const cached = this.shapeKeyToDefinition[hash];
|
|
|
|
if (cached) {
|
|
|
|
return cached;
|
|
|
|
}
|
|
|
|
return (this.shapeKeyToDefinition[hash] = ShapeDefinition.fromShortKey(hash));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a item instance from a given short key
|
|
|
|
* @param {string} hash
|
|
|
|
* @returns {ShapeItem}
|
|
|
|
*/
|
|
|
|
getShapeItemFromShortKey(hash) {
|
|
|
|
const cached = this.shapeKeyToItem[hash];
|
|
|
|
if (cached) {
|
|
|
|
return cached;
|
|
|
|
}
|
|
|
|
const definition = this.getShapeFromShortKey(hash);
|
|
|
|
return (this.shapeKeyToItem[hash] = new ShapeItem(definition));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a shape item for a given definition
|
|
|
|
* @param {ShapeDefinition} definition
|
|
|
|
* @returns {ShapeItem}
|
|
|
|
*/
|
|
|
|
getShapeItemFromDefinition(definition) {
|
|
|
|
return this.getShapeItemFromShortKey(definition.getHash());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Registers a new shape definition
|
|
|
|
* @param {ShapeDefinition} definition
|
|
|
|
*/
|
|
|
|
registerShapeDefinition(definition) {
|
|
|
|
const id = definition.getHash();
|
|
|
|
assert(!this.shapeKeyToDefinition[id], "Shape Definition " + id + " already exists");
|
|
|
|
this.shapeKeyToDefinition[id] = definition;
|
|
|
|
// logger.log("Registered shape with key", id);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a definition for splitting a shape definition in two halfs
|
|
|
|
* @param {ShapeDefinition} definition
|
|
|
|
* @returns {[ShapeDefinition, ShapeDefinition]}
|
|
|
|
*/
|
|
|
|
shapeActionCutHalf(definition) {
|
2020-10-11 06:18:55 +00:00
|
|
|
const key = "cut/" + definition.getHash();
|
2020-09-19 15:55:36 +00:00
|
|
|
if (this.operationCache[key]) {
|
|
|
|
return /** @type {[ShapeDefinition, ShapeDefinition]} */ (this.operationCache[key]);
|
|
|
|
}
|
|
|
|
const rightSide = definition.cloneFilteredByQuadrants([2, 3]);
|
|
|
|
const leftSide = definition.cloneFilteredByQuadrants([0, 1]);
|
|
|
|
|
2021-03-11 05:11:29 +00:00
|
|
|
this.root.signals.achievementCheck.dispatch(ACHIEVEMENTS.cutShape, null);
|
Achievements (#1087)
* [WIP] Add boilerplate for achievement implementation
* Add config.local.template.js and rm cached copy of config.local.js
* [WIP] Implement painting, cutting, rotating achievements (to log only)
* [WIP] Refactor achievements, jsdoc fixes, add npm script
- Refactor achievements to make use of Signals
- Move implemented achievement interfaces to appropriate
platform folders (SteamAchievements in currently in use
in browser wrapper for testing)
- Fix invalid jsdocs
- Add dev-standalone script to package.json scripts
* Add steam/greenworks IPC calls and optional private-artifact dependency
* Include private artifacts in standalone builds
* Uncomment appid include
* [WIP] Add steam overlay fix, add hash to artifact dependency
* Update electron, greenworks. Add task to add local config if not present
* Add more achievements, refactor achievement code
* Add receiver flexibility and more achievements
- Add check to see if necessary to create achievement and add receiver
- Add remove receiver functionality when achievement is unlocked
* Add achievements and accommodations for switching states
- Fix startup code to avoid clobbering achievements on state switch
- Add a few more achievements
* Add achievements, ids. Update names, keys for consistency
* Add play time achievements
* [WIP] Add more achievements
* Add more achievements. Add bulk achievement check signal
* [WIP] Add achievements. Start savefile migration
* Add achievements. Add savefile migration
* Remove superfluous achievement stat
* Update lock files, fix merge conflict
2021-03-10 06:33:39 +00:00
|
|
|
|
2020-09-19 15:55:36 +00:00
|
|
|
return /** @type {[ShapeDefinition, ShapeDefinition]} */ (this.operationCache[key] = [
|
|
|
|
this.registerOrReturnHandle(rightSide),
|
|
|
|
this.registerOrReturnHandle(leftSide),
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a definition for splitting a shape definition in four quads
|
|
|
|
* @param {ShapeDefinition} definition
|
|
|
|
* @returns {[ShapeDefinition, ShapeDefinition, ShapeDefinition, ShapeDefinition]}
|
|
|
|
*/
|
|
|
|
shapeActionCutQuad(definition) {
|
2020-10-11 06:18:55 +00:00
|
|
|
const key = "cut-quad/" + definition.getHash();
|
2020-09-19 15:55:36 +00:00
|
|
|
if (this.operationCache[key]) {
|
|
|
|
return /** @type {[ShapeDefinition, ShapeDefinition, ShapeDefinition, ShapeDefinition]} */ (this
|
|
|
|
.operationCache[key]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return /** @type {[ShapeDefinition, ShapeDefinition, ShapeDefinition, ShapeDefinition]} */ (this.operationCache[
|
|
|
|
key
|
|
|
|
] = [
|
|
|
|
this.registerOrReturnHandle(definition.cloneFilteredByQuadrants([0])),
|
|
|
|
this.registerOrReturnHandle(definition.cloneFilteredByQuadrants([1])),
|
|
|
|
this.registerOrReturnHandle(definition.cloneFilteredByQuadrants([2])),
|
|
|
|
this.registerOrReturnHandle(definition.cloneFilteredByQuadrants([3])),
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a definition for rotating a shape clockwise
|
|
|
|
* @param {ShapeDefinition} definition
|
|
|
|
* @returns {ShapeDefinition}
|
|
|
|
*/
|
|
|
|
shapeActionRotateCW(definition) {
|
2020-10-11 06:18:55 +00:00
|
|
|
const key = "rotate-cw/" + definition.getHash();
|
2020-09-19 15:55:36 +00:00
|
|
|
if (this.operationCache[key]) {
|
|
|
|
return /** @type {ShapeDefinition} */ (this.operationCache[key]);
|
|
|
|
}
|
|
|
|
|
|
|
|
const rotated = definition.cloneRotateCW();
|
|
|
|
|
2021-03-11 05:11:29 +00:00
|
|
|
this.root.signals.achievementCheck.dispatch(ACHIEVEMENTS.rotateShape, null);
|
Achievements (#1087)
* [WIP] Add boilerplate for achievement implementation
* Add config.local.template.js and rm cached copy of config.local.js
* [WIP] Implement painting, cutting, rotating achievements (to log only)
* [WIP] Refactor achievements, jsdoc fixes, add npm script
- Refactor achievements to make use of Signals
- Move implemented achievement interfaces to appropriate
platform folders (SteamAchievements in currently in use
in browser wrapper for testing)
- Fix invalid jsdocs
- Add dev-standalone script to package.json scripts
* Add steam/greenworks IPC calls and optional private-artifact dependency
* Include private artifacts in standalone builds
* Uncomment appid include
* [WIP] Add steam overlay fix, add hash to artifact dependency
* Update electron, greenworks. Add task to add local config if not present
* Add more achievements, refactor achievement code
* Add receiver flexibility and more achievements
- Add check to see if necessary to create achievement and add receiver
- Add remove receiver functionality when achievement is unlocked
* Add achievements and accommodations for switching states
- Fix startup code to avoid clobbering achievements on state switch
- Add a few more achievements
* Add achievements, ids. Update names, keys for consistency
* Add play time achievements
* [WIP] Add more achievements
* Add more achievements. Add bulk achievement check signal
* [WIP] Add achievements. Start savefile migration
* Add achievements. Add savefile migration
* Remove superfluous achievement stat
* Update lock files, fix merge conflict
2021-03-10 06:33:39 +00:00
|
|
|
|
2020-09-19 15:55:36 +00:00
|
|
|
return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle(
|
|
|
|
rotated
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a definition for rotating a shape counter clockwise
|
|
|
|
* @param {ShapeDefinition} definition
|
|
|
|
* @returns {ShapeDefinition}
|
|
|
|
*/
|
|
|
|
shapeActionRotateCCW(definition) {
|
2020-10-11 06:18:55 +00:00
|
|
|
const key = "rotate-ccw/" + definition.getHash();
|
2020-09-19 15:55:36 +00:00
|
|
|
if (this.operationCache[key]) {
|
|
|
|
return /** @type {ShapeDefinition} */ (this.operationCache[key]);
|
|
|
|
}
|
|
|
|
|
|
|
|
const rotated = definition.cloneRotateCCW();
|
|
|
|
|
|
|
|
return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle(
|
|
|
|
rotated
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a definition for rotating a shape FL
|
|
|
|
* @param {ShapeDefinition} definition
|
|
|
|
* @returns {ShapeDefinition}
|
|
|
|
*/
|
|
|
|
shapeActionRotate180(definition) {
|
2020-10-11 06:18:55 +00:00
|
|
|
const key = "rotate-fl/" + definition.getHash();
|
2020-09-19 15:55:36 +00:00
|
|
|
if (this.operationCache[key]) {
|
|
|
|
return /** @type {ShapeDefinition} */ (this.operationCache[key]);
|
|
|
|
}
|
|
|
|
|
|
|
|
const rotated = definition.cloneRotate180();
|
|
|
|
|
|
|
|
return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle(
|
|
|
|
rotated
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a definition for stacking the upper definition onto the lower one
|
|
|
|
* @param {ShapeDefinition} lowerDefinition
|
|
|
|
* @param {ShapeDefinition} upperDefinition
|
|
|
|
* @returns {ShapeDefinition}
|
|
|
|
*/
|
|
|
|
shapeActionStack(lowerDefinition, upperDefinition) {
|
2020-10-11 06:18:55 +00:00
|
|
|
const key = "stack/" + lowerDefinition.getHash() + "/" + upperDefinition.getHash();
|
2020-09-19 15:55:36 +00:00
|
|
|
if (this.operationCache[key]) {
|
|
|
|
return /** @type {ShapeDefinition} */ (this.operationCache[key]);
|
|
|
|
}
|
Achievements (#1087)
* [WIP] Add boilerplate for achievement implementation
* Add config.local.template.js and rm cached copy of config.local.js
* [WIP] Implement painting, cutting, rotating achievements (to log only)
* [WIP] Refactor achievements, jsdoc fixes, add npm script
- Refactor achievements to make use of Signals
- Move implemented achievement interfaces to appropriate
platform folders (SteamAchievements in currently in use
in browser wrapper for testing)
- Fix invalid jsdocs
- Add dev-standalone script to package.json scripts
* Add steam/greenworks IPC calls and optional private-artifact dependency
* Include private artifacts in standalone builds
* Uncomment appid include
* [WIP] Add steam overlay fix, add hash to artifact dependency
* Update electron, greenworks. Add task to add local config if not present
* Add more achievements, refactor achievement code
* Add receiver flexibility and more achievements
- Add check to see if necessary to create achievement and add receiver
- Add remove receiver functionality when achievement is unlocked
* Add achievements and accommodations for switching states
- Fix startup code to avoid clobbering achievements on state switch
- Add a few more achievements
* Add achievements, ids. Update names, keys for consistency
* Add play time achievements
* [WIP] Add more achievements
* Add more achievements. Add bulk achievement check signal
* [WIP] Add achievements. Start savefile migration
* Add achievements. Add savefile migration
* Remove superfluous achievement stat
* Update lock files, fix merge conflict
2021-03-10 06:33:39 +00:00
|
|
|
|
2021-03-11 05:11:29 +00:00
|
|
|
this.root.signals.achievementCheck.dispatch(ACHIEVEMENTS.stackShape, null);
|
Achievements (#1087)
* [WIP] Add boilerplate for achievement implementation
* Add config.local.template.js and rm cached copy of config.local.js
* [WIP] Implement painting, cutting, rotating achievements (to log only)
* [WIP] Refactor achievements, jsdoc fixes, add npm script
- Refactor achievements to make use of Signals
- Move implemented achievement interfaces to appropriate
platform folders (SteamAchievements in currently in use
in browser wrapper for testing)
- Fix invalid jsdocs
- Add dev-standalone script to package.json scripts
* Add steam/greenworks IPC calls and optional private-artifact dependency
* Include private artifacts in standalone builds
* Uncomment appid include
* [WIP] Add steam overlay fix, add hash to artifact dependency
* Update electron, greenworks. Add task to add local config if not present
* Add more achievements, refactor achievement code
* Add receiver flexibility and more achievements
- Add check to see if necessary to create achievement and add receiver
- Add remove receiver functionality when achievement is unlocked
* Add achievements and accommodations for switching states
- Fix startup code to avoid clobbering achievements on state switch
- Add a few more achievements
* Add achievements, ids. Update names, keys for consistency
* Add play time achievements
* [WIP] Add more achievements
* Add more achievements. Add bulk achievement check signal
* [WIP] Add achievements. Start savefile migration
* Add achievements. Add savefile migration
* Remove superfluous achievement stat
* Update lock files, fix merge conflict
2021-03-10 06:33:39 +00:00
|
|
|
|
2020-09-19 15:55:36 +00:00
|
|
|
const stacked = lowerDefinition.cloneAndStackWith(upperDefinition);
|
|
|
|
return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle(
|
|
|
|
stacked
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a definition for painting it with the given color
|
|
|
|
* @param {ShapeDefinition} definition
|
|
|
|
* @param {enumColors} color
|
|
|
|
* @returns {ShapeDefinition}
|
|
|
|
*/
|
|
|
|
shapeActionPaintWith(definition, color) {
|
2020-10-11 06:18:55 +00:00
|
|
|
const key = "paint/" + definition.getHash() + "/" + color;
|
2020-09-19 15:55:36 +00:00
|
|
|
if (this.operationCache[key]) {
|
|
|
|
return /** @type {ShapeDefinition} */ (this.operationCache[key]);
|
|
|
|
}
|
Achievements (#1087)
* [WIP] Add boilerplate for achievement implementation
* Add config.local.template.js and rm cached copy of config.local.js
* [WIP] Implement painting, cutting, rotating achievements (to log only)
* [WIP] Refactor achievements, jsdoc fixes, add npm script
- Refactor achievements to make use of Signals
- Move implemented achievement interfaces to appropriate
platform folders (SteamAchievements in currently in use
in browser wrapper for testing)
- Fix invalid jsdocs
- Add dev-standalone script to package.json scripts
* Add steam/greenworks IPC calls and optional private-artifact dependency
* Include private artifacts in standalone builds
* Uncomment appid include
* [WIP] Add steam overlay fix, add hash to artifact dependency
* Update electron, greenworks. Add task to add local config if not present
* Add more achievements, refactor achievement code
* Add receiver flexibility and more achievements
- Add check to see if necessary to create achievement and add receiver
- Add remove receiver functionality when achievement is unlocked
* Add achievements and accommodations for switching states
- Fix startup code to avoid clobbering achievements on state switch
- Add a few more achievements
* Add achievements, ids. Update names, keys for consistency
* Add play time achievements
* [WIP] Add more achievements
* Add more achievements. Add bulk achievement check signal
* [WIP] Add achievements. Start savefile migration
* Add achievements. Add savefile migration
* Remove superfluous achievement stat
* Update lock files, fix merge conflict
2021-03-10 06:33:39 +00:00
|
|
|
|
2021-03-11 05:11:29 +00:00
|
|
|
this.root.signals.achievementCheck.dispatch(ACHIEVEMENTS.paintShape, null);
|
Achievements (#1087)
* [WIP] Add boilerplate for achievement implementation
* Add config.local.template.js and rm cached copy of config.local.js
* [WIP] Implement painting, cutting, rotating achievements (to log only)
* [WIP] Refactor achievements, jsdoc fixes, add npm script
- Refactor achievements to make use of Signals
- Move implemented achievement interfaces to appropriate
platform folders (SteamAchievements in currently in use
in browser wrapper for testing)
- Fix invalid jsdocs
- Add dev-standalone script to package.json scripts
* Add steam/greenworks IPC calls and optional private-artifact dependency
* Include private artifacts in standalone builds
* Uncomment appid include
* [WIP] Add steam overlay fix, add hash to artifact dependency
* Update electron, greenworks. Add task to add local config if not present
* Add more achievements, refactor achievement code
* Add receiver flexibility and more achievements
- Add check to see if necessary to create achievement and add receiver
- Add remove receiver functionality when achievement is unlocked
* Add achievements and accommodations for switching states
- Fix startup code to avoid clobbering achievements on state switch
- Add a few more achievements
* Add achievements, ids. Update names, keys for consistency
* Add play time achievements
* [WIP] Add more achievements
* Add more achievements. Add bulk achievement check signal
* [WIP] Add achievements. Start savefile migration
* Add achievements. Add savefile migration
* Remove superfluous achievement stat
* Update lock files, fix merge conflict
2021-03-10 06:33:39 +00:00
|
|
|
|
2020-09-19 15:55:36 +00:00
|
|
|
const colorized = definition.cloneAndPaintWith(color);
|
|
|
|
return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle(
|
|
|
|
colorized
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a definition for painting it with the 4 colors
|
|
|
|
* @param {ShapeDefinition} definition
|
|
|
|
* @param {[enumColors, enumColors, enumColors, enumColors]} colors
|
|
|
|
* @returns {ShapeDefinition}
|
|
|
|
*/
|
|
|
|
shapeActionPaintWith4Colors(definition, colors) {
|
2020-10-11 06:18:55 +00:00
|
|
|
const key = "paint4/" + definition.getHash() + "/" + colors.join(",");
|
2020-09-19 15:55:36 +00:00
|
|
|
if (this.operationCache[key]) {
|
|
|
|
return /** @type {ShapeDefinition} */ (this.operationCache[key]);
|
|
|
|
}
|
|
|
|
const colorized = definition.cloneAndPaintWith4Colors(colors);
|
|
|
|
return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle(
|
|
|
|
colorized
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if we already have cached this definition, and if so throws it away and returns the already
|
|
|
|
* cached variant
|
|
|
|
* @param {ShapeDefinition} definition
|
|
|
|
*/
|
|
|
|
registerOrReturnHandle(definition) {
|
|
|
|
const id = definition.getHash();
|
|
|
|
if (this.shapeKeyToDefinition[id]) {
|
|
|
|
return this.shapeKeyToDefinition[id];
|
|
|
|
}
|
|
|
|
this.shapeKeyToDefinition[id] = definition;
|
|
|
|
// logger.log("Registered shape with key (2)", id);
|
|
|
|
return definition;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param {[enumSubShape, enumSubShape, enumSubShape, enumSubShape]} subShapes
|
|
|
|
* @returns {ShapeDefinition}
|
|
|
|
*/
|
|
|
|
getDefinitionFromSimpleShapes(subShapes, color = enumColors.uncolored) {
|
|
|
|
const shapeLayer = /** @type {import("./shape_definition").ShapeLayer} */ (subShapes.map(
|
|
|
|
subShape => ({ subShape, color })
|
|
|
|
));
|
|
|
|
|
|
|
|
return this.registerOrReturnHandle(new ShapeDefinition({ layers: [shapeLayer] }));
|
|
|
|
}
|
|
|
|
}
|