2022-04-11 00:04:56 +00:00
|
|
|
import { OptionsFunc, getUniqueID, Replace } from "features/feature";
|
2022-03-04 03:39:48 +00:00
|
|
|
import { globalBus } from "game/events";
|
|
|
|
import { GenericLayer } from "game/layers";
|
2022-04-06 04:01:14 +00:00
|
|
|
import { DefaultValue, Persistent, persistent, PersistentState } from "game/persistence";
|
2022-03-11 20:02:41 +00:00
|
|
|
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>;
|
|
|
|
|
2022-02-27 19:49:34 +00:00
|
|
|
export function createReset<T extends ResetOptions>(
|
2022-04-11 00:04:56 +00:00
|
|
|
optionsFunc: OptionsFunc<T, Reset<T>, BaseReset>
|
2022-02-27 19:49:34 +00:00
|
|
|
): Reset<T> {
|
|
|
|
return createLazyProxy(() => {
|
2022-04-11 00:04:56 +00:00
|
|
|
const reset = optionsFunc();
|
2022-02-27 19:49:34 +00:00
|
|
|
reset.id = getUniqueID("reset-");
|
|
|
|
reset.type = ResetType;
|
2022-01-14 04:25:47 +00:00
|
|
|
|
2022-02-27 19:49:34 +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
|
|
|
}
|
|
|
|
}
|
2022-02-27 19:49:34 +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
|
|
|
};
|
|
|
|
|
2022-02-27 19:49:34 +00:00
|
|
|
processComputable(reset as T, "thingsToReset");
|
2022-01-14 04:25:47 +00:00
|
|
|
|
2022-02-27 19:49:34 +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> = {};
|
2022-04-06 04:01:14 +00:00
|
|
|
export function trackResetTime(layer: GenericLayer, reset: GenericReset): Persistent<Decimal> {
|
2022-01-14 04:25:47 +00:00
|
|
|
const resetTime = persistent<Decimal>(new Decimal(0));
|
2022-03-11 20:02:41 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|