Add type hints to signals

pull/33/head
tobspr 4 years ago
parent ca3f4ff02a
commit cf5d776270

@ -8,7 +8,7 @@ export class Signal {
/** /**
* Adds a new signal listener * Adds a new signal listener
* @param {object} receiver * @param {function} receiver
* @param {object} scope * @param {object} scope
*/ */
add(receiver, scope = null) { add(receiver, scope = null) {
@ -40,7 +40,7 @@ export class Signal {
/** /**
* Removes a receiver * Removes a receiver
* @param {object} receiver * @param {function} receiver
*/ */
remove(receiver) { remove(receiver) {
let index = null; let index = null;

@ -90,18 +90,6 @@ export class BaseHUDPart {
// Helpers // Helpers
/**
* Calls closeMethod if an overlay is opened
* @param {function=} closeMethod
*/
closeOnOverlayOpen(closeMethod = null) {
this.root.hud.signals.overlayOpened.add(overlay => {
if (overlay !== this) {
(closeMethod || this.close).call(this);
}
}, this);
}
/** /**
* Helper method to construct a new click detector * Helper method to construct a new click detector
* @param {Element} element The element to listen on * @param {Element} element The element to listen on

@ -16,6 +16,7 @@ import { IS_MOBILE } from "../../core/config";
import { HUDMassSelector } from "./parts/mass_selector"; import { HUDMassSelector } from "./parts/mass_selector";
import { HUDVignetteOverlay } from "./parts/vignette_overlay"; import { HUDVignetteOverlay } from "./parts/vignette_overlay";
import { HUDStatistics } from "./parts/statistics"; import { HUDStatistics } from "./parts/statistics";
import { MetaBuilding } from "../meta_building";
export class GameHUD { export class GameHUD {
/** /**
@ -29,10 +30,6 @@ export class GameHUD {
* Initializes the hud parts * Initializes the hud parts
*/ */
initialize() { initialize() {
this.signals = {
overlayOpened: new Signal(/* overlay */),
};
this.parts = { this.parts = {
processingOverlay: new HUDProcessingOverlay(this.root), processingOverlay: new HUDProcessingOverlay(this.root),
@ -54,7 +51,7 @@ export class GameHUD {
}; };
this.signals = { this.signals = {
selectedPlacementBuildingChanged: new Signal(/* metaBuilding|null */), selectedPlacementBuildingChanged: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()),
}; };
if (!IS_MOBILE) { if (!IS_MOBILE) {

@ -1,6 +1,8 @@
import { GameRoot } from "./root"; import { GameRoot } from "./root";
import { ShapeDefinition } from "./shape_definition"; import { ShapeDefinition } from "./shape_definition";
import { globalConfig } from "../core/config"; import { globalConfig } from "../core/config";
import { BaseItem } from "./base_item";
import { ShapeItem } from "./items/shape_item";
/** @enum {string} */ /** @enum {string} */
export const enumAnalyticsDataSource = { export const enumAnalyticsDataSource = {
@ -27,7 +29,7 @@ export class ProductionAnalytics {
} }
this.root.signals.shapeDelivered.add(this.onShapeDelivered, this); this.root.signals.shapeDelivered.add(this.onShapeDelivered, this);
this.root.signals.shapeProduced.add(this.onShapeProduced, this); this.root.signals.itemProduced.add(this.onItemProduced, this);
this.lastAnalyticsSlice = 0; this.lastAnalyticsSlice = 0;
} }
@ -42,12 +44,15 @@ export class ProductionAnalytics {
} }
/** /**
* @param {ShapeDefinition} definition * @param {BaseItem} item
*/ */
onShapeProduced(definition) { onItemProduced(item) {
const key = definition.getHash(); if (item instanceof ShapeItem) {
const entry = this.history[enumAnalyticsDataSource.produced]; const definition = item.definition;
entry[entry.length - 1][key] = (entry[entry.length - 1][key] || 0) + 1; const key = definition.getHash();
const entry = this.history[enumAnalyticsDataSource.produced];
entry[entry.length - 1][key] = (entry[entry.length - 1][key] || 0) + 1;
}
} }
/** /**

@ -28,6 +28,9 @@ import { PerlinNoise } from "../core/perlin_noise";
import { HubGoals } from "./hub_goals"; import { HubGoals } from "./hub_goals";
import { BufferMaintainer } from "../core/buffer_maintainer"; import { BufferMaintainer } from "../core/buffer_maintainer";
import { ProductionAnalytics } from "./production_analytics"; import { ProductionAnalytics } from "./production_analytics";
import { Entity } from "./entity";
import { ShapeDefinition } from "./shape_definition";
import { BaseItem } from "./base_item";
/* typehints:end */ /* typehints:end */
const logger = createLogger("game/root"); const logger = createLogger("game/root");
@ -131,32 +134,32 @@ export class GameRoot {
this.signals = { this.signals = {
// Entities // Entities
entityAdded: new Signal(/* entity */), entityAdded: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
entityGotNewComponent: new Signal(/* entity */), entityGotNewComponent: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
entityQueuedForDestroy: new Signal(/* entity */), entityQueuedForDestroy: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
entityDestroyed: new Signal(/* entity */), entityDestroyed: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
// Global // Global
resized: new Signal(/* w, h */), // Game got resized, resized: /** @type {TypedSignal<[number, number]>} */ (new Signal()),
readyToRender: new Signal(), readyToRender: /** @type {TypedSignal<[]>} */ (new Signal()),
aboutToDestruct: new Signal(), aboutToDestruct: /** @type {TypedSignal<[]>} */ new Signal(),
// Game Hooks // Game Hooks
gameSaved: new Signal(), // Game got saved gameSaved: /** @type {TypedSignal<[]>} */ (new Signal()), // Game got saved
gameRestored: new Signal(), // Game got restored gameRestored: /** @type {TypedSignal<[]>} */ (new Signal()), // Game got restored
gameOver: new Signal(), // Game over gameOver: /** @type {TypedSignal<[]>} */ (new Signal()), // Game over
storyGoalCompleted: new Signal(/* level, reward */), storyGoalCompleted: /** @type {TypedSignal<[number, string]>} */ (new Signal()),
upgradePurchased: new Signal(), upgradePurchased: /** @type {TypedSignal<[string]>} */ (new Signal()),
// Called right after game is initialized // Called right after game is initialized
postLoadHook: new Signal(), postLoadHook: /** @type {TypedSignal<[]>} */ (new Signal()),
// Can be used to trigger an async task // Can be used to trigger an async task
performAsync: new Signal(), performAsync: /** @type {TypedSignal<[function]>} */ (new Signal()),
shapeDelivered: new Signal(/* definition */), shapeDelivered: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()),
shapeProduced: new Signal(/* definition */), itemProduced: /** @type {TypedSignal<[BaseItem]>} */ (new Signal()),
}; };
// RNG's // RNG's

@ -157,11 +157,9 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
item: new ShapeItem(cutDefinition1), item: new ShapeItem(cutDefinition1),
requiredSlot: 0, requiredSlot: 0,
}); });
this.root.signals.shapeProduced.dispatch(cutDefinition1);
} }
if (!cutDefinition2.isEntirelyEmpty()) { if (!cutDefinition2.isEntirelyEmpty()) {
this.root.signals.shapeProduced.dispatch(cutDefinition2);
outItems.push({ outItems.push({
item: new ShapeItem(cutDefinition2), item: new ShapeItem(cutDefinition2),
requiredSlot: 1, requiredSlot: 1,
@ -178,7 +176,6 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
const inputDefinition = inputItem.definition; const inputDefinition = inputItem.definition;
const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotateCW(inputDefinition); const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotateCW(inputDefinition);
this.root.signals.shapeProduced.dispatch(rotatedDefinition);
outItems.push({ outItems.push({
item: new ShapeItem(rotatedDefinition), item: new ShapeItem(rotatedDefinition),
}); });
@ -200,7 +197,6 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
lowerItem.definition, lowerItem.definition,
upperItem.definition upperItem.definition
); );
this.root.signals.shapeProduced.dispatch(stackedDefinition);
outItems.push({ outItems.push({
item: new ShapeItem(stackedDefinition), item: new ShapeItem(stackedDefinition),
}); });
@ -253,7 +249,6 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
colorItem.color colorItem.color
); );
this.root.signals.shapeProduced.dispatch(colorizedDefinition);
outItems.push({ outItems.push({
item: new ShapeItem(colorizedDefinition), item: new ShapeItem(colorizedDefinition),
}); });
@ -277,6 +272,11 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
assertAlways(false, "Unkown item processor type: " + processorComp.type); assertAlways(false, "Unkown item processor type: " + processorComp.type);
} }
// Track produced items
for (let i = 0; i < outItems.length; ++i) {
this.root.signals.itemProduced.dispatch(outItems[i].item);
}
processorComp.itemsToEject = outItems; processorComp.itemsToEject = outItems;
} }

@ -38,9 +38,7 @@ export class MinerSystem extends GameSystemWithFilter {
} }
// Analytics hook // Analytics hook
if (lowerLayerItem instanceof ShapeItem) { this.root.signals.itemProduced.dispatch(lowerLayerItem);
this.root.signals.shapeProduced.dispatch(lowerLayerItem.definition);
}
// Try actually ejecting // Try actually ejecting
if (!ejectComp.tryEject(0, lowerLayerItem)) { if (!ejectComp.tryEject(0, lowerLayerItem)) {

@ -193,3 +193,14 @@ declare class TypedTrackedState<T> {
setSilent(value: any): void; setSilent(value: any): void;
get(): T; get(): T;
} }
declare const STOP_PROPAGATION = "stop_propagation";
declare interface TypedSignal<T extends Array<any>> {
add(receiver: (...args: T) => typeof STOP_PROPAGATION | void, scope?: object);
remove(receiver: (...args: T) => typeof STOP_PROPAGATION | void);
dispatch(...args: T): typeof STOP_PROPAGATION | void;
removeAll();
}

@ -92,7 +92,7 @@ export class InGameState extends GameState {
getThemeMusic() { getThemeMusic() {
// set later // set later
return MUSIC.gameBg; return MUSIC.mainMenu;
} }
onBeforeExit() { onBeforeExit() {
@ -115,7 +115,7 @@ export class InGameState extends GameState {
} }
getPauseOnFocusLost() { getPauseOnFocusLost() {
return !this.isMultiplayer(); return false;
} }
getHasUnloadConfirmation() { getHasUnloadConfirmation() {
@ -407,7 +407,6 @@ export class InGameState extends GameState {
return; return;
if (!this.savegame || !this.savegame.isSaveable()) { if (!this.savegame || !this.savegame.isSaveable()) {
// Can not save in multiplayer
return Promise.resolve(); return Promise.resolve();
} }

Loading…
Cancel
Save