chromatic-lattice/src/features/reset.ts

90 lines
2.9 KiB
TypeScript
Raw Normal View History

import { OptionsFunc, getUniqueID, Replace } from "features/feature";
2022-03-04 03:39:48 +00:00
import { globalBus } from "game/events";
import { BaseLayer } from "game/layers";
import { DefaultValue, Persistent, persistent, PersistentState } from "game/persistence";
import Decimal from "util/bignum";
2022-03-04 03:39:48 +00:00
import { Computable, GetComputableType, processComputable } from "util/computed";
import { createLazyProxy } from "util/proxies";
2022-01-14 04:25:47 +00:00
import { Unsubscribe } from "nanoevents";
2022-03-11 15:22:16 +00:00
import { isRef, unref } from "vue";
2022-01-14 04:25:47 +00:00
export const ResetType = Symbol("Reset");
export interface ResetOptions {
thingsToReset: Computable<Record<string, unknown>[]>;
onReset?: VoidFunction;
}
2022-03-09 01:40:51 +00:00
export interface BaseReset {
2022-01-14 04:25:47 +00:00
id: string;
reset: VoidFunction;
type: typeof ResetType;
}
export type Reset<T extends ResetOptions> = Replace<
T & BaseReset,
{
thingsToReset: GetComputableType<T["thingsToReset"]>;
}
>;
export type GenericReset = Reset<ResetOptions>;
export function createReset<T extends ResetOptions>(
optionsFunc: OptionsFunc<T, BaseReset, GenericReset>
): Reset<T> {
return createLazyProxy(() => {
const reset = optionsFunc();
reset.id = getUniqueID("reset-");
reset.type = ResetType;
2022-01-14 04:25:47 +00:00
reset.reset = function () {
const handleObject = (obj: unknown) => {
if (obj && typeof obj === "object") {
if (PersistentState in obj) {
(obj as Persistent)[PersistentState].value = (obj as Persistent)[
DefaultValue
];
} else if (!(obj instanceof Decimal) && !isRef(obj)) {
Object.values(obj).forEach(obj =>
handleObject(obj as Record<string, unknown>)
);
2022-01-14 04:25:47 +00:00
}
}
};
unref((reset as GenericReset).thingsToReset).forEach(handleObject);
globalBus.emit("reset", reset as GenericReset);
reset.onReset?.();
2022-01-14 04:25:47 +00:00
};
processComputable(reset as T, "thingsToReset");
2022-01-14 04:25:47 +00:00
return reset as unknown as Reset<T>;
});
2022-01-14 04:25:47 +00:00
}
2022-01-25 04:23:30 +00:00
const listeners: Record<string, Unsubscribe | undefined> = {};
export function trackResetTime(layer: BaseLayer, reset: GenericReset): Persistent<Decimal> {
2022-01-14 04:25:47 +00:00
const resetTime = persistent<Decimal>(new Decimal(0));
listeners[layer.id] = layer.on("preUpdate", diff => {
2022-01-14 04:25:47 +00:00
resetTime.value = Decimal.add(resetTime.value, diff);
});
globalBus.on("reset", currentReset => {
if (currentReset === reset) {
resetTime.value = new Decimal(0);
}
});
return resetTime;
}
globalBus.on("removeLayer", layer => {
// unsubscribe from preUpdate
listeners[layer.id]?.();
2022-01-25 04:23:30 +00:00
listeners[layer.id] = undefined;
2022-01-14 04:25:47 +00:00
});
2022-03-04 04:45:25 +00:00
declare module "game/events" {
2022-01-14 04:25:47 +00:00
interface GlobalEvents {
reset: (reset: GenericReset) => void;
}
}