forked from profectus/Profectus
Fixing building / cleanup
This commit is contained in:
parent
6f781b33fa
commit
15a460bf42
51 changed files with 5727 additions and 15879 deletions
18
.eslintrc.js
18
.eslintrc.js
|
@ -1,23 +1,27 @@
|
|||
require("@rushstack/eslint-patch/modern-module-resolution");
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
'vue/setup-compiler-macros': true
|
||||
node: true
|
||||
},
|
||||
extends: [
|
||||
"plugin:vue/vue3-essential",
|
||||
"eslint:recommended",
|
||||
"@vue/typescript/recommended",
|
||||
"@vue/prettier",
|
||||
"@vue/prettier/@typescript-eslint"
|
||||
"@vue/eslint-config-typescript/recommended",
|
||||
"@vue/eslint-config-prettier"
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020
|
||||
},
|
||||
ignorePatterns: ["src/lib"],
|
||||
rules: {
|
||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||
"vue/script-setup-uses-vars": "error",
|
||||
"vue/script-setup-uses-vars": "warn",
|
||||
"vue/no-mutating-props": "off"
|
||||
},
|
||||
globals: {
|
||||
defineProps: "readonly",
|
||||
defineEmits: "readonly"
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
{
|
||||
"arrowParens": "avoid",
|
||||
"endOfLine": "auto",
|
||||
"printWidth": 100,
|
||||
"tabWidth": 4
|
||||
"tabWidth": 4,
|
||||
"trailingComma": "none"
|
||||
}
|
||||
|
|
20968
package-lock.json
generated
20968
package-lock.json
generated
File diff suppressed because it is too large
Load diff
21
package.json
21
package.json
|
@ -22,24 +22,21 @@
|
|||
"devDependencies": {
|
||||
"@ivanv/vue-collapse-transition": "^1.0.2",
|
||||
"@jetblack/operator-overloading": "^0.2.0",
|
||||
"@rushstack/eslint-patch": "^1.1.0",
|
||||
"@types/lodash.clonedeep": "^4.5.6",
|
||||
"@typescript-eslint/eslint-plugin": "^5.9.1",
|
||||
"@typescript-eslint/parser": "^5.9.1",
|
||||
"@vue/babel-plugin-jsx": "^1.1.1",
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-plugin-typescript": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"@vue/cli-plugin-babel": "~5.0.0-rc.1",
|
||||
"@vue/cli-plugin-eslint": "~5.0.0-rc.1",
|
||||
"@vue/cli-plugin-typescript": "~5.0.0-rc.1",
|
||||
"@vue/cli-service": "~5.0.0-rc.1",
|
||||
"@vue/compiler-sfc": "^3.2.26",
|
||||
"@vue/eslint-config-prettier": "^6.0.0",
|
||||
"@vue/eslint-config-prettier": "^7.0.0",
|
||||
"@vue/eslint-config-typescript": "^10.0.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^8.6.0",
|
||||
"eslint-plugin-prettier": "^3.4.0",
|
||||
"eslint-plugin-vue": "^8.3.0",
|
||||
"prettier": "^1.19.1",
|
||||
"prettier": "^2.5.1",
|
||||
"raw-loader": "^4.0.2",
|
||||
"sass": "^1.36.0",
|
||||
"sass": "^1.48.0",
|
||||
"sass-loader": "^10.2.0",
|
||||
"tsconfig-paths-webpack-plugin": "^3.5.1",
|
||||
"typescript": "^4.5.4"
|
||||
|
@ -53,7 +50,7 @@
|
|||
"pre-commit": "lint-staged"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,vue}": [
|
||||
"*.{js,jsx,ts,tsx,vue}": [
|
||||
"vue-cli-service lint",
|
||||
"git add"
|
||||
]
|
||||
|
|
|
@ -14,6 +14,7 @@ import { computed, toRef } from "vue";
|
|||
import Game from "./components/system/Game.vue";
|
||||
import GameOverScreen from "./components/system/GameOverScreen.vue";
|
||||
import NaNScreen from "./components/system/NaNScreen.vue";
|
||||
import Nav from "./components/system/Nav.vue";
|
||||
import TPS from "./components/system/TPS.vue";
|
||||
import modInfo from "./data/modInfo.json";
|
||||
import themes from "./data/themes";
|
||||
|
|
|
@ -12,12 +12,14 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script lang="ts">
|
||||
import { FeatureComponent, Visibility } from "@/features/feature";
|
||||
import { GenericGrid } from "@/features/grid";
|
||||
import { defineComponent } from "vue";
|
||||
import GridCell from "./GridCell.vue";
|
||||
|
||||
defineProps<FeatureComponent<GenericGrid>>();
|
||||
// https://github.com/thepaperpilot/The-Modding-Tree-X/issues/1
|
||||
export default defineComponent(function Grid(props: FeatureComponent<GenericGrid>) {
|
||||
return { ...props, GridCell, Visibility };
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
:disabled="!canClick"
|
||||
>
|
||||
<div v-if="title"><component :is="titleComponent" /></div>
|
||||
<component :is="component" style="white-space: pre-line;" />
|
||||
<component :is="component" style="white-space: pre-line" />
|
||||
<LinkNode :id="id" />
|
||||
</button>
|
||||
</template>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import themes from "@/data/themes";
|
||||
import { FeatureComponent } from "@/features/feature";
|
||||
import { FeatureComponent, PersistentState } from "@/features/feature";
|
||||
import { GenericTabFamily } from "@/features/tabFamily";
|
||||
import settings from "@/game/settings";
|
||||
import { coerceComponent, isCoercableComponent } from "@/util/vue";
|
||||
|
@ -52,7 +52,7 @@ const style = computed(() => {
|
|||
});
|
||||
|
||||
function selectTab(tab: string) {
|
||||
props.state.value = tab;
|
||||
props[PersistentState].value = tab;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { BoardNode, GenericBoard, getNodeProperty } from "@/features/board";
|
||||
import { FeatureComponent, Visibility } from "@/features/feature";
|
||||
import { FeatureComponent, PersistentState, Visibility } from "@/features/feature";
|
||||
import { computed, ref, toRefs } from "vue";
|
||||
import panZoom from "vue-panzoom";
|
||||
import BoardLinkVue from "./BoardLink.vue";
|
||||
|
@ -147,8 +147,8 @@ function mouseDown(e: MouseEvent | TouchEvent, nodeID: number | null = null, dra
|
|||
}
|
||||
}
|
||||
if (nodeID != null) {
|
||||
props.state.value.selectedNode = null;
|
||||
props.state.value.selectedAction = null;
|
||||
props[PersistentState].value.selectedNode = null;
|
||||
props[PersistentState].value.selectedAction = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,8 +206,8 @@ function endDragging(nodeID: number | null) {
|
|||
|
||||
dragging.value = null;
|
||||
} else if (!hasDragged.value) {
|
||||
props.state.value.selectedNode = null;
|
||||
props.state.value.selectedAction = null;
|
||||
props[PersistentState].value.selectedNode = null;
|
||||
props[PersistentState].value.selectedAction = null;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -13,14 +13,16 @@
|
|||
:key="action.id"
|
||||
class="action"
|
||||
:class="{ selected: selectedAction?.id === action.id }"
|
||||
:transform="
|
||||
`translate(
|
||||
${(-size - 30) *
|
||||
Math.sin(((actions.length - 1) / 2 - index) * actionDistance)},
|
||||
${(size + 30) *
|
||||
Math.cos(((actions.length - 1) / 2 - index) * actionDistance)}
|
||||
)`
|
||||
"
|
||||
:transform="`translate(
|
||||
${
|
||||
(-size - 30) *
|
||||
Math.sin(((actions.length - 1) / 2 - index) * actionDistance)
|
||||
},
|
||||
${
|
||||
(size + 30) *
|
||||
Math.cos(((actions.length - 1) / 2 - index) * actionDistance)
|
||||
}
|
||||
)`"
|
||||
@mousedown="e => performAction(e, action)"
|
||||
@touchstart="e => performAction(e, action)"
|
||||
@mouseup="e => actionMouseUp(e, action)"
|
||||
|
@ -91,9 +93,9 @@
|
|||
class="receiver"
|
||||
:width="size * sqrtTwo + 16"
|
||||
:height="size * sqrtTwo + 16"
|
||||
:transform="
|
||||
`translate(${-(size * sqrtTwo + 16) / 2}, ${-(size * sqrtTwo + 16) / 2})`
|
||||
"
|
||||
:transform="`translate(${-(size * sqrtTwo + 16) / 2}, ${
|
||||
-(size * sqrtTwo + 16) / 2
|
||||
})`"
|
||||
:fill="backgroundColor"
|
||||
:stroke="receivingNode ? '#0F0' : '#0F03'"
|
||||
:stroke-width="2"
|
||||
|
@ -114,12 +116,9 @@
|
|||
class="progressFill"
|
||||
:width="Math.max(size * sqrtTwo * progress - 2, 0)"
|
||||
:height="Math.max(size * sqrtTwo * progress - 2, 0)"
|
||||
:transform="
|
||||
`translate(${-Math.max(size * sqrtTwo * progress - 2, 0) / 2}, ${-Math.max(
|
||||
size * sqrtTwo * progress - 2,
|
||||
0
|
||||
) / 2})`
|
||||
"
|
||||
:transform="`translate(${-Math.max(size * sqrtTwo * progress - 2, 0) / 2}, ${
|
||||
-Math.max(size * sqrtTwo * progress - 2, 0) / 2
|
||||
})`"
|
||||
:fill="progressColor"
|
||||
/>
|
||||
<rect
|
||||
|
@ -127,9 +126,9 @@
|
|||
class="progressDiamond"
|
||||
:width="size * sqrtTwo + 9"
|
||||
:height="size * sqrtTwo + 9"
|
||||
:transform="
|
||||
`translate(${-(size * sqrtTwo + 9) / 2}, ${-(size * sqrtTwo + 9) / 2})`
|
||||
"
|
||||
:transform="`translate(${-(size * sqrtTwo + 9) / 2}, ${
|
||||
-(size * sqrtTwo + 9) / 2
|
||||
})`"
|
||||
fill="transparent"
|
||||
:stroke-dasharray="(size * sqrtTwo + 9) * 4"
|
||||
:stroke-width="5"
|
||||
|
|
|
@ -20,12 +20,16 @@
|
|||
</span>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script lang="ts">
|
||||
import { FeatureComponent, wrapFeature } from "@/features/feature";
|
||||
import { GenericTree } from "@/features/tree";
|
||||
import { defineComponent } from "vue";
|
||||
import TreeNode from "./TreeNode.vue";
|
||||
|
||||
defineProps<FeatureComponent<GenericTree>>();
|
||||
// https://github.com/thepaperpilot/The-Modding-Tree-X/issues/1
|
||||
export default defineComponent(function Grid(props: FeatureComponent<GenericTree>) {
|
||||
return { ...props, TreeNode, wrapFeature };
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -2,8 +2,18 @@
|
|||
<Tooltip
|
||||
v-if="visibility !== Visibility.None"
|
||||
v-show="visibility === Visibility.Visible"
|
||||
v-bind="typeof tooltip === 'object' ? wrapFeature(tooltip) : null"
|
||||
:display="typeof tooltip === 'object' ? unref(tooltip.display) : tooltip || ''"
|
||||
v-bind="
|
||||
typeof tooltip === 'object' && !isCoercableComponent(tooltip)
|
||||
? wrapFeature(tooltip)
|
||||
: null
|
||||
"
|
||||
:display="
|
||||
typeof tooltip === 'object'
|
||||
? isCoercableComponent(tooltip)
|
||||
? unref(tooltip)
|
||||
: tooltip.display
|
||||
: tooltip || ''
|
||||
"
|
||||
:force="forceTooltip"
|
||||
:class="{
|
||||
treeNode: true,
|
||||
|
@ -38,7 +48,7 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { GenericTreeNode } from "@/features/tree";
|
||||
import { coerceComponent, setupHoldToClick } from "@/util/vue";
|
||||
import { coerceComponent, isCoercableComponent, setupHoldToClick } from "@/util/vue";
|
||||
import { computed, toRefs, unref } from "vue";
|
||||
import Tooltip from "@/components/system/Tooltip.vue";
|
||||
import MarkNode from "../MarkNode.vue";
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<template>
|
||||
<form @submit.prevent="submit">
|
||||
<div class="field">
|
||||
<span class="field-title" v-if="titleComponent"><component :is="titleComponent"/></span>
|
||||
<span class="field-title" v-if="titleComponent"
|
||||
><component :is="titleComponent"
|
||||
/></span>
|
||||
<VueTextareaAutosize
|
||||
v-if="textArea"
|
||||
v-model="value"
|
||||
|
|
|
@ -17,9 +17,7 @@
|
|||
Aarex
|
||||
</div>
|
||||
<br />
|
||||
<div class="link" @click="openChangelog">
|
||||
Changelog
|
||||
</div>
|
||||
<div class="link" @click="openChangelog">Changelog</div>
|
||||
<br />
|
||||
<div>
|
||||
<a
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
<template>
|
||||
<div class="layer-container">
|
||||
<button v-if="showGoBack" class="goBack" @click="goBack">
|
||||
←
|
||||
</button>
|
||||
<button v-if="showGoBack" class="goBack" @click="goBack">←</button>
|
||||
<button class="layer-tab minimized" v-if="minimized" @click="minimized = false">
|
||||
<div>{{ name }}</div>
|
||||
</button>
|
||||
|
@ -12,9 +10,7 @@
|
|||
</Links>
|
||||
<component v-else :is="component" />
|
||||
</div>
|
||||
<button v-if="minimizable" class="minimize" @click="minimized = true">
|
||||
▼
|
||||
</button>
|
||||
<button v-if="minimizable" class="minimize" @click="minimized = true">▼</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
v-for="(link, index) in validLinks"
|
||||
:key="index"
|
||||
:link="link"
|
||||
:startNode="nodes[link.startNode.id]"
|
||||
:endNode="nodes[link.endNode.id]"
|
||||
:startNode="nodes[link.startNode.id]!"
|
||||
:endNode="nodes[link.endNode.id]!"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
|
@ -24,16 +24,31 @@ import LinkVue from "./Link.vue";
|
|||
|
||||
const props = toRefs(defineProps<{ links: Link[] }>());
|
||||
|
||||
const observer = new MutationObserver(updateNodes);
|
||||
const resizeObserver = new ResizeObserver(updateBounds);
|
||||
|
||||
const nodes = ref<Record<string, LinkNode | undefined>>({});
|
||||
const boundingRect = ref(new DOMRect());
|
||||
|
||||
const resizeListener = ref<Element | null>(null);
|
||||
|
||||
onMounted(() => {
|
||||
// ResizeListener exists because ResizeObserver's don't work when told to observe an SVG element
|
||||
const resListener = resizeListener.value;
|
||||
if (resListener != null) {
|
||||
resizeObserver.observe(resListener);
|
||||
}
|
||||
updateNodes();
|
||||
});
|
||||
|
||||
const validLinks = computed(() =>
|
||||
unref(props.links.value).filter(link => {
|
||||
const n = nodes.value;
|
||||
return (
|
||||
link.startNode.id in n &&
|
||||
link.endNode.id in n &&
|
||||
n[link.startNode.id].x != undefined &&
|
||||
n[link.startNode.id].y != undefined &&
|
||||
n[link.endNode.id].x != undefined &&
|
||||
n[link.endNode.id].y != undefined
|
||||
n[link.startNode.id]?.x != undefined &&
|
||||
n[link.startNode.id]?.y != undefined &&
|
||||
n[link.endNode.id]?.x != undefined &&
|
||||
n[link.endNode.id]?.y != undefined
|
||||
);
|
||||
})
|
||||
);
|
||||
|
@ -54,7 +69,7 @@ provide(RegisterLinkNodeInjectionKey, (id, element) => {
|
|||
});
|
||||
});
|
||||
provide(UnregisterLinkNodeInjectionKey, id => {
|
||||
delete nodes.value[id];
|
||||
nodes.value[id] = undefined;
|
||||
});
|
||||
|
||||
function updateNodes() {
|
||||
|
@ -64,12 +79,13 @@ function updateNodes() {
|
|||
}
|
||||
|
||||
function updateNode(id: string) {
|
||||
if (!(id in nodes.value)) {
|
||||
const node = nodes.value[id];
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
const linkStartRect = nodes.value[id].element.getBoundingClientRect();
|
||||
nodes.value[id].x = linkStartRect.x + linkStartRect.width / 2 - boundingRect.value.x;
|
||||
nodes.value[id].y = linkStartRect.y + linkStartRect.height / 2 - boundingRect.value.y;
|
||||
const linkStartRect = node.element.getBoundingClientRect();
|
||||
node.x = linkStartRect.x + linkStartRect.width / 2 - boundingRect.value.x;
|
||||
node.y = linkStartRect.y + linkStartRect.height / 2 - boundingRect.value.y;
|
||||
}
|
||||
|
||||
function updateBounds() {
|
||||
|
@ -78,23 +94,6 @@ function updateBounds() {
|
|||
updateNodes();
|
||||
}
|
||||
}
|
||||
|
||||
const observer = new MutationObserver(updateNodes);
|
||||
const resizeObserver = new ResizeObserver(updateBounds);
|
||||
|
||||
const nodes = ref<Record<string, LinkNode>>({});
|
||||
const boundingRect = ref(new DOMRect());
|
||||
|
||||
const resizeListener = ref<Element | null>(null);
|
||||
|
||||
onMounted(() => {
|
||||
// ResizeListener exists because ResizeObserver's don't work when told to observe an SVG element
|
||||
const resListener = resizeListener.value;
|
||||
if (resListener != null) {
|
||||
resizeObserver.observe(resListener);
|
||||
}
|
||||
updateNodes();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -14,16 +14,13 @@
|
|||
<div class="modal-wrapper">
|
||||
<div class="modal-container">
|
||||
<div class="modal-header">
|
||||
<slot name="header" :shown="isOpen">
|
||||
default header
|
||||
</slot>
|
||||
<slot name="header" :shown="isOpen"> default header </slot>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<branches>
|
||||
<slot name="body" :shown="isOpen">
|
||||
default body
|
||||
</slot>
|
||||
</branches>
|
||||
<Links v-if="links" :links="links">
|
||||
<slot name="body" :shown="isOpen"> default body </slot>
|
||||
</Links>
|
||||
<slot name="body" v-else :shown="isOpen"> default body </slot>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<slot name="footer" :shown="isOpen">
|
||||
|
@ -43,10 +40,13 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Link } from "@/features/links";
|
||||
import { computed, ref } from "vue";
|
||||
import Links from "./Links.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean;
|
||||
links?: Link[];
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: "update:modelValue", value: boolean): void;
|
||||
|
|
|
@ -25,9 +25,7 @@
|
|||
</template>
|
||||
<template v-slot:footer>
|
||||
<div class="nan-footer">
|
||||
<button @click="savesManager?.open()" class="button">
|
||||
Open Saves Manager
|
||||
</button>
|
||||
<button @click="savesManager?.open()" class="button">Open Saves Manager</button>
|
||||
<button @click="setZero" class="button">Set to 0</button>
|
||||
<button @click="setOne" class="button">Set to 1</button>
|
||||
<button
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
><span>v{{ versionNumber }}</span></Tooltip
|
||||
>
|
||||
</div>
|
||||
<div style="flex-grow: 1; cursor: unset;"></div>
|
||||
<div style="flex-grow: 1; cursor: unset"></div>
|
||||
<div class="discord">
|
||||
<span @click="openDiscord" class="material-icons">discord</span>
|
||||
<ul class="discord-links">
|
||||
|
@ -54,7 +54,7 @@
|
|||
<div @click="changelog?.open()" class="version-container">
|
||||
<Tooltip display="Changelog" right xoffset="25%" class="version">
|
||||
<span>v{{ versionNumber }}</span>
|
||||
</tooltip>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div @click="savesManager?.open()">
|
||||
<Tooltip display="Saves" right>
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
<Save
|
||||
v-for="(save, index) in saves"
|
||||
:key="index"
|
||||
:save="save"
|
||||
@open="openSave(save.id)"
|
||||
@export="exportSave(save.id)"
|
||||
@editName="name => editSave(save.id, name)"
|
||||
@duplicate="duplicateSave(save.id)"
|
||||
@delete="deleteSave(save.id)"
|
||||
:save="save!"
|
||||
@open="openSave(save!.id)"
|
||||
@export="exportSave(save!.id)"
|
||||
@editName="name => editSave(save!.id, name)"
|
||||
@duplicate="duplicateSave(save!.id)"
|
||||
@delete="deleteSave(save!.id)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -122,7 +122,7 @@ let bank = ref(
|
|||
}, [])
|
||||
);
|
||||
|
||||
const saves = ref<Record<string, LoadablePlayerData>>({});
|
||||
const saves = ref<Record<string, LoadablePlayerData | undefined>>({});
|
||||
|
||||
function loadSaveData() {
|
||||
saves.value = settings.saves.reduce((acc: Record<string, LoadablePlayerData>, curr: string) => {
|
||||
|
@ -178,13 +178,15 @@ function duplicateSave(id: string) {
|
|||
function deleteSave(id: string) {
|
||||
settings.saves = settings.saves.filter((save: string) => save !== id);
|
||||
localStorage.removeItem(id);
|
||||
delete saves.value[id];
|
||||
saves.value[id] = undefined;
|
||||
}
|
||||
|
||||
function openSave(id: string) {
|
||||
saves.value[player.id].time = player.time;
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
saves.value[player.id]!.time = player.time;
|
||||
save();
|
||||
loadSave(saves.value[id]);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
loadSave(saves.value[id]!);
|
||||
}
|
||||
|
||||
function newSave() {
|
||||
|
|
|
@ -103,7 +103,7 @@ export function createResetButton<T extends ClickableOptions & ResetButtonOption
|
|||
onClick?.();
|
||||
};
|
||||
|
||||
const proxy = (createClickable(options) as unknown) as ResetButton<T>;
|
||||
const proxy = createClickable(options) as unknown as ResetButton<T>;
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ export type LayerTreeNode<T extends LayerTreeNodeOptions> = Replace<
|
|||
export function createLayerTreeNode<T extends LayerTreeNodeOptions>(options: T): LayerTreeNode<T> {
|
||||
processComputable(options as T, "append");
|
||||
|
||||
return (createTreeNode({
|
||||
return createTreeNode({
|
||||
...options,
|
||||
display: options.layerID,
|
||||
onClick:
|
||||
|
@ -141,5 +141,5 @@ export function createLayerTreeNode<T extends LayerTreeNodeOptions>(options: T):
|
|||
: function () {
|
||||
player.tabs.splice(1, 1, options.layerID);
|
||||
}
|
||||
}) as unknown) as LayerTreeNode<T>;
|
||||
}) as unknown as LayerTreeNode<T>;
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ const funChallenge = createChallenge({
|
|||
return showIf(Decimal.gt(best.value, 0));
|
||||
},
|
||||
goal: 20,
|
||||
resource: mainPoints,
|
||||
resource: () => mainPoints,
|
||||
onComplete() {
|
||||
console.log("hiii");
|
||||
},
|
||||
|
@ -249,10 +249,7 @@ const longBoi = createBar({
|
|||
width: 300,
|
||||
height: 30,
|
||||
progress() {
|
||||
return Decimal.add(mainPoints.value, 1)
|
||||
.log(10)
|
||||
.div(10)
|
||||
.toNumber();
|
||||
return Decimal.add(mainPoints.value, 1).log(10).div(10).toNumber();
|
||||
},
|
||||
display() {
|
||||
return format(mainPoints.value) + " / 1e10 points";
|
||||
|
@ -393,16 +390,16 @@ const tree = createTree({
|
|||
},
|
||||
branches: [
|
||||
{
|
||||
from: fNode,
|
||||
to: treeNode,
|
||||
startNode: fNode,
|
||||
endNode: treeNode,
|
||||
style: {
|
||||
strokeWidth: "25px",
|
||||
stroke: "blue",
|
||||
filter: "blur(5px)"
|
||||
}
|
||||
},
|
||||
{ from: treeNode, to: g },
|
||||
{ from: g, to: h }
|
||||
{ startNode: treeNode, endNode: g },
|
||||
{ startNode: g, endNode: h }
|
||||
]
|
||||
});
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import Modal from "@/components/system/Modal.vue";
|
||||
import Spacer from "@/components/system/Spacer.vue";
|
||||
import { createResource, trackBest, trackOOMPS, trackTotal } from "@/features/resource";
|
||||
import { createTree, GenericTree } from "@/features/tree";
|
||||
import { globalBus } from "@/game/events";
|
||||
|
@ -5,7 +7,8 @@ import { createLayer, GenericLayer } from "@/game/layers";
|
|||
import player, { PlayerData } from "@/game/player";
|
||||
import { DecimalSource } from "@/lib/break_eternity";
|
||||
import Decimal, { format, formatSmall, formatTime } from "@/util/bignum";
|
||||
import { computed } from "vue";
|
||||
import { render } from "@/util/vue";
|
||||
import { computed, ref } from "vue";
|
||||
import a from "./layers/aca/a";
|
||||
import c, {
|
||||
generatorUpgrade,
|
||||
|
@ -18,6 +21,7 @@ export const points = createResource<DecimalSource>(0);
|
|||
const best = trackBest(points);
|
||||
const total = trackTotal(points);
|
||||
const oomps = trackOOMPS(points);
|
||||
const showModal = ref(false);
|
||||
|
||||
const pointGain = computed(() => {
|
||||
if (!generatorUpgrade.bought) return new Decimal(0);
|
||||
|
@ -73,8 +77,8 @@ export const main = createLayer({
|
|||
<div v-if={Decimal.gt(pointGain.value, 0)}>
|
||||
({oomps.value === "" ? formatSmall(pointGain.value) : oomps.value}/sec)
|
||||
</div>
|
||||
<spacer />
|
||||
<modal show={false}>
|
||||
<Spacer />
|
||||
<Modal v-model={showModal}>
|
||||
<svg style="height: 80vmin; width: 80vmin;">
|
||||
<path d="M 32 222 Q 128 222, 128 0 Q 128 222, 224 222 L 224 224 L 32 224" />
|
||||
|
||||
|
@ -82,8 +86,8 @@ export const main = createLayer({
|
|||
<circle cx="128" cy="64" r="64" fill="#71368a" />
|
||||
<circle cx="192" cy="128" r="64" fill="#fa8508" />
|
||||
</svg>
|
||||
</modal>
|
||||
<tree {...tree} />
|
||||
</Modal>
|
||||
{render(tree)}
|
||||
</template>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
getUniqueID,
|
||||
makePersistent,
|
||||
Persistent,
|
||||
PersistentState,
|
||||
Replace,
|
||||
setDefault,
|
||||
StyleValue,
|
||||
|
@ -78,9 +79,9 @@ export function createAchievement<T extends AchievementOptions>(
|
|||
achievement.type = AchievementType;
|
||||
achievement[Component] = AchievementComponent;
|
||||
|
||||
achievement.earned = achievement.state;
|
||||
achievement.earned = achievement[PersistentState];
|
||||
achievement.complete = function () {
|
||||
proxy.state.value = true;
|
||||
proxy[PersistentState].value = true;
|
||||
};
|
||||
|
||||
processComputable(achievement as T, "visibility");
|
||||
|
@ -94,18 +95,17 @@ export function createAchievement<T extends AchievementOptions>(
|
|||
processComputable(achievement as T, "tooltip");
|
||||
setDefault(achievement, "tooltip", achievement.display);
|
||||
|
||||
const proxy = createProxy((achievement as unknown) as Achievement<T>);
|
||||
const proxy = createProxy(achievement as unknown as Achievement<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
const toast = useToast();
|
||||
|
||||
const listeners: Record<string, Unsubscribe> = {};
|
||||
const listeners: Record<string, Unsubscribe | undefined> = {};
|
||||
globalBus.on("addLayer", layer => {
|
||||
const achievements: GenericAchievement[] = (findFeatures(
|
||||
layer,
|
||||
AchievementType
|
||||
) as GenericAchievement[]).filter(ach => ach.shouldEarn != null);
|
||||
const achievements: GenericAchievement[] = (
|
||||
findFeatures(layer, AchievementType) as GenericAchievement[]
|
||||
).filter(ach => ach.shouldEarn != null);
|
||||
if (achievements.length) {
|
||||
listeners[layer.id] = layer.on("postUpdate", () => {
|
||||
achievements.forEach(achievement => {
|
||||
|
@ -114,7 +114,7 @@ globalBus.on("addLayer", layer => {
|
|||
!unref(achievement.earned) &&
|
||||
unref(achievement.shouldEarn)
|
||||
) {
|
||||
achievement.state.value = true;
|
||||
achievement[PersistentState].value = true;
|
||||
achievement.onComplete?.();
|
||||
if (achievement.display) {
|
||||
const display = unref(achievement.display);
|
||||
|
@ -133,5 +133,5 @@ globalBus.on("addLayer", layer => {
|
|||
globalBus.on("removeLayer", layer => {
|
||||
// unsubscribe from postUpdate
|
||||
listeners[layer.id]?.();
|
||||
delete listeners[layer.id];
|
||||
listeners[layer.id] = undefined;
|
||||
});
|
||||
|
|
|
@ -97,6 +97,6 @@ export function createBar<T extends BarOptions>(options: T & ThisType<Bar<T>>):
|
|||
processComputable(bar as T, "display");
|
||||
processComputable(bar as T, "mark");
|
||||
|
||||
const proxy = createProxy((bar as unknown) as Bar<T>);
|
||||
const proxy = createProxy(bar as unknown as Bar<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
getUniqueID,
|
||||
makePersistent,
|
||||
Persistent,
|
||||
PersistentState,
|
||||
Replace,
|
||||
setDefault,
|
||||
State,
|
||||
|
@ -208,9 +209,11 @@ export function createBoard<T extends BoardOptions>(options: T & ThisType<Board<
|
|||
board.type = BoardType;
|
||||
board[Component] = BoardComponent;
|
||||
|
||||
board.nodes = computed(() => proxy.state.value.nodes);
|
||||
board.nodes = computed(() => proxy[PersistentState].value.nodes);
|
||||
board.selectedNode = computed(
|
||||
() => proxy.nodes.value.find(node => node.id === proxy.state.value.selectedNode) || null
|
||||
() =>
|
||||
proxy.nodes.value.find(node => node.id === proxy[PersistentState].value.selectedNode) ||
|
||||
null
|
||||
);
|
||||
board.selectedAction = computed(() => {
|
||||
if (proxy.selectedNode.value == null) {
|
||||
|
@ -220,7 +223,11 @@ export function createBoard<T extends BoardOptions>(options: T & ThisType<Board<
|
|||
if (type.actions == null) {
|
||||
return null;
|
||||
}
|
||||
return type.actions.find(action => action.id === proxy.state.value.selectedAction) || null;
|
||||
return (
|
||||
type.actions.find(
|
||||
action => action.id === proxy[PersistentState].value.selectedAction
|
||||
) || null
|
||||
);
|
||||
});
|
||||
board.links = computed(() => {
|
||||
if (proxy.selectedAction.value == null) {
|
||||
|
@ -263,9 +270,11 @@ export function createBoard<T extends BoardOptions>(options: T & ThisType<Board<
|
|||
processComputable(nodeType, "titleColor");
|
||||
processComputable(nodeType, "actionDistance");
|
||||
setDefault(nodeType, "actionDistance", Math.PI / 6);
|
||||
nodeType.nodes = computed(() => proxy.state.value.nodes.filter(node => node.type === type));
|
||||
nodeType.nodes = computed(() =>
|
||||
proxy[PersistentState].value.nodes.filter(node => node.type === type)
|
||||
);
|
||||
setDefault(nodeType, "onClick", function (node: BoardNode) {
|
||||
proxy.state.value.selectedNode = node.id;
|
||||
proxy[PersistentState].value.selectedNode = node.id;
|
||||
});
|
||||
|
||||
if (nodeType.actions) {
|
||||
|
@ -279,10 +288,10 @@ export function createBoard<T extends BoardOptions>(options: T & ThisType<Board<
|
|||
}
|
||||
}
|
||||
|
||||
board.types[type] = createProxy((nodeType as unknown) as GenericNodeType);
|
||||
board.types[type] = createProxy(nodeType as unknown as GenericNodeType);
|
||||
}
|
||||
|
||||
const proxy = createProxy((board as unknown) as Board<T>);
|
||||
const proxy = createProxy(board as unknown as Board<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
@ -300,7 +309,7 @@ export function getUniqueNodeID(board: GenericBoard): number {
|
|||
return id;
|
||||
}
|
||||
|
||||
const listeners: Record<string, Unsubscribe> = {};
|
||||
const listeners: Record<string, Unsubscribe | undefined> = {};
|
||||
globalBus.on("addLayer", layer => {
|
||||
const boards: GenericBoard[] = findFeatures(layer, BoardType) as GenericBoard[];
|
||||
listeners[layer.id] = layer.on("postUpdate", (diff: Decimal) => {
|
||||
|
@ -313,6 +322,6 @@ globalBus.on("addLayer", layer => {
|
|||
});
|
||||
globalBus.on("removeLayer", layer => {
|
||||
// unsubscribe from postUpdate
|
||||
listeners[layer.id]();
|
||||
delete listeners[layer.id];
|
||||
listeners[layer.id]?.();
|
||||
listeners[layer.id] = undefined;
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
getUniqueID,
|
||||
makePersistent,
|
||||
Persistent,
|
||||
PersistentState,
|
||||
Replace,
|
||||
setDefault,
|
||||
StyleValue,
|
||||
|
@ -101,7 +102,7 @@ export function createBuyable<T extends BuyableOptions>(
|
|||
buyable.type = BuyableType;
|
||||
buyable[Component] = ClickableComponent;
|
||||
|
||||
buyable.amount = buyable.state;
|
||||
buyable.amount = buyable[PersistentState];
|
||||
buyable.bought = computed(() => Decimal.gt(proxy.amount.value, 0));
|
||||
buyable.canAfford = computed(
|
||||
() =>
|
||||
|
@ -177,6 +178,6 @@ export function createBuyable<T extends BuyableOptions>(
|
|||
processComputable(buyable as T, "mark");
|
||||
processComputable(buyable as T, "small");
|
||||
|
||||
const proxy = createProxy((buyable as unknown) as Buyable<T>);
|
||||
const proxy = createProxy(buyable as unknown as Buyable<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ export function createChallenge<T extends ChallengeOptions>(
|
|||
});
|
||||
}
|
||||
|
||||
const proxy = createProxy((challenge as unknown) as Challenge<T>);
|
||||
const proxy = createProxy(challenge as unknown as Challenge<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,6 +79,6 @@ export function createClickable<T extends ClickableOptions>(
|
|||
processComputable(clickable as T, "mark");
|
||||
processComputable(clickable as T, "display");
|
||||
|
||||
const proxy = createProxy((clickable as unknown) as Clickable<T>);
|
||||
const proxy = createProxy(clickable as unknown as Clickable<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ export function createConversion<T extends ConversionOptions>(
|
|||
processComputable(conversion as T, "roundUpCost");
|
||||
setDefault(conversion, "roundUpCost", true);
|
||||
|
||||
const proxy = createProxy((conversion as unknown) as Conversion<T>);
|
||||
const proxy = createProxy(conversion as unknown as Conversion<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,9 @@ import { GenericLayer } from "@/game/layers";
|
|||
import Decimal, { DecimalSource } from "@/util/bignum";
|
||||
import { ProcessedComputable } from "@/util/computed";
|
||||
import { isArray } from "@vue/shared";
|
||||
import { ComponentOptions, CSSProperties, DefineComponent, isRef, ref, Ref } from "vue";
|
||||
import { ComponentOptions, CSSProperties, DefineComponent, isRef, ref, Ref, UnwrapRef } from "vue";
|
||||
|
||||
export const PersistentState = Symbol("PersistentState");
|
||||
export const SetupPersistence = Symbol("SetupPersistence");
|
||||
export const DefaultValue = Symbol("DefaultValue");
|
||||
export const Component = Symbol("Component");
|
||||
|
@ -21,10 +22,10 @@ export type State =
|
|||
| { [key: string]: State }
|
||||
| { [key: number]: State };
|
||||
export type CoercableComponent = string | ComponentOptions | DefineComponent | JSX.Element;
|
||||
export type StyleValue = string | CSSProperties | Array<StyleValue>;
|
||||
export type StyleValue = string | CSSProperties | Array<string | CSSProperties>;
|
||||
|
||||
export type Persistent<T extends State = State> = {
|
||||
state: Ref<T>;
|
||||
[PersistentState]: Ref<T>;
|
||||
[DefaultValue]: T;
|
||||
[SetupPersistence]: () => Ref<T>;
|
||||
};
|
||||
|
@ -40,9 +41,9 @@ export type PersistentRef<T extends State = State> = Ref<T> & {
|
|||
export type GenericComponent = DefineComponent<any, any, any>;
|
||||
|
||||
// Example usage: `<Upgrade {...wrapComputable<GenericUpgrade>(upgrade)} />`
|
||||
export function wrapFeature<T>(component: T): FeatureComponent<T> {
|
||||
export function wrapFeature<T>(component: T): UnwrapRef<T> {
|
||||
// TODO is this okay, or do we actually need to unref each property?
|
||||
return (component as unknown) as FeatureComponent<T>;
|
||||
return component as unknown as UnwrapRef<T>;
|
||||
}
|
||||
|
||||
export type FeatureComponent<T> = Omit<
|
||||
|
@ -75,13 +76,13 @@ export function showIf(condition: boolean, otherwise = Visibility.None): Visibil
|
|||
|
||||
export function persistent<T extends State>(defaultValue: T | Ref<T>): PersistentRef<T> {
|
||||
const persistent = isRef(defaultValue) ? defaultValue : (ref(defaultValue) as Ref<T>);
|
||||
((persistent as unknown) as PersistentRef<T>)[DefaultValue] = isRef(defaultValue)
|
||||
(persistent as unknown as PersistentRef<T>)[DefaultValue] = isRef(defaultValue)
|
||||
? defaultValue.value
|
||||
: defaultValue;
|
||||
((persistent as unknown) as PersistentRef<T>)[SetupPersistence] = function() {
|
||||
(persistent as unknown as PersistentRef<T>)[SetupPersistence] = function () {
|
||||
return persistent;
|
||||
};
|
||||
return (persistent as unknown) as PersistentRef<T>;
|
||||
return persistent as unknown as PersistentRef<T>;
|
||||
}
|
||||
|
||||
export function makePersistent<T extends State>(
|
||||
|
@ -91,7 +92,7 @@ export function makePersistent<T extends State>(
|
|||
const persistent = obj as Partial<Persistent<T>>;
|
||||
const state = ref(defaultValue) as Ref<T>;
|
||||
|
||||
Object.defineProperty(persistent, "state", {
|
||||
Object.defineProperty(persistent, PersistentState, {
|
||||
get: () => {
|
||||
return state.value;
|
||||
},
|
||||
|
@ -136,20 +137,14 @@ export function findFeatures(obj: Record<string, unknown>, type: symbol): unknow
|
|||
globalBus.on("addLayer", (layer: GenericLayer, saveData: Record<string, unknown>) => {
|
||||
const handleObject = (
|
||||
obj: Record<string, unknown>,
|
||||
persistentState: Record<string, unknown>,
|
||||
foundArray: boolean
|
||||
) => {
|
||||
persistentState: Record<string, unknown>
|
||||
): boolean => {
|
||||
let foundPersistent = false;
|
||||
Object.keys(obj).forEach(key => {
|
||||
const value = obj[key];
|
||||
if (value && typeof value === "object") {
|
||||
const warnArray = foundArray || isArray(value);
|
||||
if (SetupPersistence in value) {
|
||||
if (warnArray) {
|
||||
console.warn(
|
||||
"Found persistent property inside array when adding layer. Keep in mind changing the order of persistent objects in an array will mess with existing player saves.",
|
||||
layer
|
||||
);
|
||||
}
|
||||
foundPersistent = true;
|
||||
const savedValue = persistentState[key];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
persistentState[key] = (value as PersistentRef | Persistent)[
|
||||
|
@ -162,14 +157,25 @@ globalBus.on("addLayer", (layer: GenericLayer, saveData: Record<string, unknown>
|
|||
if (typeof persistentState[key] !== "object") {
|
||||
persistentState[key] = {};
|
||||
}
|
||||
handleObject(
|
||||
const foundPersistentInChild = handleObject(
|
||||
value as Record<string, unknown>,
|
||||
persistentState[key] as Record<string, unknown>,
|
||||
warnArray
|
||||
persistentState[key] as Record<string, unknown>
|
||||
);
|
||||
if (foundPersistentInChild) {
|
||||
if (isArray(value)) {
|
||||
console.warn(
|
||||
"Found array that contains persistent values when adding layer. Keep in mind changing the order of elements in the array will mess with existing player saves.",
|
||||
obj,
|
||||
key
|
||||
);
|
||||
} else {
|
||||
foundPersistent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return foundPersistent;
|
||||
};
|
||||
handleObject(layer, saveData, false);
|
||||
handleObject(layer, saveData);
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
getUniqueID,
|
||||
makePersistent,
|
||||
Persistent,
|
||||
PersistentState,
|
||||
Replace,
|
||||
setDefault,
|
||||
State,
|
||||
|
@ -138,7 +139,7 @@ export interface BaseGrid extends Persistent<Record<string | number, State>> {
|
|||
id: string;
|
||||
getID: (id: string | number, state: State) => string;
|
||||
getState: (id: string | number, state: State) => State;
|
||||
setState: (cell: string | number, state: State) => void;
|
||||
setState: (id: string | number, state: State) => void;
|
||||
cells: Record<string | number, GridCell>;
|
||||
type: typeof GridType;
|
||||
[Component]: typeof GridComponent;
|
||||
|
@ -175,18 +176,18 @@ export function createGrid<T extends GridOptions>(options: T & ThisType<Grid<T>>
|
|||
grid.id = getUniqueID("grid-");
|
||||
grid[Component] = GridComponent;
|
||||
|
||||
grid.cells = createGridProxy((grid as unknown) as Record<string, unknown>);
|
||||
grid.cells = createGridProxy(grid as unknown as Record<string, unknown>);
|
||||
grid.getID = function (this: GenericGrid, cell: string | number) {
|
||||
return grid.id + "-" + cell;
|
||||
};
|
||||
grid.getState = function (this: GenericGrid, cell: string | number) {
|
||||
if (this.state.value[cell] != undefined) {
|
||||
return this.state.value[cell];
|
||||
if (this[PersistentState].value[cell] != undefined) {
|
||||
return this[PersistentState].value[cell];
|
||||
}
|
||||
return this.cells[cell].startState;
|
||||
};
|
||||
grid.setState = function (this: GenericGrid, cell: string | number, state: State) {
|
||||
this.state.value[cell] = state;
|
||||
this[PersistentState].value[cell] = state;
|
||||
};
|
||||
|
||||
processComputable(grid as T, "visibility");
|
||||
|
@ -203,6 +204,6 @@ export function createGrid<T extends GridOptions>(options: T & ThisType<Grid<T>>
|
|||
processComputable(grid as T, "getTitle");
|
||||
processComputable(grid as T, "getDisplay");
|
||||
|
||||
const proxy = createProxy((grid as unknown) as Grid<T>);
|
||||
const proxy = createProxy(grid as unknown as Grid<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import { createProxy } from "@/util/proxies";
|
|||
import { unref } from "vue";
|
||||
import { findFeatures, Replace, setDefault } from "./feature";
|
||||
|
||||
export const hotkeys: Record<string, GenericHotkey> = {};
|
||||
export const hotkeys: Record<string, GenericHotkey | undefined> = {};
|
||||
export const HotkeyType = Symbol("Hotkey");
|
||||
|
||||
export interface HotkeyOptions {
|
||||
|
@ -49,7 +49,7 @@ export function createHotkey<T extends HotkeyOptions>(options: T & ThisType<Hotk
|
|||
setDefault(hotkey, "enabled", true);
|
||||
processComputable(hotkey as T, "description");
|
||||
|
||||
const proxy = createProxy((hotkey as unknown) as Hotkey<T>);
|
||||
const proxy = createProxy(hotkey as unknown as Hotkey<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ globalBus.on("addLayer", layer => {
|
|||
|
||||
globalBus.on("removeLayer", layer => {
|
||||
(findFeatures(layer, HotkeyType) as GenericHotkey[]).forEach(hotkey => {
|
||||
delete hotkeys[hotkey.key];
|
||||
hotkeys[hotkey.key] = undefined;
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
getUniqueID,
|
||||
makePersistent,
|
||||
Persistent,
|
||||
PersistentState,
|
||||
Replace,
|
||||
setDefault,
|
||||
StyleValue,
|
||||
|
@ -70,7 +71,7 @@ export function createInfobox<T extends InfoboxOptions>(
|
|||
infobox.type = InfoboxType;
|
||||
infobox[Component] = InfoboxComponent;
|
||||
|
||||
infobox.collapsed = infobox.state;
|
||||
infobox.collapsed = infobox[PersistentState];
|
||||
|
||||
processComputable(infobox as T, "visibility");
|
||||
setDefault(infobox, "visibility", Visibility.Visible);
|
||||
|
@ -82,6 +83,6 @@ export function createInfobox<T extends InfoboxOptions>(
|
|||
processComputable(infobox as T, "title");
|
||||
processComputable(infobox as T, "display");
|
||||
|
||||
const proxy = createProxy((infobox as unknown) as Infobox<T>);
|
||||
const proxy = createProxy(infobox as unknown as Infobox<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
|
|
@ -14,10 +14,8 @@ export interface Link extends SVGAttributes {
|
|||
offsetEnd?: Position;
|
||||
}
|
||||
|
||||
export const RegisterLinkNodeInjectionKey: InjectionKey<(
|
||||
id: string,
|
||||
element: HTMLElement
|
||||
) => void> = Symbol("RegisterLinkNode");
|
||||
export const UnregisterLinkNodeInjectionKey: InjectionKey<(id: string) => void> = Symbol(
|
||||
"UnregisterLinkNode"
|
||||
);
|
||||
export const RegisterLinkNodeInjectionKey: InjectionKey<
|
||||
(id: string, element: HTMLElement) => void
|
||||
> = Symbol("RegisterLinkNode");
|
||||
export const UnregisterLinkNodeInjectionKey: InjectionKey<(id: string) => void> =
|
||||
Symbol("UnregisterLinkNode");
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
getUniqueID,
|
||||
makePersistent,
|
||||
Persistent,
|
||||
PersistentState,
|
||||
Replace,
|
||||
setDefault,
|
||||
StyleValue,
|
||||
|
@ -87,7 +88,7 @@ export function createMilestone<T extends MilestoneOptions>(
|
|||
milestone.type = MilestoneType;
|
||||
milestone[Component] = MilestoneComponent;
|
||||
|
||||
milestone.earned = milestone.state;
|
||||
milestone.earned = milestone[PersistentState];
|
||||
processComputable(milestone as T, "visibility");
|
||||
setDefault(milestone, "visibility", Visibility.Visible);
|
||||
const visibility = milestone.visibility as ProcessedComputable<Visibility>;
|
||||
|
@ -123,18 +124,17 @@ export function createMilestone<T extends MilestoneOptions>(
|
|||
processComputable(milestone as T, "classes");
|
||||
processComputable(milestone as T, "display");
|
||||
|
||||
const proxy = createProxy((milestone as unknown) as Milestone<T>);
|
||||
const proxy = createProxy(milestone as unknown as Milestone<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
const toast = useToast();
|
||||
|
||||
const listeners: Record<string, Unsubscribe> = {};
|
||||
const listeners: Record<string, Unsubscribe | undefined> = {};
|
||||
globalBus.on("addLayer", layer => {
|
||||
const milestones: GenericMilestone[] = (findFeatures(
|
||||
layer,
|
||||
MilestoneType
|
||||
) as GenericMilestone[]).filter(milestone => milestone.shouldEarn != null);
|
||||
const milestones: GenericMilestone[] = (
|
||||
findFeatures(layer, MilestoneType) as GenericMilestone[]
|
||||
).filter(milestone => milestone.shouldEarn != null);
|
||||
listeners[layer.id] = layer.on("postUpdate", () => {
|
||||
milestones.forEach(milestone => {
|
||||
if (
|
||||
|
@ -142,7 +142,7 @@ globalBus.on("addLayer", layer => {
|
|||
!milestone.earned.value &&
|
||||
unref(milestone.shouldEarn)
|
||||
) {
|
||||
milestone.state.value = true;
|
||||
milestone[PersistentState].value = true;
|
||||
milestone.onComplete?.();
|
||||
if (milestone.display) {
|
||||
const display = unref(milestone.display);
|
||||
|
@ -164,7 +164,7 @@ globalBus.on("addLayer", layer => {
|
|||
globalBus.on("removeLayer", layer => {
|
||||
// unsubscribe from postUpdate
|
||||
listeners[layer.id]?.();
|
||||
delete listeners[layer.id];
|
||||
listeners[layer.id] = undefined;
|
||||
});
|
||||
|
||||
declare module "@/game/settings" {
|
||||
|
|
|
@ -51,7 +51,7 @@ export function createReset<T extends ResetOptions>(options: T & ThisType<Reset<
|
|||
if (DefaultValue in value) {
|
||||
(value as PersistentRef).value = (value as PersistentRef)[DefaultValue];
|
||||
} else if (DefaultValue in obj) {
|
||||
(value as PersistentRef).value = ((obj as unknown) as Persistent)[
|
||||
(value as PersistentRef).value = (obj as unknown as Persistent)[
|
||||
DefaultValue
|
||||
];
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ export function createReset<T extends ResetOptions>(options: T & ThisType<Reset<
|
|||
|
||||
processComputable(reset as T, "thingsToReset");
|
||||
|
||||
const proxy = createProxy((reset as unknown) as Reset<T>);
|
||||
const proxy = createProxy(reset as unknown as Reset<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ export function setupAutoReset(
|
|||
});
|
||||
}
|
||||
|
||||
const listeners: Record<string, Unsubscribe> = {};
|
||||
const listeners: Record<string, Unsubscribe | undefined> = {};
|
||||
export function trackResetTime(layer: GenericLayer, reset: GenericReset): PersistentRef<Decimal> {
|
||||
const resetTime = persistent<Decimal>(new Decimal(0));
|
||||
listeners[layer.id] = layer.on("preUpdate", (diff: Decimal) => {
|
||||
|
@ -101,7 +101,7 @@ export function trackResetTime(layer: GenericLayer, reset: GenericReset): Persis
|
|||
globalBus.on("removeLayer", layer => {
|
||||
// unsubscribe from preUpdate
|
||||
listeners[layer.id]?.();
|
||||
delete listeners[layer.id];
|
||||
listeners[layer.id] = undefined;
|
||||
});
|
||||
|
||||
declare module "@/game/events" {
|
||||
|
|
|
@ -84,10 +84,7 @@ export function trackOOMPS(resource: Resource): Ref<string> {
|
|||
oompsMag = -1;
|
||||
} else {
|
||||
while (
|
||||
Decimal.div(curr, prev)
|
||||
.log(10)
|
||||
.div(diff)
|
||||
.gte("100") &&
|
||||
Decimal.div(curr, prev).log(10).div(diff).gte("100") &&
|
||||
oompsMag <= 5 &&
|
||||
Decimal.gt(prev, 0)
|
||||
) {
|
||||
|
|
|
@ -34,6 +34,6 @@ export function createTab<T extends TabOptions>(options: T & ThisType<Tab<T>>):
|
|||
tab.type = TabType;
|
||||
tab[Component] = TabComponent;
|
||||
|
||||
const proxy = createProxy((tab as unknown) as Tab<T>);
|
||||
const proxy = createProxy(tab as unknown as Tab<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
getUniqueID,
|
||||
makePersistent,
|
||||
Persistent,
|
||||
PersistentState,
|
||||
Replace,
|
||||
setDefault,
|
||||
StyleValue,
|
||||
|
@ -73,7 +74,7 @@ export function createTabButton<T extends TabButtonOptions>(
|
|||
processComputable(tabButton as T, "style");
|
||||
processComputable(tabButton as T, "glowColor");
|
||||
|
||||
const proxy = createProxy((tabButton as unknown) as TabButton<T>);
|
||||
const proxy = createProxy(tabButton as unknown as TabButton<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
@ -114,10 +115,10 @@ export function createTabFamily<T extends TabFamilyOptions>(
|
|||
tabFamily.activeTab = computed(() => {
|
||||
const tabs = unref(proxy.tabs);
|
||||
if (
|
||||
proxy.state.value in tabs &&
|
||||
unref(tabs[proxy.state.value].visibility) === Visibility.Visible
|
||||
proxy[PersistentState].value in tabs &&
|
||||
unref(tabs[proxy[PersistentState].value].visibility) === Visibility.Visible
|
||||
) {
|
||||
return unref(tabs[proxy.state.value].tab);
|
||||
return unref(tabs[proxy[PersistentState].value].tab);
|
||||
}
|
||||
const firstTab = Object.values(tabs).find(
|
||||
tab => unref(tab.visibility) === Visibility.Visible
|
||||
|
@ -128,6 +129,6 @@ export function createTabFamily<T extends TabFamilyOptions>(
|
|||
return null;
|
||||
});
|
||||
|
||||
const proxy = createProxy((tabFamily as unknown) as TabFamily<T>);
|
||||
const proxy = createProxy(tabFamily as unknown as TabFamily<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ export function createTreeNode<T extends TreeNodeOptions>(
|
|||
processComputable(treeNode as T, "style");
|
||||
processComputable(treeNode as T, "mark");
|
||||
|
||||
const proxy = createProxy((treeNode as unknown) as TreeNode<T>);
|
||||
const proxy = createProxy(treeNode as unknown as TreeNode<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ export function createTree<T extends TreeOptions>(options: T & ThisType<Tree<T>>
|
|||
processComputable(tree as T, "rightSideNodes");
|
||||
processComputable(tree as T, "branches");
|
||||
|
||||
const proxy = createProxy((tree as unknown) as Tree<T>);
|
||||
const proxy = createProxy(tree as unknown as Tree<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
getUniqueID,
|
||||
makePersistent,
|
||||
Persistent,
|
||||
PersistentState,
|
||||
Replace,
|
||||
setDefault,
|
||||
StyleValue,
|
||||
|
@ -93,7 +94,7 @@ export function createUpgrade<T extends UpgradeOptions>(
|
|||
);
|
||||
}
|
||||
|
||||
upgrade.bought = upgrade.state;
|
||||
upgrade.bought = upgrade[PersistentState];
|
||||
if (upgrade.canAfford == null) {
|
||||
upgrade.canAfford = computed(
|
||||
() =>
|
||||
|
@ -115,7 +116,7 @@ export function createUpgrade<T extends UpgradeOptions>(
|
|||
unref(proxy.cost)
|
||||
);
|
||||
}
|
||||
proxy.state.value = true;
|
||||
proxy[PersistentState].value = true;
|
||||
proxy.onPurchase?.();
|
||||
};
|
||||
|
||||
|
@ -129,7 +130,7 @@ export function createUpgrade<T extends UpgradeOptions>(
|
|||
processComputable(upgrade as T, "resource");
|
||||
processComputable(upgrade as T, "canPurchase");
|
||||
|
||||
const proxy = createProxy((upgrade as unknown) as Upgrade<T>);
|
||||
const proxy = createProxy(upgrade as unknown as Upgrade<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { hasWon } from "@/data/mod";
|
||||
import modInfo from "@/data/modInfo.json";
|
||||
import Decimal, { DecimalSource } from "@/util/bignum";
|
||||
import { createNanoEvents } from "nanoevents";
|
||||
import { App } from "vue";
|
||||
import { GenericLayer, layers } from "./layers";
|
||||
import { App, Ref } from "vue";
|
||||
import { GenericLayer } from "./layers";
|
||||
import player from "./player";
|
||||
import settings, { Settings } from "./settings";
|
||||
import state from "./state";
|
||||
|
@ -16,19 +15,14 @@ export interface GlobalEvents {
|
|||
setupVue: (vue: App) => void;
|
||||
}
|
||||
|
||||
export interface LayerEvents {
|
||||
// Generation
|
||||
preUpdate: (diff: Decimal) => void;
|
||||
// Actions (e.g. automation)
|
||||
update: (diff: Decimal) => void;
|
||||
// Effects (e.g. milestones)
|
||||
postUpdate: (diff: Decimal) => void;
|
||||
}
|
||||
|
||||
export const globalBus = createNanoEvents<GlobalEvents>();
|
||||
|
||||
let intervalID: number | null = null;
|
||||
|
||||
// Not imported immediately due to dependency cycles
|
||||
// This gets set during startGameLoop(), and will only be used in the update function
|
||||
let hasWon: null | Ref<boolean> = null;
|
||||
|
||||
function update() {
|
||||
const now = Date.now();
|
||||
let diff: DecimalSource = (now - player.time) / 1e3;
|
||||
|
@ -41,7 +35,7 @@ function update() {
|
|||
}
|
||||
|
||||
// Stop here if the game is paused on the win screen
|
||||
if (hasWon.value && !player.keepGoing) {
|
||||
if (hasWon?.value && !player.keepGoing) {
|
||||
return;
|
||||
}
|
||||
// Stop here if the player had a NaN value
|
||||
|
@ -94,22 +88,11 @@ function update() {
|
|||
}
|
||||
}
|
||||
|
||||
export function startGameLoop(): void {
|
||||
export async function startGameLoop() {
|
||||
hasWon = (await import("@/data/mod")).hasWon;
|
||||
if (settings.unthrottled) {
|
||||
requestAnimationFrame(update);
|
||||
} else {
|
||||
intervalID = setInterval(update, 50);
|
||||
}
|
||||
}
|
||||
|
||||
globalBus.on("update", function updateLayers(diff) {
|
||||
Object.values(layers).forEach(layer => {
|
||||
layer.emit("preUpdate", diff);
|
||||
});
|
||||
Object.values(layers).forEach(layer => {
|
||||
layer.emit("update", diff);
|
||||
});
|
||||
Object.values(layers).forEach(layer => {
|
||||
layer.emit("postUpdate", diff);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
StyleValue
|
||||
} from "@/features/feature";
|
||||
import { Link } from "@/features/links";
|
||||
import Decimal from "@/util/bignum";
|
||||
import {
|
||||
Computable,
|
||||
GetComputableType,
|
||||
|
@ -16,10 +17,19 @@ import {
|
|||
} from "@/util/computed";
|
||||
import { createProxy } from "@/util/proxies";
|
||||
import { createNanoEvents, Emitter } from "nanoevents";
|
||||
import { globalBus, LayerEvents } from "./events";
|
||||
import { globalBus } from "./events";
|
||||
import player from "./player";
|
||||
|
||||
export const layers: Record<string, Readonly<GenericLayer>> = {};
|
||||
export interface LayerEvents {
|
||||
// Generation
|
||||
preUpdate: (diff: Decimal) => void;
|
||||
// Actions (e.g. automation)
|
||||
update: (diff: Decimal) => void;
|
||||
// Effects (e.g. milestones)
|
||||
postUpdate: (diff: Decimal) => void;
|
||||
}
|
||||
|
||||
export const layers: Record<string, Readonly<GenericLayer> | undefined> = {};
|
||||
window.layers = layers;
|
||||
|
||||
export interface Position {
|
||||
|
@ -75,8 +85,8 @@ export function createLayer<T extends LayerOptions>(options: T): Layer<T> {
|
|||
const layer: T & Partial<BaseLayer> = options;
|
||||
|
||||
const emitter = (layer.emitter = createNanoEvents<LayerEvents>());
|
||||
layer.on = emitter.on;
|
||||
layer.emit = emitter.emit;
|
||||
layer.on = emitter.on.bind(emitter);
|
||||
layer.emit = emitter.emit.bind(emitter);
|
||||
|
||||
layer.minimized = persistent(false);
|
||||
|
||||
|
@ -90,7 +100,7 @@ export function createLayer<T extends LayerOptions>(options: T): Layer<T> {
|
|||
setDefault(layer, "minimizable", true);
|
||||
processComputable(layer as T, "links");
|
||||
|
||||
const proxy = createProxy((layer as unknown) as Layer<T>);
|
||||
const proxy = createProxy(layer as unknown as Layer<T>);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
@ -98,7 +108,8 @@ export function addLayer(
|
|||
layer: GenericLayer,
|
||||
player: { layers?: Record<string, Record<string, unknown>> }
|
||||
): void {
|
||||
if (layer.id in layers) {
|
||||
console.info("Adding layer", layer.id);
|
||||
if (layers[layer.id]) {
|
||||
console.error(
|
||||
"Attempted to add layer with same ID as existing layer",
|
||||
layer.id,
|
||||
|
@ -121,9 +132,10 @@ export function getLayer<T extends GenericLayer>(layerID: string): () => T {
|
|||
}
|
||||
|
||||
export function removeLayer(layer: GenericLayer): void {
|
||||
console.info("Removing layer", layer.id);
|
||||
globalBus.emit("removeLayer", layer);
|
||||
|
||||
delete layers[layer.id];
|
||||
layers[layer.id] = undefined;
|
||||
}
|
||||
|
||||
export function reloadLayer(layer: GenericLayer): void {
|
||||
|
@ -132,3 +144,15 @@ export function reloadLayer(layer: GenericLayer): void {
|
|||
// Re-create layer
|
||||
addLayer(layer, player);
|
||||
}
|
||||
|
||||
globalBus.on("update", function updateLayers(diff) {
|
||||
Object.values(layers).forEach(layer => {
|
||||
layer?.emit("preUpdate", diff);
|
||||
});
|
||||
Object.values(layers).forEach(layer => {
|
||||
layer?.emit("update", diff);
|
||||
});
|
||||
Object.values(layers).forEach(layer => {
|
||||
layer?.emit("postUpdate", diff);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -97,7 +97,7 @@ const playerHandler: ProxyHandler<Record<PropertyKey, any>> = {
|
|||
state.autosave = false;
|
||||
transientState.hasNaN = true;
|
||||
transientState.NaNPath = [...target[ProxyPath], property];
|
||||
transientState.NaNReceiver = (receiver as unknown) as Record<string, unknown>;
|
||||
transientState.NaNReceiver = receiver as unknown as Record<string, unknown>;
|
||||
console.error(
|
||||
`Attempted to set NaN value`,
|
||||
[...target[ProxyPath], property],
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { App as VueApp, createApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
import modInfo from "./data/modInfo.json";
|
||||
import { globalBus, startGameLoop } from "./game/events";
|
||||
import { GenericLayer } from "./game/layers";
|
||||
import { PlayerData } from "./game/player";
|
||||
import { Settings } from "./game/settings";
|
||||
|
@ -15,7 +14,7 @@ declare global {
|
|||
save: VoidFunction;
|
||||
hardReset: VoidFunction;
|
||||
hardResetSettings: VoidFunction;
|
||||
layers: Record<string, Readonly<GenericLayer>>;
|
||||
layers: Record<string, Readonly<GenericLayer> | undefined>;
|
||||
player: PlayerData;
|
||||
state: Transient;
|
||||
settings: Settings;
|
||||
|
@ -34,6 +33,7 @@ declare global {
|
|||
|
||||
requestAnimationFrame(async () => {
|
||||
await load();
|
||||
const { globalBus, startGameLoop } = await require("./game/events");
|
||||
|
||||
// Create Vue
|
||||
const vue = (window.vue = createApp({
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { fixOldSave, getInitialLayers } from "@/data/mod";
|
||||
import modInfo from "@/data/modInfo.json";
|
||||
import player, { Player, PlayerData, stringifySave } from "@/game/player";
|
||||
import settings, { loadSettings } from "@/game/settings";
|
||||
|
@ -48,6 +47,7 @@ export async function load(): Promise<void> {
|
|||
player.id = settings.active;
|
||||
await loadSave(player);
|
||||
} catch (e) {
|
||||
console.error("Failed to load save. Falling back to new save.\n", e);
|
||||
await loadSave(newSave());
|
||||
}
|
||||
}
|
||||
|
@ -73,11 +73,15 @@ export function getUniqueID(): string {
|
|||
}
|
||||
|
||||
export async function loadSave(playerObj: Partial<PlayerData>): Promise<void> {
|
||||
const { layers, removeLayer, addLayer } = await import("../game/layers");
|
||||
console.info("Loading save", playerObj);
|
||||
const { layers, removeLayer, addLayer } = await import("@/game/layers");
|
||||
const { fixOldSave, getInitialLayers } = await import("@/data/mod");
|
||||
|
||||
for (const layer in layers) {
|
||||
removeLayer(layers[layer]);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
removeLayer(layers[layer]!);
|
||||
}
|
||||
console.log(getInitialLayers(playerObj))
|
||||
getInitialLayers(playerObj).forEach(layer => addLayer(layer, playerObj));
|
||||
|
||||
setupInitialStore(playerObj);
|
||||
|
|
|
@ -12,6 +12,6 @@ module.exports = {
|
|||
config.plugins.delete("fork-ts-checker");
|
||||
},
|
||||
devServer: {
|
||||
disableHostCheck: true
|
||||
allowedHosts: "all"
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue