From b6d5eaa72d7486be1b7b3c6b220bd3b7cceedff9 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sun, 26 Jun 2022 23:03:40 -0500 Subject: [PATCH 01/37] Added math components folder --- src/components/math/Floor.vue | 5 +++++ src/components/math/Sqrt.vue | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 src/components/math/Floor.vue create mode 100644 src/components/math/Sqrt.vue diff --git a/src/components/math/Floor.vue b/src/components/math/Floor.vue new file mode 100644 index 0000000..7010c59 --- /dev/null +++ b/src/components/math/Floor.vue @@ -0,0 +1,5 @@ + diff --git a/src/components/math/Sqrt.vue b/src/components/math/Sqrt.vue new file mode 100644 index 0000000..f3b62f5 --- /dev/null +++ b/src/components/math/Sqrt.vue @@ -0,0 +1,5 @@ + From 9370b0ed6f3904d29d213e05709e9d173bf2b418 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sun, 5 Jun 2022 17:30:40 -0500 Subject: [PATCH 02/37] Improved typing for player.layers --- src/game/player.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/game/player.ts b/src/game/player.ts index 30f9a6c..506337d 100644 --- a/src/game/player.ts +++ b/src/game/player.ts @@ -3,6 +3,7 @@ import Decimal from "util/bignum"; import type { ProxiedWithState } from "util/proxies"; import { ProxyPath, ProxyState } from "util/proxies"; import { reactive, unref } from "vue"; +import type { Ref } from "vue"; import transientState from "./state"; export interface PlayerData { @@ -18,11 +19,23 @@ export interface PlayerData { keepGoing: boolean; modID: string; modVersion: string; - layers: Record>; + layers: Record>; } export type Player = ProxiedWithState; +export type LayerData = { + [P in keyof T]?: T[P] extends (infer U)[] + ? LayerData[] + : T[P] extends Record + ? never + : T[P] extends Ref + ? S + : T[P] extends object + ? LayerData + : T[P]; +}; + const state = reactive({ id: "", devSpeed: null, From 8fce6ac23e8d53b7b8708746dc63cc6c0df31d8d Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Tue, 7 Jun 2022 19:07:04 -0500 Subject: [PATCH 03/37] Removed v-show --- src/data/common.tsx | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/data/common.tsx b/src/data/common.tsx index 7792fab..45f6321 100644 --- a/src/data/common.tsx +++ b/src/data/common.tsx @@ -92,18 +92,20 @@ export function createResetButton{" "} {resetButton.conversion.gainResource.displayName} -
-
- {unref(resetButton.conversion.buyMax) ? "Next:" : "Req:"}{" "} - {displayResource( - resetButton.conversion.baseResource, - unref(resetButton.conversion.buyMax) || - Decimal.floor(unref(resetButton.conversion.actualGain)).neq(1) - ? unref(resetButton.conversion.nextAt) - : unref(resetButton.conversion.currentAt) - )}{" "} - {resetButton.conversion.baseResource.displayName} -
+ {unref(resetButton.showNextAt) ? ( +
+
+ {unref(resetButton.conversion.buyMax) ? "Next:" : "Req:"}{" "} + {displayResource( + resetButton.conversion.baseResource, + unref(resetButton.conversion.buyMax) || + Decimal.floor(unref(resetButton.conversion.actualGain)).neq(1) + ? unref(resetButton.conversion.nextAt) + : unref(resetButton.conversion.currentAt) + )}{" "} + {resetButton.conversion.baseResource.displayName} +
+ ) : null} )); } From d7041a3c3cd831ad030969890a6603269b7c24df Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sun, 26 Jun 2022 23:00:41 -0500 Subject: [PATCH 04/37] Make OptionsFunc include the options in the typing for `this` --- src/features/feature.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/features/feature.ts b/src/features/feature.ts index 61cd7ed..c2f34f5 100644 --- a/src/features/feature.ts +++ b/src/features/feature.ts @@ -42,7 +42,9 @@ export type Replace = S & Omit; * with "this" bound to what the type will eventually be processed into. * Intended for making lazily evaluated objects. */ -export type OptionsFunc, S = R> = () => T & Partial & ThisType; +export type OptionsFunc, S = R> = () => T & + Partial & + ThisType; let id = 0; /** From fe15551e629efd064ee3504eed74d14a26467f55 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Mon, 27 Jun 2022 08:22:10 -0500 Subject: [PATCH 05/37] Version Bump --- CHANGELOG.md | 20 ++++++++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecae588..26e00f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.5.0] - 2022-06-27 +### Added +- Projects now cache for offline play, and show notification when an update is available +- Projects can now be "installed" as a Progressive Web App +- Conversions can now be given a custom spend function, which defaults to setting the base resource amount to 0 +- Components for displaying Floor and Square Root symbols +### Changed +- **BREAKING** Several projInfo properties now default to empty strings, to prevent things like reusing project IDs +- **BREAKING** Replaced vue-cli-service with vite (should not break most projects) +- Updated dependencies +- Made all type-only imports explicit +- setupPassiveGeneration now works properly on independent conversions +- setupPassiveGeneration now takes an option cap it can't go over +- Improved typing for PlayerData.layers +- Options Functions have an improved `this` type - it now includes the options themselves +- Removed v-show being used in data/common.tsx +### Tests +- Implement Jest, and running tests automatically on push +- Tests written for utils/common.ts + ## [0.4.2] - 2022-05-23 ### Added - costModifier to conversions diff --git a/package-lock.json b/package-lock.json index 9d85e53..8ea87a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "profectus", - "version": "0.4.2", + "version": "0.5.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "profectus", - "version": "0.4.2", + "version": "0.5.0", "dependencies": { "@pixi/particle-emitter": "^5.0.4", "@vitejs/plugin-vue": "^2.3.3", diff --git a/package.json b/package.json index 82d9880..44eb680 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "profectus", - "version": "0.4.2", + "version": "0.5.0", "private": true, "scripts": { "start": "vite", From 366d34bd9a53ca080985c711d0aa77d82af54ab2 Mon Sep 17 00:00:00 2001 From: Isha Date: Thu, 7 Jul 2022 12:12:53 +0200 Subject: [PATCH 06/37] Fix typo in start command --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ca5a378..05451b5 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ npm install ### Hosts dev server and hot-reloads modules as they're changed ``` -npm starts +npm start ``` ### Compiles and minifies for production From 43fa50baeead3e365a432008b2b112b010801853 Mon Sep 17 00:00:00 2001 From: Isha Date: Thu, 7 Jul 2022 12:13:05 +0200 Subject: [PATCH 07/37] Add test command to README --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 05451b5..e535eb2 100644 --- a/README.md +++ b/README.md @@ -30,3 +30,8 @@ npm run preview ``` npm run lint ``` + +### Runs the tests using vite-jest +``` +npm run test +``` From ff9fa0bf0769492b2224c4dc215360329ff7f67f Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Tue, 28 Jun 2022 09:51:52 -0500 Subject: [PATCH 08/37] Bind uncached functions in processComputable --- src/util/computed.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/util/computed.ts b/src/util/computed.ts index d3f3119..d9b3458 100644 --- a/src/util/computed.ts +++ b/src/util/computed.ts @@ -37,6 +37,8 @@ export function processComputable>( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore obj[key] = computed(computable.bind(obj)); + } else if (isFunction(computable)) { + obj[key] = computable.bind(obj); } } From 7dd7744edf0d9219c67b6624251e1a4506d7e5c7 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Tue, 28 Jun 2022 09:52:49 -0500 Subject: [PATCH 09/37] Add colorText utility function --- src/data/common.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/data/common.tsx b/src/data/common.tsx index 45f6321..9630d9f 100644 --- a/src/data/common.tsx +++ b/src/data/common.tsx @@ -248,3 +248,7 @@ export function createCollapsibleModifierSections( }); return [jsxFunc, collapsed]; } + +export function colorText(textToColor: string, color = "var(--accent2)"): string { + return `${textToColor}`; +} From 64d6aae1c014f44dd2d55716b6f7eaec6ca66876 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Tue, 28 Jun 2022 09:53:07 -0500 Subject: [PATCH 10/37] Reformat Sqrt.vue --- src/components/math/Sqrt.vue | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/math/Sqrt.vue b/src/components/math/Sqrt.vue index f3b62f5..dc8292e 100644 --- a/src/components/math/Sqrt.vue +++ b/src/components/math/Sqrt.vue @@ -1,5 +1,6 @@ From 62d23ec699256624060735276f671a50fff4da22 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sun, 3 Jul 2022 12:27:44 -0500 Subject: [PATCH 11/37] Made MainDisplay sticky --- src/features/resources/MainDisplay.vue | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/features/resources/MainDisplay.vue b/src/features/resources/MainDisplay.vue index 2202b39..18d8164 100644 --- a/src/features/resources/MainDisplay.vue +++ b/src/features/resources/MainDisplay.vue @@ -1,15 +1,17 @@ + + From 7345471e8adb356927f52e5e06a4f82ccf4a0eb4 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sun, 3 Jul 2022 13:08:09 -0500 Subject: [PATCH 12/37] Add options to tab families to style the buttons container Example usage: adding a "top" property for proper stickying --- src/features/tabs/TabFamily.vue | 10 ++++++++-- src/features/tabs/tabFamily.ts | 26 ++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/features/tabs/TabFamily.vue b/src/features/tabs/TabFamily.vue index 45ac87e..1ae9007 100644 --- a/src/features/tabs/TabFamily.vue +++ b/src/features/tabs/TabFamily.vue @@ -11,7 +11,11 @@ tabStyle ?? [] ]" > - +
(String, Object, Array), - classes: processedPropType>(Object) + classes: processedPropType>(Object), + buttonContainerStyle: processedPropType(String, Object, Array), + buttonContainerClasses: processedPropType>(Object) }, components: { Sticky, diff --git a/src/features/tabs/tabFamily.ts b/src/features/tabs/tabFamily.ts index 6197266..a1281e0 100644 --- a/src/features/tabs/tabFamily.ts +++ b/src/features/tabs/tabFamily.ts @@ -56,6 +56,8 @@ export interface TabFamilyOptions { visibility?: Computable; classes?: Computable>; style?: Computable; + buttonContainerClasses?: Computable>; + buttonContainerStyle?: Computable; } export interface BaseTabFamily { @@ -140,10 +142,30 @@ export function createTabFamily( setDefault(tabFamily, "visibility", Visibility.Visible); processComputable(tabFamily as T, "classes"); processComputable(tabFamily as T, "style"); + processComputable(tabFamily as T, "buttonContainerClasses"); + processComputable(tabFamily as T, "buttonContainerStyle"); tabFamily[GatherProps] = function (this: GenericTabFamily) { - const { visibility, activeTab, selected, tabs, style, classes } = this; - return { visibility, activeTab, selected, tabs, style: unref(style), classes }; + const { + visibility, + activeTab, + selected, + tabs, + style, + classes, + buttonContainerClasses, + buttonContainerStyle + } = this; + return { + visibility, + activeTab, + selected, + tabs, + style: unref(style), + classes, + buttonContainerClasses, + buttonContainerStyle + }; }; // This is necessary because board.types is different from T and TabFamily From 78ac7957dd206f70ae7cd62946ca0e7f84a182e3 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Thu, 7 Jul 2022 10:40:33 -0500 Subject: [PATCH 13/37] Improved how MainDisplay displayed effect strings --- src/features/resources/MainDisplay.vue | 29 +++++++++++++++++--------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/features/resources/MainDisplay.vue b/src/features/resources/MainDisplay.vue index 18d8164..f0051cf 100644 --- a/src/features/resources/MainDisplay.vue +++ b/src/features/resources/MainDisplay.vue @@ -1,11 +1,18 @@ @@ -17,7 +24,7 @@ import type { Resource } from "features/resources/resource"; import ResourceVue from "features/resources/Resource.vue"; import Decimal from "util/bignum"; import { computeOptionalComponent } from "util/vue"; -import type { Ref, StyleValue } from "vue"; +import { ComponentPublicInstance, ref, Ref, StyleValue } from "vue"; import { computed, toRefs } from "vue"; const _props = defineProps<{ @@ -29,6 +36,8 @@ const _props = defineProps<{ }>(); const props = toRefs(_props); +const effectRef = ref(null); + const effectComponent = computeOptionalComponent( props.effectDisplay as Ref ); @@ -39,9 +48,9 @@ const showPrefix = computed(() => { From 409b3bbac46a4e627d2ba8cffdc239af7dd52f19 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Wed, 6 Jul 2022 10:09:37 -0500 Subject: [PATCH 14/37] Add showAmount boolean to buyable displays --- src/features/buyable.tsx | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/features/buyable.tsx b/src/features/buyable.tsx index 60c12c9..de60c83 100644 --- a/src/features/buyable.tsx +++ b/src/features/buyable.tsx @@ -26,6 +26,7 @@ export type BuyableDisplay = title?: CoercableComponent; description: CoercableComponent; effectDisplay?: CoercableComponent; + showAmount?: boolean; }; export interface BuyableOptions { @@ -170,15 +171,6 @@ export function createBuyable( const Title = coerceComponent(currDisplay.title || "", "h3"); const Description = coerceComponent(currDisplay.description); const EffectDisplay = coerceComponent(currDisplay.effectDisplay || ""); - const amountDisplay = - unref(genericBuyable.purchaseLimit) === Decimal.dInf ? ( - <>Amount: {formatWhole(genericBuyable.amount.value)} - ) : ( - <> - Amount: {formatWhole(genericBuyable.amount.value)} /{" "} - {formatWhole(unref(genericBuyable.purchaseLimit))} - - ); return ( @@ -188,10 +180,19 @@ export function createBuyable(
) : null} -
-
- {amountDisplay} -
+ {currDisplay.showAmount === false ? null : ( +
+
+ {unref(genericBuyable.purchaseLimit) === Decimal.dInf ? ( + <>Amount: {formatWhole(genericBuyable.amount.value)} + ) : ( + <> + Amount: {formatWhole(genericBuyable.amount.value)} /{" "} + {formatWhole(unref(genericBuyable.purchaseLimit))} + + )} +
+ )} {currDisplay.effectDisplay ? (

From 0229c0130f7bfd1491c90635cdf03e9339153f8f Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Wed, 6 Jul 2022 22:52:03 -0500 Subject: [PATCH 15/37] Cleaned up tooltips --- src/features/tooltips/Tooltip.vue | 28 ++++++++++++++-------------- src/features/tooltips/tooltip.ts | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/features/tooltips/Tooltip.vue b/src/features/tooltips/Tooltip.vue index a8bf6ae..1911186 100644 --- a/src/features/tooltips/Tooltip.vue +++ b/src/features/tooltips/Tooltip.vue @@ -34,10 +34,10 @@
- From 3ee1cdb3841c07ea4fd6d0ca621dce06bd8a8dcd Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sat, 9 Jul 2022 17:07:09 -0500 Subject: [PATCH 25/37] Fix Links not always updating its outer bounds --- src/features/links/Links.vue | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/features/links/Links.vue b/src/features/links/Links.vue index bbf4740..dafab2b 100644 --- a/src/features/links/Links.vue +++ b/src/features/links/Links.vue @@ -16,7 +16,7 @@ import type { Link } from "features/links/links"; import type { FeatureNode } from "game/layers"; import { BoundsInjectionKey, NodesInjectionKey } from "game/layers"; -import { computed, inject, ref, toRef, watch } from "vue"; +import { computed, inject, onMounted, ref, toRef, watch } from "vue"; import LinkVue from "./Link.vue"; const _props = defineProps<{ links?: Link[] }>(); @@ -26,11 +26,12 @@ const resizeListener = ref(null); const nodes = inject(NodesInjectionKey, ref>({})); const outerBoundingRect = inject(BoundsInjectionKey, ref(undefined)); -const boundingRect = ref(undefined); +const boundingRect = ref(resizeListener.value?.getBoundingClientRect()); watch( - [outerBoundingRect], + outerBoundingRect, () => (boundingRect.value = resizeListener.value?.getBoundingClientRect()) ); +onMounted(() => (boundingRect.value = resizeListener.value?.getBoundingClientRect())); const validLinks = computed(() => { const n = nodes.value; From 9828e5ec623e5f45008723ac6e783e1f0f9117c6 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sat, 9 Jul 2022 22:09:25 -0500 Subject: [PATCH 26/37] Document all the window augmentations --- src/game/layers.tsx | 7 +++++++ src/game/player.ts | 7 +++++++ src/game/settings.ts | 34 ++++++++++++++++++++++------------ src/game/state.ts | 6 ++++++ src/main.ts | 40 ++++++++++------------------------------ src/util/bignum.ts | 15 +++++++++++++++ src/util/save.ts | 11 +++++++++++ 7 files changed, 78 insertions(+), 42 deletions(-) diff --git a/src/game/layers.tsx b/src/game/layers.tsx index 5072ce9..351d1fc 100644 --- a/src/game/layers.tsx +++ b/src/game/layers.tsx @@ -48,6 +48,13 @@ export interface LayerEvents { } export const layers: Record | undefined> = shallowReactive({}); + +declare global { + /** Augment the window object so the layers can be accessed from the console */ + interface Window { + layers: Record | undefined>; + } +} window.layers = layers; declare module "@vue/runtime-dom" { diff --git a/src/game/player.ts b/src/game/player.ts index 506337d..8b4ceb0 100644 --- a/src/game/player.ts +++ b/src/game/player.ts @@ -126,6 +126,13 @@ const playerHandler: ProxyHandler> = { return Object.getOwnPropertyDescriptor(target[ProxyState], key); } }; + +declare global { + /** Augment the window object so the player can be accessed from the console */ + interface Window { + player: Player; + } +} export default window.player = new Proxy( { [ProxyState]: state, [ProxyPath]: ["player"] }, playerHandler diff --git a/src/game/settings.ts b/src/game/settings.ts index 4563008..5a94555 100644 --- a/src/game/settings.ts +++ b/src/game/settings.ts @@ -30,7 +30,29 @@ watch( }, { deep: true } ); + +declare global { + /** + * Augment the window object so the settings, and hard resetting the settings, + * can be accessed from the console + */ + interface Window { + settings: Settings; + hardResetSettings: VoidFunction; + } +} export default window.settings = state as Settings; +export const hardResetSettings = (window.hardResetSettings = () => { + const settings = { + active: "", + saves: [], + showTPS: true, + theme: Themes.Nordic + }; + globalBus.emit("loadSettings", settings); + Object.assign(state, settings); + hardReset(); +}); export function loadSettings(): void { try { @@ -59,18 +81,6 @@ export function loadSettings(): void { } catch {} } -export const hardResetSettings = (window.hardResetSettings = () => { - const settings = { - active: "", - saves: [], - showTPS: true, - theme: Themes.Nordic - }; - globalBus.emit("loadSettings", settings); - Object.assign(state, settings); - hardReset(); -}); - export const settingFields: CoercableComponent[] = reactive([]); export function registerSettingField(component: CoercableComponent) { settingFields.push(component); diff --git a/src/game/state.ts b/src/game/state.ts index e8d9da0..1154949 100644 --- a/src/game/state.ts +++ b/src/game/state.ts @@ -7,6 +7,12 @@ export interface Transient { NaNReceiver?: Record; } +declare global { + /** Augment the window object so the transient state can be accessed from the console */ + interface Window { + state: Transient; + } +} export default window.state = shallowReactive({ lastTenTicks: [], hasNaN: false, diff --git a/src/main.ts b/src/main.ts index 1540a1e..8db628b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,47 +1,29 @@ import App from "App.vue"; import projInfo from "data/projInfo.json"; -import type { GenericLayer } from "game/layers"; import "game/notifications"; -import type { PlayerData } from "game/player"; -import type { Settings } from "game/settings"; -import type { Transient } from "game/state"; -import type { DecimalSource } from "util/bignum"; -import Decimal from "util/bignum"; import { load } from "util/save"; import { useRegisterSW } from "virtual:pwa-register/vue"; import type { App as VueApp } from "vue"; import { createApp, nextTick } from "vue"; import { useToast } from "vue-toastification"; -document.title = projInfo.title; -if (projInfo.id === "") { - throw "Project ID is empty! Please select a unique ID for this project in /src/data/projInfo.json"; -} - declare global { + /** + * Augment the window object so + * the vue app and project info can be accessed from the console + */ interface Window { vue: VueApp; - save: VoidFunction; - hardReset: VoidFunction; - hardResetSettings: VoidFunction; - layers: Record | undefined>; - player: PlayerData; - state: Transient; - settings: Settings; - Decimal: typeof Decimal; - exponentialFormat: (num: DecimalSource, precision: number, mantissa: boolean) => string; - commaFormat: (num: DecimalSource, precision: number) => string; - regularFormat: (num: DecimalSource, precision: number) => string; - format: (num: DecimalSource, precision?: number, small?: boolean) => string; - formatWhole: (num: DecimalSource) => string; - formatTime: (s: number) => string; - toPlaces: (x: DecimalSource, precision: number, maxAccepted: DecimalSource) => string; - formatSmall: (x: DecimalSource, precision?: number) => string; - invertOOM: (x: DecimalSource) => Decimal; projInfo: typeof projInfo; } } +document.title = projInfo.title; +window.projInfo = projInfo; +if (projInfo.id === "") { + throw "Project ID is empty! Please select a unique ID for this project in /src/data/projInfo.json"; +} + requestAnimationFrame(async () => { console.log( "%cMade in Profectus%c\nLearn more at www.moddingtree.com", @@ -90,5 +72,3 @@ requestAnimationFrame(async () => { startGameLoop(); }); - -window.projInfo = projInfo; diff --git a/src/util/bignum.ts b/src/util/bignum.ts index ad7100f..2e047a2 100644 --- a/src/util/bignum.ts +++ b/src/util/bignum.ts @@ -17,6 +17,21 @@ export const { export type DecimalSource = RawDecimalSource; +declare global { + /** Augment the window object so the big num functions can be access from the console */ + interface Window { + Decimal: typeof Decimal; + exponentialFormat: (num: DecimalSource, precision: number, mantissa: boolean) => string; + commaFormat: (num: DecimalSource, precision: number) => string; + regularFormat: (num: DecimalSource, precision: number) => string; + format: (num: DecimalSource, precision?: number, small?: boolean) => string; + formatWhole: (num: DecimalSource) => string; + formatTime: (s: number) => string; + toPlaces: (x: DecimalSource, precision: number, maxAccepted: DecimalSource) => string; + formatSmall: (x: DecimalSource, precision?: number) => string; + invertOOM: (x: DecimalSource) => Decimal; + } +} window.Decimal = Decimal; window.exponentialFormat = exponentialFormat; window.commaFormat = commaFormat; diff --git a/src/util/save.ts b/src/util/save.ts index 122a2bd..c0f96ef 100644 --- a/src/util/save.ts +++ b/src/util/save.ts @@ -124,6 +124,17 @@ window.onbeforeunload = () => { save(); } }; + +declare global { + /** + * Augment the window object so the save function, + * and the hard reset function can be access from the console + */ + interface Window { + save: VoidFunction; + hardReset: VoidFunction; + } +} window.save = save; export const hardReset = (window.hardReset = async () => { await loadSave(newSave()); From 439e10d7b15819bd06864e626daad94f241a4567 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sat, 9 Jul 2022 20:46:42 -0500 Subject: [PATCH 27/37] Create tooltips' pinnable persistent variable immediately --- src/features/tooltips/tooltip.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/features/tooltips/tooltip.ts b/src/features/tooltips/tooltip.ts index 19ab705..dcc618f 100644 --- a/src/features/tooltips/tooltip.ts +++ b/src/features/tooltips/tooltip.ts @@ -70,19 +70,19 @@ export function addTooltip( processComputable(options as T, "xoffset"); processComputable(options as T, "yoffset"); - nextTick(() => { - if (options.pinnable) { - if ("pinned" in element) { - console.error( - "Cannot add pinnable tooltip to element that already has a property called 'pinned'" - ); - options.pinnable = false; - } else { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (element as any).pinned = options.pinned = persistent(false); - } + if (options.pinnable) { + if ("pinned" in element) { + console.error( + "Cannot add pinnable tooltip to element that already has a property called 'pinned'" + ); + options.pinnable = false; + } else { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (element as any).pinned = options.pinned = persistent(false); } + } + nextTick(() => { const elementComponent = element[Component]; element[Component] = TooltipComponent; const elementGatherProps = element[GatherProps].bind(element); From 804e596fa7e4e233f4681464c85aacd83939b78f Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sat, 9 Jul 2022 22:02:44 -0500 Subject: [PATCH 28/37] Fix doc generation --- src/main.ts | 5 +++++ tsconfig.json | 7 +++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main.ts b/src/main.ts index 8db628b..5b8cf9c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -16,6 +16,11 @@ declare global { vue: VueApp; projInfo: typeof projInfo; } + + /** Fix for typedoc treating import functions as taking AssertOptions instead of GlobOptions */ + interface AssertOptions { + as: string; + } } document.title = projInfo.title; diff --git a/tsconfig.json b/tsconfig.json index af329eb..96f5d91 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,8 @@ "sourceMap": true, "baseUrl": "src", "types": [ - "vite/client" + "vite/client", + "node" ], "lib": [ "esnext", @@ -29,9 +30,7 @@ "include": [ "src/**/*.ts", "src/**/*.tsx", - "src/**/*.vue", - "tests/**/*.ts", - "tests/**/*.tsx" + "src/**/*.vue" ], "exclude": [ "node_modules" From 0b8210c18d89918e3086e9728810b3f5dfe7b6c2 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sat, 9 Jul 2022 23:03:31 -0500 Subject: [PATCH 29/37] Re-add tests to include array --- tsconfig.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 96f5d91..280a1e1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -30,7 +30,9 @@ "include": [ "src/**/*.ts", "src/**/*.tsx", - "src/**/*.vue" + "src/**/*.vue", + "tests/**/*.ts", + "tests/**/*.tsx" ], "exclude": [ "node_modules" From 21e739070dd1c2f954b513a8811ce0a38a61ba94 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sun, 10 Jul 2022 00:43:34 -0500 Subject: [PATCH 30/37] Documented game/layers.tsx --- src/game/layers.tsx | 114 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 108 insertions(+), 6 deletions(-) diff --git a/src/game/layers.tsx b/src/game/layers.tsx index 351d1fc..e8d22c3 100644 --- a/src/game/layers.tsx +++ b/src/game/layers.tsx @@ -24,33 +24,51 @@ import { createLazyProxy } from "util/proxies"; import type { InjectionKey, Ref } from "vue"; import { ref, shallowReactive, unref } from "vue"; +/** A feature's node in the DOM that has its size tracked. */ export interface FeatureNode { rect: DOMRect; observer: MutationObserver; element: HTMLElement; } +/** + * An injection key that a {@link Context} will use to provide a function that registers a {@link FeatureNode} with the given id and HTML element. + */ export const RegisterNodeInjectionKey: InjectionKey<(id: string, element: HTMLElement) => void> = - Symbol("RegisterNode"); + Symbol("RegisterNode"); +/** + * An injection key that a {@link Context} will use to provide a function that unregisters a {@link FeatureNode} with the given id. + */ export const UnregisterNodeInjectionKey: InjectionKey<(id: string) => void> = Symbol("UnregisterNode"); +/** + * An injection key that a {@link Context} will use to provide a ref to a map of all currently registered {@link FeatureNode}s. + */ export const NodesInjectionKey: InjectionKey>> = Symbol("Nodes"); +/** + * An injection key that a {@link Context} will use to provide a ref to a bounding rect of the Context. + */ export const BoundsInjectionKey: InjectionKey> = Symbol("Bounds"); +/** All types of events able to be sent or emitted from a layer's emitter. */ export interface LayerEvents { - // Generation + /** Sent every game tick, before the update event. Intended for "generation" type actions. */ preUpdate: (diff: number) => void; - // Actions (e.g. automation) + /** Sent every game tick. Intended for "automation" type actions. */ update: (diff: number) => void; - // Effects (e.g. milestones) + /** Sent every game tick, after the update event. Intended for checking state. */ postUpdate: (diff: number) => void; } +/** + * A reference to all the current layers. + * It is shallow reactive so it will update when layers are added or removed, but not interfere with the existing refs within each layer. + */ export const layers: Record | undefined> = shallowReactive({}); declare global { - /** Augment the window object so the layers can be accessed from the console */ + /** Augment the window object so the layers can be accessed from the console. */ interface Window { layers: Record | undefined>; } @@ -58,36 +76,81 @@ declare global { window.layers = layers; declare module "@vue/runtime-dom" { + /** Augment CSS Properties to allow for setting the layer color CSS variable. */ interface CSSProperties { "--layer-color"?: string; } } +/** An object representing the position of some entity. */ export interface Position { + /** The X component of the entity's position. */ x: number; + /** The Y component of the entity's position. */ y: number; } +/** + * An object that configures a {@link Layer}. + * Even moreso than features, the developer is expected to include extra properties in this object. + * All {@link persistent} refs must be included somewhere within the layer object. + */ export interface LayerOptions { + /** The color of the layer, used to theme the entire layer's display. */ color?: Computable; + /** + * The layout of this layer's features. + * When the layer is open in {@link player.tabs}, this is the content that is display. + */ display: Computable; + /** An object of classes that should be applied to the display. */ classes?: Computable>; + /** Styles that should be applied to the display. */ style?: Computable; + /** + * The name of the layer, used on minimized tabs. + * Defaults to {@link id}. + */ name?: Computable; + /** + * Whether or not the layer can be minimized. + * Defaults to true. + */ minimizable?: Computable; + /** + * Whether or not to force the go back button to be hidden. + * If true, go back will be hidden regardless of {@link projInfo.allowGoBack}. + */ forceHideGoBack?: Computable; + /** + * A CSS min-width value that is applied to the layer. + * Can be a number, in which case the unit is assumed to be px. + * Defaults to 600px. + */ minWidth?: Computable; } +/** The properties that are added onto a processed {@link LayerOptions} to create a {@link Layer} */ export interface BaseLayer { + /** + * The ID of the layer. + * Populated from the {@link createLayer} parameters. + * Used for saving and tracking open tabs. + */ id: string; + /** A persistent ref tracking if the tab is minimized or not. */ minimized: Persistent; + /** An emitter for sending {@link LayerEvents} events for this layer. */ emitter: Emitter; + /** A function to register an event listener on {@link emitter}. */ on: OmitThisParameter["on"]>; - emit: (event: K, ...args: Parameters) => void; + /** A function to emit a {@link LayerEvents} event to this layer. */ + emit: (...args: [K, ...Parameters]) => void; + /** A map of {@link FeatureNode}s present in this layer's {@link Context} component. */ nodes: Ref>; } +/** An unit of game content. Displayed to the user as a tab or modal. */ export type Layer = Replace< T & BaseLayer, { @@ -102,6 +165,7 @@ export type Layer = Replace< } >; +/** A type that matches any valid {@link Layer} object. */ export type GenericLayer = Replace< Layer, { @@ -111,8 +175,19 @@ export type GenericLayer = Replace< } >; +/** + * When creating layers, this object a map of layer ID to a set of any created persistent refs in order to check they're all included in the final layer object. + */ export const persistentRefs: Record> = {}; +/** + * When creating layers, this array stores the layers currently being created, as a stack. + */ export const addingLayers: string[] = []; +/** + * Lazily creates a layer with the given options. + * @param id The ID this layer will have. See {@link BaseLayer.id}. + * @param optionsFunc Layer options. + */ export function createLayer( id: string, optionsFunc: OptionsFunc @@ -150,6 +225,14 @@ export function createLayer( }); } +/** + * Enables a layer object, so it will be updated every tick. + * Note that accessing a layer/its properties does NOT require it to be enabled. + * For dynamic layers you can call this function and {@link removeLayer} as necessary. Just make sure {@link projEntry.getInitialLayers} will provide an accurate list of layers based on the player data object. + * For static layers just make {@link projEntry.getInitialLayers} return all the layers. + * @param layer The layer to add. + * @param player The player data object, which will have a data object for this layer. + */ export function addLayer( layer: GenericLayer, player: { layers?: Record> } @@ -173,10 +256,19 @@ export function addLayer( globalBus.emit("addLayer", layer, player.layers[layer.id]); } +/** + * Convenience method for getting a layer by its ID with correct typing. + * @param layerID The ID of the layer to get. + */ export function getLayer(layerID: string): T { return layers[layerID] as T; } +/** + * Disables a layer, so it will no longer be updated every tick. + * Note that accessing a layer/its properties does NOT require it to be enabled. + * @param layer The layer to remove. + */ export function removeLayer(layer: GenericLayer): void { console.info("Removing layer", layer.id); globalBus.emit("removeLayer", layer); @@ -184,6 +276,11 @@ export function removeLayer(layer: GenericLayer): void { layers[layer.id] = undefined; } +/** + * Convenience method for removing and immediately re-adding a layer. + * This is useful for layers with dynamic content, to ensure persistent refs are correctly configured. + * @param layer Layer to remove and then re-add + */ export function reloadLayer(layer: GenericLayer): void { removeLayer(layer); @@ -191,6 +288,11 @@ export function reloadLayer(layer: GenericLayer): void { addLayer(layer, player); } +/** + * Utility function for creating a modal that display's a {@link layer.display}. + * Returns the modal itself, which can be rendered anywhere you need, as well as a function to open the modal. + * @param layer The layer to display in the modal. + */ export function setupLayerModal(layer: GenericLayer): { openModal: VoidFunction; modal: JSXFunction; From db304dea43064fd660a3afb53eddf147c5fbdc05 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sun, 10 Jul 2022 00:43:52 -0500 Subject: [PATCH 31/37] Cleaned up docs --- src/features/conversion.ts | 18 ++++++------------ src/game/player.ts | 2 +- src/game/settings.ts | 3 +-- src/game/state.ts | 2 +- src/main.ts | 5 ++--- src/util/bignum.ts | 2 +- src/util/save.ts | 3 +-- 7 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/features/conversion.ts b/src/features/conversion.ts index 1dbf5a6..c334b6e 100644 --- a/src/features/conversion.ts +++ b/src/features/conversion.ts @@ -12,12 +12,10 @@ import { createLazyProxy } from "util/proxies"; import type { Ref } from "vue"; import { computed, unref } from "vue"; -/** - * An object that configures a {@link conversion}. - */ +/** An object that configures a {@link Conversion}. */ export interface ConversionOptions { /** - * The scaling function that is used to determine the rate of conversion from one {@link resource} to the other. + * The scaling function that is used to determine the rate of conversion from one {@link Resource} to the other. */ scaling: ScalingFunction; /** @@ -43,11 +41,11 @@ export interface ConversionOptions { */ nextAt?: Computable; /** - * The input {@link resource} for this conversion. + * The input {@link Resource} for this conversion. */ baseResource: Resource; /** - * The output {@link resource} for this conversion. i.e. the resource being generated. + * The output {@link Resource} for this conversion. i.e. the resource being generated. */ gainResource: Resource; /** @@ -101,9 +99,7 @@ export interface BaseConversion { convert: VoidFunction; } -/** - * An object that converts one {@link resource} into another at a given rate. - */ +/** An object that converts one {@link Resource} into another at a given rate. */ export type Conversion = Replace< T & BaseConversion, { @@ -117,9 +113,7 @@ export type Conversion = Replace< } >; -/** - * A type that matches any {@link conversion} object. - */ +/** A type that matches any valid {@link Conversion} object. */ export type GenericConversion = Replace< Conversion, { diff --git a/src/game/player.ts b/src/game/player.ts index 8b4ceb0..fae969c 100644 --- a/src/game/player.ts +++ b/src/game/player.ts @@ -128,7 +128,7 @@ const playerHandler: ProxyHandler> = { }; declare global { - /** Augment the window object so the player can be accessed from the console */ + /** Augment the window object so the player can be accessed from the console. */ interface Window { player: Player; } diff --git a/src/game/settings.ts b/src/game/settings.ts index 5a94555..af295c4 100644 --- a/src/game/settings.ts +++ b/src/game/settings.ts @@ -33,8 +33,7 @@ watch( declare global { /** - * Augment the window object so the settings, and hard resetting the settings, - * can be accessed from the console + * Augment the window object so the settings, and hard resetting the settings, can be accessed from the console. */ interface Window { settings: Settings; diff --git a/src/game/state.ts b/src/game/state.ts index 1154949..00934c4 100644 --- a/src/game/state.ts +++ b/src/game/state.ts @@ -8,7 +8,7 @@ export interface Transient { } declare global { - /** Augment the window object so the transient state can be accessed from the console */ + /** Augment the window object so the transient state can be accessed from the console. */ interface Window { state: Transient; } diff --git a/src/main.ts b/src/main.ts index 5b8cf9c..2896796 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,15 +9,14 @@ import { useToast } from "vue-toastification"; declare global { /** - * Augment the window object so - * the vue app and project info can be accessed from the console + * Augment the window object so the vue app and project info can be accessed from the console. */ interface Window { vue: VueApp; projInfo: typeof projInfo; } - /** Fix for typedoc treating import functions as taking AssertOptions instead of GlobOptions */ + /** Fix for typedoc treating import functions as taking AssertOptions instead of GlobOptions. */ interface AssertOptions { as: string; } diff --git a/src/util/bignum.ts b/src/util/bignum.ts index 2e047a2..33d180e 100644 --- a/src/util/bignum.ts +++ b/src/util/bignum.ts @@ -18,7 +18,7 @@ export const { export type DecimalSource = RawDecimalSource; declare global { - /** Augment the window object so the big num functions can be access from the console */ + /** Augment the window object so the big num functions can be access from the console. */ interface Window { Decimal: typeof Decimal; exponentialFormat: (num: DecimalSource, precision: number, mantissa: boolean) => string; diff --git a/src/util/save.ts b/src/util/save.ts index c0f96ef..c5a0073 100644 --- a/src/util/save.ts +++ b/src/util/save.ts @@ -127,8 +127,7 @@ window.onbeforeunload = () => { declare global { /** - * Augment the window object so the save function, - * and the hard reset function can be access from the console + * Augment the window object so the save function, and the hard reset function can be access from the console. */ interface Window { save: VoidFunction; From 5c0a248b16b8b587884c602c028cf2d50889b58f Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sun, 10 Jul 2022 01:44:45 -0500 Subject: [PATCH 32/37] Documented /data --- src/data/common.tsx | 65 ++++++++++++++++++++++++++++++++++++++++++ src/data/projEntry.tsx | 12 ++++++++ src/data/themes.ts | 9 ++++++ 3 files changed, 86 insertions(+) diff --git a/src/data/common.tsx b/src/data/common.tsx index 9630d9f..27cf420 100644 --- a/src/data/common.tsx +++ b/src/data/common.tsx @@ -25,18 +25,44 @@ import type { Ref } from "vue"; import { computed, unref } from "vue"; import "./common.css"; +/** An object that configures a {@link ResetButton} */ export interface ResetButtonOptions extends ClickableOptions { + /** The conversion the button uses to calculate how much resources will be gained on click */ conversion: GenericConversion; + /** The tree this reset button is apart of */ tree: GenericTree; + /** The specific tree node associated with this reset button */ treeNode: GenericTreeNode; + /** + * Text to display on low conversion amounts, describing what "resetting" is in this context. + * Defaults to "Reset for ". + */ resetDescription?: Computable; + /** Whether or not to show how much currency would be required to make the gain amount increase. */ showNextAt?: Computable; + /** + * The content to display on the button. + * By default, this includes the reset description, and amount of currency to be gained. + */ display?: Computable; + /** + * Whether or not this button can currently be clicked. + * Defaults to checking the current gain amount is greater than {@link minimumGain} + */ canClick?: Computable; + /** + * When {@link canClick} is left to its default, minimumGain is used to only enable the reset button when a sufficient amount of currency to gain is available. + */ minimumGain?: Computable; + /** A persistent ref to track how much time has passed since the last time this tree node was reset. */ resetTime?: Persistent; } +/** + * A button that is used to control a conversion. + * It will show how much can be converted currently, and can show when that amount will go up, as well as handle only being clickable when a sufficient amount of currency can be gained. + * Assumes this button is associated with a specific node on a tree, and triggers that tree's reset propagation. + */ export type ResetButton = Replace< Clickable, { @@ -49,6 +75,7 @@ export type ResetButton = Replace< } >; +/** A type that matches any valid {@link ResetButton} object. */ export type GenericResetButton = Replace< GenericClickable & ResetButton, { @@ -60,6 +87,10 @@ export type GenericResetButton = Replace< } >; +/** + * Lazily creates a reset button with the given options. + * @param optionsFunc A function that returns the options object for this reset button. + */ export function createResetButton( optionsFunc: OptionsFunc ): ResetButton { @@ -136,12 +167,24 @@ export function createResetButton; } +/** An object that configures a {@link LayerTreeNode} */ export interface LayerTreeNodeOptions extends TreeNodeOptions { + /** The ID of the layer this tree node is associated with */ layerID: string; + /** The color to display this tree node as */ color: Computable; // marking as required + /** + * The content to display in the tree node. + * Defaults to the layer's ID + */ display?: Computable; + /** Whether or not to append the layer to the tabs list. + * If set to false, then the tree node will instead always remove all tabs to its right and then add the layer tab. + * Defaults to true. + */ append?: Computable; } +/** A tree node that is associated with a given layer, and which opens the layer when clicked. */ export type LayerTreeNode = Replace< TreeNode, { @@ -149,6 +192,7 @@ export type LayerTreeNode = Replace< append: GetComputableType; } >; +/** A type that matches any valid {@link LayerTreeNode} object. */ export type GenericLayerTreeNode = Replace< LayerTreeNode, { @@ -157,6 +201,10 @@ export type GenericLayerTreeNode = Replace< } >; +/** + * Lazily creates a tree node that's associated with a specific layer, with the given options. + * @param optionsFunc A function that returns the options object for this tree node. + */ export function createLayerTreeNode( optionsFunc: OptionsFunc ): LayerTreeNode { @@ -184,6 +232,18 @@ export function createLayerTreeNode( }) as unknown as LayerTreeNode; } +/** + * Takes an array of modifier "sections", and creates a JSXFunction that can render all those sections, and allow each section to be collapsed. + * Also returns a list of persistent refs that are used to control which sections are currently collapsed. + * @param sections An array of options objects for each section to display. + * @param sections.title The header for this modifier. + * @param sections.subtitle A subtitle for this modifier, e.g. to explain the context for the modifier. + * @param sections.modifier The modifier to be displaying in this section. + * @param sections.base The base value being modified. + * @param sections.unit The unit of measurement for the base. + * @param sections.baseText The label to call the base amount. + * @param sections.visible Whether or not this section should be currently visible to the player. + */ export function createCollapsibleModifierSections( sections: { title: string; @@ -249,6 +309,11 @@ export function createCollapsibleModifierSections( return [jsxFunc, collapsed]; } +/** + * Creates an HTML string for a span that writes some given text in a given color. + * @param textToColor The content to change the color of + * @param color The color to change the content to look like. Defaults to the current theme's accent 2 variable. + */ export function colorText(textToColor: string, color = "var(--accent2)"): string { return `${textToColor}`; } diff --git a/src/data/projEntry.tsx b/src/data/projEntry.tsx index 8ad9113..34a67a0 100644 --- a/src/data/projEntry.tsx +++ b/src/data/projEntry.tsx @@ -73,15 +73,27 @@ export const main = createLayer("main", () => { }; }); +/** + * Given a player save data object being loaded, return a list of layers that should currently be enabled. + * If your project does not use dynamic layers, this should just return all layers. + */ export const getInitialLayers = ( /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ player: Partial ): Array => [main, prestige]; +/** + * A computed ref whose value is true whenever the game is over. + */ export const hasWon = computed(() => { return false; }); +/** + * Given a player save data object being loaded with a different version, update the save data object to match the structure of the current version. + * @param oldVersion The version of the save being loaded in + * @param player The save data being loaded in + */ /* eslint-disable @typescript-eslint/no-unused-vars */ export function fixOldSave( oldVersion: string | undefined, diff --git a/src/data/themes.ts b/src/data/themes.ts index ae7e55a..7a24e1b 100644 --- a/src/data/themes.ts +++ b/src/data/themes.ts @@ -1,3 +1,4 @@ +/** A object of all CSS variables determined by the current theme. */ export interface ThemeVars { "--foreground": string; "--background": string; @@ -19,14 +20,20 @@ export interface ThemeVars { "--feature-margin": string; } +/** An object representing a theme the player can use to change the look of the game. */ export interface Theme { + /** The values of the theme's CSS variables. */ variables: ThemeVars; + /** Whether or not tabs should "float" in the center of their container. */ floatingTabs: boolean; + /** Whether or not adjacent features should merge together - removing the margin between them, and only applying the border radius to the first and last elements in the row or column. */ mergeAdjacent: boolean; + /** Whether or not to show a pin icon on pinned tooltips. */ showPin: boolean; } declare module "@vue/runtime-dom" { + /** Make CSS properties accept any CSS variables usually controlled by a theme. */ // eslint-disable-next-line @typescript-eslint/no-empty-interface interface CSSProperties extends Partial {} @@ -62,6 +69,7 @@ const defaultTheme: Theme = { showPin: true }; +/** An enum of all available themes and their internal IDs. The keys are their display names. */ export enum Themes { Classic = "classic", Paper = "paper", @@ -69,6 +77,7 @@ export enum Themes { Aqua = "aqua" } +/** A dictionary of all available themes. */ export default { classic: defaultTheme, paper: { From f90e226fe1e57a156ce57aacaf597615b4bdee4e Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sun, 10 Jul 2022 02:20:42 -0500 Subject: [PATCH 33/37] Update TS --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3f3934e..83758fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,7 +37,7 @@ "eslint": "^8.6.0", "jsdom": "^20.0.0", "prettier": "^2.5.1", - "typescript": "~4.5.5", + "typescript": "^4.7.4", "vitest": "^0.17.1", "vue-tsc": "^0.38.1" }, @@ -6735,9 +6735,9 @@ } }, "node_modules/typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -12284,9 +12284,9 @@ "dev": true }, "typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "dev": true }, "unbox-primitive": { diff --git a/package.json b/package.json index d4d3c1f..97cbc7f 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "eslint": "^8.6.0", "jsdom": "^20.0.0", "prettier": "^2.5.1", - "typescript": "~4.5.5", + "typescript": "^4.7.4", "vitest": "^0.17.1", "vue-tsc": "^0.38.1" }, From 717f13ebe0c540011458f756ba767dd7a933e9c4 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sun, 10 Jul 2022 02:20:51 -0500 Subject: [PATCH 34/37] Fix typing errors --- src/features/particles/Particles.vue | 2 +- src/game/layers.tsx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/features/particles/Particles.vue b/src/features/particles/Particles.vue index d5ecdcb..04307d0 100644 --- a/src/features/particles/Particles.vue +++ b/src/features/particles/Particles.vue @@ -46,7 +46,7 @@ export default defineComponent({ backgroundAlpha: 0 }); resizeListener.value?.appendChild(app.value.view); - props.onInit(app.value as Application); + props.onInit?.(app.value as Application); } updateBounds(); if (props.onHotReload) { diff --git a/src/game/layers.tsx b/src/game/layers.tsx index e8d22c3..ea40350 100644 --- a/src/game/layers.tsx +++ b/src/game/layers.tsx @@ -35,7 +35,7 @@ export interface FeatureNode { * An injection key that a {@link Context} will use to provide a function that registers a {@link FeatureNode} with the given id and HTML element. */ export const RegisterNodeInjectionKey: InjectionKey<(id: string, element: HTMLElement) => void> = - Symbol("RegisterNode"); + Symbol("RegisterNode"); /** * An injection key that a {@link Context} will use to provide a function that unregisters a {@link FeatureNode} with the given id. */ @@ -196,7 +196,9 @@ export function createLayer( const layer = {} as T & Partial; const emitter = (layer.emitter = createNanoEvents()); layer.on = emitter.on.bind(emitter); - layer.emit = emitter.emit.bind(emitter); + layer.emit = emitter.emit.bind(emitter) as ( + ...args: [K, ...Parameters] + ) => void; layer.nodes = ref({}); layer.id = id; From be96fcdd38fedb69080d506a73ca81ec0a9363da Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sun, 10 Jul 2022 03:00:08 -0500 Subject: [PATCH 35/37] Fixed broken links --- src/features/conversion.ts | 12 ++++++------ src/features/feature.ts | 4 ++-- src/game/layers.tsx | 24 ++++++++++++------------ 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/features/conversion.ts b/src/features/conversion.ts index c334b6e..d140cc3 100644 --- a/src/features/conversion.ts +++ b/src/features/conversion.ts @@ -15,7 +15,7 @@ import { computed, unref } from "vue"; /** An object that configures a {@link Conversion}. */ export interface ConversionOptions { /** - * The scaling function that is used to determine the rate of conversion from one {@link Resource} to the other. + * The scaling function that is used to determine the rate of conversion from one {@link features/resources/resource.Resource} to the other. */ scaling: ScalingFunction; /** @@ -41,11 +41,11 @@ export interface ConversionOptions { */ nextAt?: Computable; /** - * The input {@link Resource} for this conversion. + * The input {@link features/resources/resource.Resource} for this conversion. */ baseResource: Resource; /** - * The output {@link Resource} for this conversion. i.e. the resource being generated. + * The output {@link features/resources/resource.Resource} for this conversion. i.e. the resource being generated. */ gainResource: Resource; /** @@ -76,7 +76,7 @@ export interface ConversionOptions { /** * An additional modifier that will be applied to the gain amounts. * Must be reversible in order to correctly calculate {@link nextAt}. - * @see {@link createSequentialModifier} if you want to apply multiple modifiers. + * @see {@link game/modifiers.createSequentialModifier} if you want to apply multiple modifiers. */ gainModifier?: WithRequired; /** @@ -84,7 +84,7 @@ export interface ConversionOptions { * That is to say, this modifier will be applied to the amount of baseResource before going into the scaling function. * A cost modifier of x0.5 would give gain amounts equal to the player having half the baseResource they actually have. * Must be reversible in order to correctly calculate {@link nextAt}. - * @see {@link createSequentialModifier} if you want to apply multiple modifiers. + * @see {@link game/modifiers.createSequentialModifier} if you want to apply multiple modifiers. */ costModifier?: WithRequired; } @@ -99,7 +99,7 @@ export interface BaseConversion { convert: VoidFunction; } -/** An object that converts one {@link Resource} into another at a given rate. */ +/** An object that converts one {@link features/resources/resource.Resource} into another at a given rate. */ export type Conversion = Replace< T & BaseConversion, { diff --git a/src/features/feature.ts b/src/features/feature.ts index c2f34f5..ae14e29 100644 --- a/src/features/feature.ts +++ b/src/features/feature.ts @@ -5,12 +5,12 @@ import { isRef } from "vue"; /** * A symbol to use as a key for a vue component a feature can be rendered with - * @see {@link VueFeature} + * @see {@link util/vue.VueFeature} */ export const Component = Symbol("Component"); /** * A symbol to use as a key for a prop gathering function that a feature can use to send to its component - * @see {@link VueFeature} + * @see {@link util/vue.VueFeature} */ export const GatherProps = Symbol("GatherProps"); diff --git a/src/game/layers.tsx b/src/game/layers.tsx index ea40350..2ecae92 100644 --- a/src/game/layers.tsx +++ b/src/game/layers.tsx @@ -32,22 +32,22 @@ export interface FeatureNode { } /** - * An injection key that a {@link Context} will use to provide a function that registers a {@link FeatureNode} with the given id and HTML element. + * An injection key that a {@link ContextComponent} will use to provide a function that registers a {@link FeatureNode} with the given id and HTML element. */ export const RegisterNodeInjectionKey: InjectionKey<(id: string, element: HTMLElement) => void> = Symbol("RegisterNode"); /** - * An injection key that a {@link Context} will use to provide a function that unregisters a {@link FeatureNode} with the given id. + * An injection key that a {@link ContextComponent} will use to provide a function that unregisters a {@link FeatureNode} with the given id. */ export const UnregisterNodeInjectionKey: InjectionKey<(id: string) => void> = Symbol("UnregisterNode"); /** - * An injection key that a {@link Context} will use to provide a ref to a map of all currently registered {@link FeatureNode}s. + * An injection key that a {@link ContextComponent} will use to provide a ref to a map of all currently registered {@link FeatureNode}s. */ export const NodesInjectionKey: InjectionKey>> = Symbol("Nodes"); /** - * An injection key that a {@link Context} will use to provide a ref to a bounding rect of the Context. + * An injection key that a {@link ContextComponent} will use to provide a ref to a bounding rect of the Context. */ export const BoundsInjectionKey: InjectionKey> = Symbol("Bounds"); @@ -93,14 +93,14 @@ export interface Position { /** * An object that configures a {@link Layer}. * Even moreso than features, the developer is expected to include extra properties in this object. - * All {@link persistent} refs must be included somewhere within the layer object. + * All {@link game/persistence.Persistent} refs must be included somewhere within the layer object. */ export interface LayerOptions { /** The color of the layer, used to theme the entire layer's display. */ color?: Computable; /** * The layout of this layer's features. - * When the layer is open in {@link player.tabs}, this is the content that is display. + * When the layer is open in {@link game/player.PlayerData.tabs}, this is the content that is display. */ display: Computable; /** An object of classes that should be applied to the display. */ @@ -109,7 +109,7 @@ export interface LayerOptions { style?: Computable; /** * The name of the layer, used on minimized tabs. - * Defaults to {@link id}. + * Defaults to {@link BaseLayer.id}. */ name?: Computable; /** @@ -119,7 +119,7 @@ export interface LayerOptions { minimizable?: Computable; /** * Whether or not to force the go back button to be hidden. - * If true, go back will be hidden regardless of {@link projInfo.allowGoBack}. + * If true, go back will be hidden regardless of {@link data/projInfo.allowGoBack}. */ forceHideGoBack?: Computable; /** @@ -146,7 +146,7 @@ export interface BaseLayer { on: OmitThisParameter["on"]>; /** A function to emit a {@link LayerEvents} event to this layer. */ emit: (...args: [K, ...Parameters]) => void; - /** A map of {@link FeatureNode}s present in this layer's {@link Context} component. */ + /** A map of {@link FeatureNode}s present in this layer's {@link ContextComponent} component. */ nodes: Ref>; } @@ -230,8 +230,8 @@ export function createLayer( /** * Enables a layer object, so it will be updated every tick. * Note that accessing a layer/its properties does NOT require it to be enabled. - * For dynamic layers you can call this function and {@link removeLayer} as necessary. Just make sure {@link projEntry.getInitialLayers} will provide an accurate list of layers based on the player data object. - * For static layers just make {@link projEntry.getInitialLayers} return all the layers. + * For dynamic layers you can call this function and {@link removeLayer} as necessary. Just make sure {@link data/projEntry.getInitialLayers} will provide an accurate list of layers based on the player data object. + * For static layers just make {@link data/projEntry.getInitialLayers} return all the layers. * @param layer The layer to add. * @param player The player data object, which will have a data object for this layer. */ @@ -291,7 +291,7 @@ export function reloadLayer(layer: GenericLayer): void { } /** - * Utility function for creating a modal that display's a {@link layer.display}. + * Utility function for creating a modal that display's a {@link LayerOptions.display}. * Returns the modal itself, which can be rendered anywhere you need, as well as a function to open the modal. * @param layer The layer to display in the modal. */ From 4b769a022ac702f2dc4d5949c711a9798534d9eb Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Mon, 11 Jul 2022 07:55:00 -0500 Subject: [PATCH 36/37] Remove browserslist --- package.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/package.json b/package.json index 97cbc7f..d756ce7 100644 --- a/package.json +++ b/package.json @@ -44,11 +44,6 @@ "vitest": "^0.17.1", "vue-tsc": "^0.38.1" }, - "browserslist": [ - "> 1%", - "last 2 versions", - "not dead" - ], "engines": { "node": "16.x" } From fbfecbe4f6224153b4d5adb40db2c92aab77397e Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Mon, 11 Jul 2022 07:56:02 -0500 Subject: [PATCH 37/37] Removed lodash.clonedeep --- package-lock.json | 42 ------------------------------------------ package.json | 2 -- 2 files changed, 44 deletions(-) diff --git a/package-lock.json b/package-lock.json index 83758fe..a43ed9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,6 @@ "@vitejs/plugin-vue": "^2.3.3", "@vitejs/plugin-vue-jsx": "^1.3.10", "is-plain-object": "^5.0.0", - "lodash.clonedeep": "^4.5.0", "lz-string": "^1.4.4", "nanoevents": "^6.0.2", "pixi.js": "^6.3.0", @@ -30,7 +29,6 @@ "devDependencies": { "@ivanv/vue-collapse-transition": "^1.0.2", "@rushstack/eslint-patch": "^1.1.0", - "@types/lodash.clonedeep": "^4.5.6", "@types/lz-string": "^1.3.34", "@vue/eslint-config-prettier": "^7.0.0", "@vue/eslint-config-typescript": "^10.0.0", @@ -2384,21 +2382,6 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, - "node_modules/@types/lodash": { - "version": "4.14.182", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", - "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==", - "dev": true - }, - "node_modules/@types/lodash.clonedeep": { - "version": "4.5.7", - "resolved": "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.7.tgz", - "integrity": "sha512-ccNqkPptFIXrpVqUECi60/DFxjNKsfoQxSQsgcBJCX/fuX1wgyQieojkcWH/KpE3xzLoWN/2k+ZeGqIN3paSvw==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, "node_modules/@types/lz-string": { "version": "1.3.34", "resolved": "https://registry.npmjs.org/@types/lz-string/-/lz-string-1.3.34.tgz", @@ -5528,11 +5511,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" - }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -9196,21 +9174,6 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, - "@types/lodash": { - "version": "4.14.182", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", - "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==", - "dev": true - }, - "@types/lodash.clonedeep": { - "version": "4.5.7", - "resolved": "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.7.tgz", - "integrity": "sha512-ccNqkPptFIXrpVqUECi60/DFxjNKsfoQxSQsgcBJCX/fuX1wgyQieojkcWH/KpE3xzLoWN/2k+ZeGqIN3paSvw==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, "@types/lz-string": { "version": "1.3.34", "resolved": "https://registry.npmjs.org/@types/lz-string/-/lz-string-1.3.34.tgz", @@ -11399,11 +11362,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" - }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", diff --git a/package.json b/package.json index d756ce7..a1c3b2f 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "@vitejs/plugin-vue": "^2.3.3", "@vitejs/plugin-vue-jsx": "^1.3.10", "is-plain-object": "^5.0.0", - "lodash.clonedeep": "^4.5.0", "lz-string": "^1.4.4", "nanoevents": "^6.0.2", "pixi.js": "^6.3.0", @@ -33,7 +32,6 @@ "devDependencies": { "@ivanv/vue-collapse-transition": "^1.0.2", "@rushstack/eslint-patch": "^1.1.0", - "@types/lodash.clonedeep": "^4.5.6", "@types/lz-string": "^1.3.34", "@vue/eslint-config-prettier": "^7.0.0", "@vue/eslint-config-typescript": "^10.0.0",