Profectus-Demo/src/game/player.ts

113 lines
3.6 KiB
TypeScript
Raw Normal View History

import { Themes } from "@/data/themes";
import { PlayerData } from "@/typings/player";
import Decimal from "@/util/bignum";
import { isPlainObject } from "@/util/common";
import { reactive } from "vue";
import { ImportingStatus, MilestoneDisplay } from "./enums";
const state = reactive<PlayerData>({
id: "",
points: new Decimal(0),
oomps: new Decimal(0),
oompsMag: 0,
name: "",
tabs: [],
time: -1,
autosave: true,
offlineProd: true,
offlineTime: null,
timePlayed: new Decimal(0),
keepGoing: false,
lastTenTicks: [],
showTPS: true,
msDisplay: MilestoneDisplay.All,
hideChallenges: false,
theme: Themes.Paper,
subtabs: {},
minimized: {},
modID: "",
modVersion: "",
hasNaN: false,
NaNPath: [],
NaNReceiver: null,
importing: ImportingStatus.NotImporting,
saveToImport: "",
saveToExport: "",
layers: {}
});
const playerHandler: ProxyHandler<Record<string, any>> = {
get(target: Record<string, any>, key: string): any {
if (key === "__state" || key === "__path") {
return target[key];
}
if (target.__state[key] == undefined) {
return;
}
if (isPlainObject(target.__state[key]) && !(target.__state[key] instanceof Decimal)) {
if (target.__state[key] !== target[key]?.__state) {
const path = [...target.__path, key];
target[key] = new Proxy(
{ __state: target.__state[key], __path: path },
playerHandler
);
}
return target[key];
}
return target.__state[key];
},
set(
target: Record<string, any>,
property: string,
value: any,
receiver: ProxyConstructor
): boolean {
if (
!state.hasNaN &&
((typeof value === "number" && isNaN(value)) ||
(value instanceof Decimal &&
(isNaN(value.sign) || isNaN(value.layer) || isNaN(value.mag))))
) {
const currentValue = target.__state[property];
if (
!(
(typeof currentValue === "number" && isNaN(currentValue)) ||
(currentValue instanceof Decimal &&
(isNaN(currentValue.sign) ||
isNaN(currentValue.layer) ||
isNaN(currentValue.mag)))
)
) {
state.autosave = false;
state.hasNaN = true;
state.NaNPath = [...target.__path, property];
state.NaNReceiver = (receiver as unknown) as Record<string, unknown>;
console.error(
`Attempted to set NaN value`,
[...target.__path, property],
target.__state
);
throw "Attempted to set NaN value. See above for details";
}
}
target.__state[property] = value;
if (property === "points") {
if (target.__state.best != undefined) {
target.__state.best = Decimal.max(target.__state.best, value);
}
if (target.__state.total != undefined) {
const diff = Decimal.sub(value, target.__state.points);
if (diff.gt(0)) {
target.__state.total = target.__state.total.add(diff);
}
}
}
return true;
}
};
export default window.player = new Proxy(
{ __state: state, __path: ["player"] },
playerHandler
) as PlayerData;