forked from profectus/Profectus
Make lazy proxies and options funcs pass along base object
This commit is contained in:
parent
0f2cc45a7e
commit
632da10aca
23 changed files with 77 additions and 60 deletions
|
@ -140,8 +140,10 @@ export function createAchievement<T extends AchievementOptions>(
|
|||
optionsFunc?: OptionsFunc<T, BaseAchievement, GenericAchievement>
|
||||
): Achievement<T> {
|
||||
const earned = persistent<boolean>(false, false);
|
||||
return createLazyProxy(() => {
|
||||
const achievement = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>);
|
||||
return createLazyProxy(feature => {
|
||||
const achievement =
|
||||
optionsFunc?.call(feature, feature) ??
|
||||
({} as ReturnType<NonNullable<typeof optionsFunc>>);
|
||||
achievement.id = getUniqueID("achievement-");
|
||||
achievement.type = AchievementType;
|
||||
achievement[Component] = AchievementComponent as GenericComponent;
|
||||
|
|
|
@ -105,8 +105,10 @@ export function createAction<T extends ActionOptions>(
|
|||
optionsFunc?: OptionsFunc<T, BaseAction, GenericAction>
|
||||
): Action<T> {
|
||||
const progress = persistent<DecimalSource>(0);
|
||||
return createLazyProxy(() => {
|
||||
const action = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>);
|
||||
return createLazyProxy(feature => {
|
||||
const action =
|
||||
optionsFunc?.call(feature, feature) ??
|
||||
({} as ReturnType<NonNullable<typeof optionsFunc>>);
|
||||
action.id = getUniqueID("action-");
|
||||
action.type = ActionType;
|
||||
action[Component] = ClickableComponent as GenericComponent;
|
||||
|
|
|
@ -103,8 +103,8 @@ export type GenericBar = Replace<
|
|||
export function createBar<T extends BarOptions>(
|
||||
optionsFunc: OptionsFunc<T, BaseBar, GenericBar>
|
||||
): Bar<T> {
|
||||
return createLazyProxy(() => {
|
||||
const bar = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const bar = optionsFunc.call(feature, feature);
|
||||
bar.id = getUniqueID("bar-");
|
||||
bar.type = BarType;
|
||||
bar[Component] = BarComponent as GenericComponent;
|
||||
|
|
|
@ -297,8 +297,8 @@ export function createBoard<T extends BoardOptions>(
|
|||
false
|
||||
);
|
||||
|
||||
return createLazyProxy(() => {
|
||||
const board = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const board = optionsFunc.call(feature, feature);
|
||||
board.id = getUniqueID("board-");
|
||||
board.type = BoardType;
|
||||
board[Component] = BoardComponent as GenericComponent;
|
||||
|
|
|
@ -152,8 +152,8 @@ export function createChallenge<T extends ChallengeOptions>(
|
|||
): Challenge<T> {
|
||||
const completions = persistent(0);
|
||||
const active = persistent(false, false);
|
||||
return createLazyProxy(() => {
|
||||
const challenge = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const challenge = optionsFunc.call(feature, feature);
|
||||
|
||||
challenge.id = getUniqueID("challenge-");
|
||||
challenge.type = ChallengeType;
|
||||
|
|
|
@ -97,8 +97,10 @@ export type GenericClickable = Replace<
|
|||
export function createClickable<T extends ClickableOptions>(
|
||||
optionsFunc?: OptionsFunc<T, BaseClickable, GenericClickable>
|
||||
): Clickable<T> {
|
||||
return createLazyProxy(() => {
|
||||
const clickable = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>);
|
||||
return createLazyProxy(feature => {
|
||||
const clickable =
|
||||
optionsFunc?.call(feature, feature) ??
|
||||
({} as ReturnType<NonNullable<typeof optionsFunc>>);
|
||||
clickable.id = getUniqueID("clickable-");
|
||||
clickable.type = ClickableType;
|
||||
clickable[Component] = ClickableComponent as GenericComponent;
|
||||
|
|
|
@ -125,8 +125,8 @@ export type GenericConversion = Replace<
|
|||
export function createConversion<T extends ConversionOptions>(
|
||||
optionsFunc: OptionsFunc<T, BaseConversion, GenericConversion>
|
||||
): Conversion<T> {
|
||||
return createLazyProxy(() => {
|
||||
const conversion = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const conversion = optionsFunc.call(feature, feature);
|
||||
|
||||
(conversion as GenericConversion).formula = conversion.formula(
|
||||
Formula.variable(conversion.baseResource)
|
||||
|
@ -211,8 +211,8 @@ export function createCumulativeConversion<S extends ConversionOptions>(
|
|||
export function createIndependentConversion<S extends ConversionOptions>(
|
||||
optionsFunc: OptionsFunc<S, BaseConversion, GenericConversion>
|
||||
): Conversion<S> {
|
||||
return createConversion(() => {
|
||||
const conversion: S = optionsFunc();
|
||||
return createConversion(feature => {
|
||||
const conversion: S = optionsFunc.call(feature, feature);
|
||||
|
||||
setDefault(conversion, "buyMax", false);
|
||||
|
||||
|
|
|
@ -42,9 +42,7 @@ export type Replace<T, S> = S & Omit<T, keyof S>;
|
|||
* with "this" bound to what the type will eventually be processed into.
|
||||
* Intended for making lazily evaluated objects.
|
||||
*/
|
||||
export type OptionsFunc<T, R = Record<string, unknown>, S = R> = () => T &
|
||||
Partial<R> &
|
||||
ThisType<T & S>;
|
||||
export type OptionsFunc<T, R = unknown, S = R> = (obj: R) => T & Partial<R> & ThisType<T & S>;
|
||||
|
||||
let id = 0;
|
||||
/**
|
||||
|
|
|
@ -307,8 +307,8 @@ export function createGrid<T extends GridOptions>(
|
|||
optionsFunc: OptionsFunc<T, BaseGrid, GenericGrid>
|
||||
): Grid<T> {
|
||||
const cellState = persistent<Record<string | number, State>>({}, false);
|
||||
return createLazyProxy(() => {
|
||||
const grid = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const grid = optionsFunc.call(feature, feature);
|
||||
grid.id = getUniqueID("grid-");
|
||||
grid[Component] = GridComponent as GenericComponent;
|
||||
|
||||
|
|
|
@ -68,8 +68,8 @@ const uppercaseNumbers = [")", "!", "@", "#", "$", "%", "^", "&", "*", "("];
|
|||
export function createHotkey<T extends HotkeyOptions>(
|
||||
optionsFunc: OptionsFunc<T, BaseHotkey, GenericHotkey>
|
||||
): Hotkey<T> {
|
||||
return createLazyProxy(() => {
|
||||
const hotkey = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const hotkey = optionsFunc.call(feature, feature);
|
||||
hotkey.type = HotkeyType;
|
||||
|
||||
processComputable(hotkey as T, "enabled");
|
||||
|
|
|
@ -91,8 +91,8 @@ export function createInfobox<T extends InfoboxOptions>(
|
|||
optionsFunc: OptionsFunc<T, BaseInfobox, GenericInfobox>
|
||||
): Infobox<T> {
|
||||
const collapsed = persistent<boolean>(false, false);
|
||||
return createLazyProxy(() => {
|
||||
const infobox = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const infobox = optionsFunc.call(feature, feature);
|
||||
infobox.id = getUniqueID("infobox-");
|
||||
infobox.type = InfoboxType;
|
||||
infobox[Component] = InfoboxComponent as GenericComponent;
|
||||
|
|
|
@ -59,8 +59,8 @@ export type GenericLinks = Replace<
|
|||
export function createLinks<T extends LinksOptions>(
|
||||
optionsFunc: OptionsFunc<T, BaseLinks, GenericLinks>
|
||||
): Links<T> {
|
||||
return createLazyProxy(() => {
|
||||
const links = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const links = optionsFunc.call(feature, feature);
|
||||
links.type = LinksType;
|
||||
links[Component] = LinksComponent as GenericComponent;
|
||||
|
||||
|
|
|
@ -69,8 +69,10 @@ export type GenericParticles = Particles<ParticlesOptions>;
|
|||
export function createParticles<T extends ParticlesOptions>(
|
||||
optionsFunc?: OptionsFunc<T, BaseParticles, GenericParticles>
|
||||
): Particles<T> {
|
||||
return createLazyProxy(() => {
|
||||
const particles = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>);
|
||||
return createLazyProxy(feature => {
|
||||
const particles =
|
||||
optionsFunc?.call(feature, feature) ??
|
||||
({} as ReturnType<NonNullable<typeof optionsFunc>>);
|
||||
particles.id = getUniqueID("particles-");
|
||||
particles.type = ParticlesType;
|
||||
particles[Component] = ParticlesComponent as GenericComponent;
|
||||
|
|
|
@ -132,8 +132,8 @@ export function createRepeatable<T extends RepeatableOptions>(
|
|||
optionsFunc: OptionsFunc<T, BaseRepeatable, GenericRepeatable>
|
||||
): Repeatable<T> {
|
||||
const amount = persistent<DecimalSource>(0);
|
||||
return createLazyProxy(() => {
|
||||
const repeatable = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const repeatable = optionsFunc.call(feature, feature);
|
||||
|
||||
repeatable.id = getUniqueID("repeatable-");
|
||||
repeatable.type = RepeatableType;
|
||||
|
|
|
@ -54,8 +54,8 @@ export type GenericReset = Reset<ResetOptions>;
|
|||
export function createReset<T extends ResetOptions>(
|
||||
optionsFunc: OptionsFunc<T, BaseReset, GenericReset>
|
||||
): Reset<T> {
|
||||
return createLazyProxy(() => {
|
||||
const reset = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const reset = optionsFunc.call(feature, feature);
|
||||
reset.id = getUniqueID("reset-");
|
||||
reset.type = ResetType;
|
||||
|
||||
|
|
|
@ -62,8 +62,8 @@ export type GenericTab = Tab<TabOptions>;
|
|||
export function createTab<T extends TabOptions>(
|
||||
optionsFunc: OptionsFunc<T, BaseTab, GenericTab>
|
||||
): Tab<T> {
|
||||
return createLazyProxy(() => {
|
||||
const tab = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const tab = optionsFunc.call(feature, feature);
|
||||
tab.id = getUniqueID("tab-");
|
||||
tab.type = TabType;
|
||||
tab[Component] = TabComponent as GenericComponent;
|
||||
|
|
|
@ -156,8 +156,10 @@ export function createTabFamily<T extends TabFamilyOptions>(
|
|||
}
|
||||
|
||||
const selected = persistent(Object.keys(tabs)[0], false);
|
||||
return createLazyProxy(() => {
|
||||
const tabFamily = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>);
|
||||
return createLazyProxy(feature => {
|
||||
const tabFamily =
|
||||
optionsFunc?.call(feature, feature) ??
|
||||
({} as ReturnType<NonNullable<typeof optionsFunc>>);
|
||||
|
||||
tabFamily.id = getUniqueID("tabFamily-");
|
||||
tabFamily.type = TabFamilyType;
|
||||
|
|
|
@ -103,8 +103,10 @@ export type GenericTreeNode = Replace<
|
|||
export function createTreeNode<T extends TreeNodeOptions>(
|
||||
optionsFunc?: OptionsFunc<T, BaseTreeNode, GenericTreeNode>
|
||||
): TreeNode<T> {
|
||||
return createLazyProxy(() => {
|
||||
const treeNode = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>);
|
||||
return createLazyProxy(feature => {
|
||||
const treeNode =
|
||||
optionsFunc?.call(feature, feature) ??
|
||||
({} as ReturnType<NonNullable<typeof optionsFunc>>);
|
||||
treeNode.id = getUniqueID("treeNode-");
|
||||
treeNode.type = TreeNodeType;
|
||||
treeNode[Component] = TreeNodeComponent as GenericComponent;
|
||||
|
@ -242,8 +244,8 @@ export type GenericTree = Replace<
|
|||
export function createTree<T extends TreeOptions>(
|
||||
optionsFunc: OptionsFunc<T, BaseTree, GenericTree>
|
||||
): Tree<T> {
|
||||
return createLazyProxy(() => {
|
||||
const tree = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const tree = optionsFunc.call(feature, feature);
|
||||
tree.id = getUniqueID("tree-");
|
||||
tree.type = TreeType;
|
||||
tree[Component] = TreeComponent as GenericComponent;
|
||||
|
|
|
@ -118,8 +118,8 @@ export function createUpgrade<T extends UpgradeOptions>(
|
|||
optionsFunc: OptionsFunc<T, BaseUpgrade, GenericUpgrade>
|
||||
): Upgrade<T> {
|
||||
const bought = persistent<boolean>(false, false);
|
||||
return createLazyProxy(() => {
|
||||
const upgrade = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const upgrade = optionsFunc.call(feature, feature);
|
||||
upgrade.id = getUniqueID("upgrade-");
|
||||
upgrade.type = UpgradeType;
|
||||
upgrade[Component] = UpgradeComponent as GenericComponent;
|
||||
|
|
|
@ -220,7 +220,7 @@ export function createLayer<T extends LayerOptions>(
|
|||
addingLayers.push(id);
|
||||
persistentRefs[id] = new Set();
|
||||
layer.minimized = persistent(false, false);
|
||||
Object.assign(layer, optionsFunc.call(layer as BaseLayer));
|
||||
Object.assign(layer, optionsFunc.call(layer, layer as BaseLayer));
|
||||
if (
|
||||
addingLayers[addingLayers.length - 1] == null ||
|
||||
addingLayers[addingLayers.length - 1] !== id
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import "components/common/modifiers.css";
|
||||
import type { CoercableComponent } from "features/feature";
|
||||
import type { CoercableComponent, OptionsFunc } from "features/feature";
|
||||
import { jsx } from "features/feature";
|
||||
import settings from "game/settings";
|
||||
import type { DecimalSource } from "util/bignum";
|
||||
|
@ -66,10 +66,13 @@ export interface AdditiveModifierOptions {
|
|||
* @param optionsFunc Additive modifier options.
|
||||
*/
|
||||
export function createAdditiveModifier<T extends AdditiveModifierOptions>(
|
||||
optionsFunc: () => T
|
||||
optionsFunc: OptionsFunc<T>
|
||||
): ModifierFromOptionalParams<T["description"], T["enabled"]> {
|
||||
return createLazyProxy(() => {
|
||||
const { addend, description, enabled, smallerIsBetter } = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const { addend, description, enabled, smallerIsBetter } = optionsFunc.call(
|
||||
feature,
|
||||
feature
|
||||
);
|
||||
|
||||
const processedAddend = convertComputable(addend);
|
||||
const processedDescription = convertComputable(description);
|
||||
|
@ -128,10 +131,13 @@ export interface MultiplicativeModifierOptions {
|
|||
* @param optionsFunc Multiplicative modifier options.
|
||||
*/
|
||||
export function createMultiplicativeModifier<T extends MultiplicativeModifierOptions>(
|
||||
optionsFunc: () => T
|
||||
optionsFunc: OptionsFunc<T>
|
||||
): ModifierFromOptionalParams<T["description"], T["enabled"]> {
|
||||
return createLazyProxy(() => {
|
||||
const { multiplier, description, enabled, smallerIsBetter } = optionsFunc();
|
||||
return createLazyProxy(feature => {
|
||||
const { multiplier, description, enabled, smallerIsBetter } = optionsFunc.call(
|
||||
feature,
|
||||
feature
|
||||
);
|
||||
|
||||
const processedMultiplier = convertComputable(multiplier);
|
||||
const processedDescription = convertComputable(description);
|
||||
|
@ -191,11 +197,11 @@ export interface ExponentialModifierOptions {
|
|||
* @param optionsFunc Exponential modifier options.
|
||||
*/
|
||||
export function createExponentialModifier<T extends ExponentialModifierOptions>(
|
||||
optionsFunc: () => T
|
||||
optionsFunc: OptionsFunc<T>
|
||||
): ModifierFromOptionalParams<T["description"], T["enabled"]> {
|
||||
return createLazyProxy(() => {
|
||||
return createLazyProxy(feature => {
|
||||
const { exponent, description, enabled, supportLowNumbers, smallerIsBetter } =
|
||||
optionsFunc();
|
||||
optionsFunc.call(feature, feature);
|
||||
|
||||
const processedExponent = convertComputable(exponent);
|
||||
const processedDescription = convertComputable(description);
|
||||
|
|
|
@ -3,6 +3,7 @@ import {
|
|||
CoercableComponent,
|
||||
isVisible,
|
||||
jsx,
|
||||
OptionsFunc,
|
||||
Replace,
|
||||
setDefault,
|
||||
Visibility
|
||||
|
@ -108,10 +109,10 @@ export type CostRequirement = Replace<
|
|||
* @param optionsFunc Cost requirement options.
|
||||
*/
|
||||
export function createCostRequirement<T extends CostRequirementOptions>(
|
||||
optionsFunc: () => T
|
||||
optionsFunc: OptionsFunc<T>
|
||||
): CostRequirement {
|
||||
return createLazyProxy(() => {
|
||||
const req = optionsFunc() as T & Partial<Requirement>;
|
||||
return createLazyProxy(feature => {
|
||||
const req = optionsFunc.call(feature, feature) as T & Partial<Requirement>;
|
||||
|
||||
req.partialDisplay = amount => (
|
||||
<span
|
||||
|
|
|
@ -31,14 +31,14 @@ export type Proxied<T> = NonNullable<T> extends Record<PropertyKey, unknown>
|
|||
// Takes a function that returns an object and pretends to be that object
|
||||
// Note that the object is lazily calculated
|
||||
export function createLazyProxy<T extends object, S extends T>(
|
||||
objectFunc: (baseObject: S) => T & S,
|
||||
objectFunc: (this: S, baseObject: S) => T & S,
|
||||
baseObject: S = {} as S
|
||||
): T {
|
||||
const obj: S & Partial<T> = baseObject;
|
||||
let calculated = false;
|
||||
function calculateObj(): T {
|
||||
if (!calculated) {
|
||||
Object.assign(obj, objectFunc(obj));
|
||||
Object.assign(obj, objectFunc.call(obj, obj));
|
||||
calculated = true;
|
||||
}
|
||||
return obj as S & T;
|
||||
|
@ -73,7 +73,7 @@ export function createLazyProxy<T extends object, S extends T>(
|
|||
},
|
||||
getOwnPropertyDescriptor(target, key) {
|
||||
if (!calculated) {
|
||||
Object.assign(obj, objectFunc(obj));
|
||||
Object.assign(obj, objectFunc.call(obj, obj));
|
||||
calculated = true;
|
||||
}
|
||||
return Object.getOwnPropertyDescriptor(target, key);
|
||||
|
|
Loading…
Reference in a new issue