installer
This commit is contained in:
parent
3158c3cec8
commit
6b5cc23888
8 changed files with 127 additions and 48 deletions
|
|
@ -1,40 +1,42 @@
|
||||||
import { AnimationKeyframe } from "../components/AnimationKeyframe.js"
|
import { AnimationKeyframe } from "../components/AnimationKeyframe.js";
|
||||||
import { AnimType } from "../types/enums/AnimType.js"
|
import { AnimType } from "../types/enums/AnimType.js";
|
||||||
import { KeyframeAnimationProperties } from "../types/properties/element/Animation.js"
|
import { KeyframeAnimationProperties } from "../types/properties/element/Animation.js";
|
||||||
import { Binding } from "../types/properties/value.js"
|
import { Binding } from "../types/properties/value.js";
|
||||||
|
|
||||||
export function FormatProperties(properties: any) {
|
export function FormatProperties(properties: any) {
|
||||||
const property_bag: Record<Binding, any> = {}
|
const property_bag: Record<Binding, any> = {};
|
||||||
|
|
||||||
for (const key in properties) {
|
for (const key in properties) {
|
||||||
const value = properties[key]
|
const value = properties[key];
|
||||||
|
|
||||||
if (key.startsWith("#")) {
|
if (key.startsWith("#")) {
|
||||||
property_bag[<Binding>key] = value
|
property_bag[<Binding>key] = value;
|
||||||
delete properties[key]
|
delete properties[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (properties.anchor) {
|
if (properties.anchor) {
|
||||||
properties.anchor_from = properties.anchor_to = properties.anchor
|
properties.anchor_from = properties.anchor_to = properties.anchor;
|
||||||
delete properties.anchor
|
delete properties.anchor;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Object.keys(property_bag).length) {
|
if (Object.keys(property_bag).length) {
|
||||||
if (properties.property_bag) {
|
if (properties.property_bag) {
|
||||||
properties.property_bag = { ...property_bag, ...properties.property_bag }
|
properties.property_bag = { ...property_bag, ...properties.property_bag };
|
||||||
} else {
|
} else {
|
||||||
properties.property_bag = property_bag
|
properties.property_bag = property_bag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return properties
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FormatAnimationProperties(properties: KeyframeAnimationProperties<AnimType>) {
|
export function FormatAnimationProperties(
|
||||||
|
properties: KeyframeAnimationProperties<AnimType>,
|
||||||
|
) {
|
||||||
if (properties.next instanceof AnimationKeyframe) {
|
if (properties.next instanceof AnimationKeyframe) {
|
||||||
properties.next = `${properties.next}`
|
properties.next = `${properties.next}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return properties
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { AnimationKeyframe } from "../components/AnimationKeyframe.js"
|
import { AnimationKeyframe } from "../components/AnimationKeyframe.js"
|
||||||
import { Class } from "../components/Class.js"
|
import { Class } from "../components/Class.js"
|
||||||
import { ModifyUI, UI } from "../components/UI.js"
|
import { UI } from "../components/UI.js"
|
||||||
import { AnimType } from "../types/enums/AnimType.js"
|
import { AnimType } from "../types/enums/AnimType.js"
|
||||||
import { Renderer } from "../types/enums/Renderer.js"
|
import { Renderer } from "../types/enums/Renderer.js"
|
||||||
import { Type } from "../types/enums/Type.js"
|
import { Type } from "../types/enums/Type.js"
|
||||||
|
|
@ -40,9 +40,7 @@ export class Memory extends Class {
|
||||||
Memory.files.entries().forEach(([path, { elements, namespace }]) => {
|
Memory.files.entries().forEach(([path, { elements, namespace }]) => {
|
||||||
const record: Record<string, any> = {}
|
const record: Record<string, any> = {}
|
||||||
|
|
||||||
elements.forEach(element => {
|
elements.forEach(element => (record[element.name] = element))
|
||||||
record[element.name] = element
|
|
||||||
})
|
|
||||||
|
|
||||||
data.set(path, {
|
data.set(path, {
|
||||||
namespace,
|
namespace,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import { isBuildMode } from "../Configuration.js"
|
import { isBuildMode } from "../Configuration.js"
|
||||||
import { Memory } from "../Memory.js"
|
import { Memory } from "../Memory.js"
|
||||||
import { createBuildFolder } from "./linker.js"
|
import { createBuildFolder, linkToGame } from "./linker.js"
|
||||||
import fs from "fs/promises"
|
|
||||||
import { genManifest } from "./manifest.js"
|
import { genManifest } from "./manifest.js"
|
||||||
|
import { UI } from "../../components/UI.js"
|
||||||
|
import { Type } from "../../types/enums/Type.js"
|
||||||
|
import fs from "fs/promises"
|
||||||
|
|
||||||
async function buildUI() {
|
async function buildUI() {
|
||||||
const build = Memory.build()
|
const build = Memory.build()
|
||||||
|
|
@ -11,6 +13,10 @@ async function buildUI() {
|
||||||
ui_defs: Array.from(build.keys()),
|
ui_defs: Array.from(build.keys()),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
build.set("build.json", {
|
||||||
|
files: Array.from(build.keys()),
|
||||||
|
})
|
||||||
|
|
||||||
const out = await Promise.all(
|
const out = await Promise.all(
|
||||||
build.entries().map(async ([file, value]) => {
|
build.entries().map(async ([file, value]) => {
|
||||||
const outFile = `build/build/${file}`
|
const outFile = `build/build/${file}`
|
||||||
|
|
@ -18,12 +24,30 @@ async function buildUI() {
|
||||||
.stat(outFile.split(/\\|\//g).slice(0, -1).join("/"))
|
.stat(outFile.split(/\\|\//g).slice(0, -1).join("/"))
|
||||||
.catch(async () => await fs.mkdir(outFile.split(/\\|\//g).slice(0, -1).join("/"), { recursive: true }))
|
.catch(async () => await fs.mkdir(outFile.split(/\\|\//g).slice(0, -1).join("/"), { recursive: true }))
|
||||||
|
|
||||||
await fs.writeFile(outFile, JSON.stringify(value), "utf-8")
|
await fs.writeFile(
|
||||||
|
outFile,
|
||||||
|
JSON.stringify(
|
||||||
|
Object.fromEntries(
|
||||||
|
Object.entries(value).map(([key, value]: [string, any]) => {
|
||||||
|
const extend = (value as UI<Type>).extend
|
||||||
|
return [extend ? key + String(extend) : key, value]
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
"utf-8",
|
||||||
|
)
|
||||||
build.delete(file)
|
build.delete(file)
|
||||||
|
return file
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
await fs.writeFile("build/build/manifest.json", await genManifest(), "utf-8")
|
await Promise.all([
|
||||||
|
fs.writeFile("build/build/manifest.json", await genManifest(), "utf-8"),
|
||||||
|
fs.writeFile("build/build/.gitignore", [...out, "manifest.json"].join("\n"), "utf-8"),
|
||||||
|
fs
|
||||||
|
.stat("build/build/pack_icon.png")
|
||||||
|
.catch(() => fs.copyFile("node_modules/asajs/resources/pack_icon.png", "build/build/pack_icon.png")),
|
||||||
|
])
|
||||||
|
|
||||||
return out.length
|
return out.length
|
||||||
}
|
}
|
||||||
|
|
@ -34,6 +58,7 @@ if (isBuildMode) {
|
||||||
if (first) {
|
if (first) {
|
||||||
await createBuildFolder()
|
await createBuildFolder()
|
||||||
await buildUI()
|
await buildUI()
|
||||||
|
await linkToGame()
|
||||||
}
|
}
|
||||||
first = false
|
first = false
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import os from "os"
|
import os from "os"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
|
|
||||||
function getGamedataPath() {
|
export function getGamedataPath() {
|
||||||
switch (os.platform()) {
|
switch (os.platform()) {
|
||||||
case "win32": {
|
case "win32": {
|
||||||
if (/Windows (10|11)/.test(os.version())) {
|
if (/Windows (10|11)/.test(os.version())) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
import fs from "fs/promises"
|
import fs from "fs/promises"
|
||||||
import { BuildCache } from "./buildcache.js"
|
import { BuildCache } from "./buildcache.js"
|
||||||
import { RandomString } from "../../components/Utils.js"
|
import { RandomString } from "../../components/Utils.js"
|
||||||
|
import { prevData } from "./prevdata.js"
|
||||||
|
import path from "path"
|
||||||
|
import { getGamedataPath } from "./installer.js"
|
||||||
|
|
||||||
const HEX: string[] = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"))
|
const HEX: string[] = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"))
|
||||||
|
|
||||||
|
|
@ -22,7 +25,7 @@ function genUUID(): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function clearBuild() {
|
export async function clearBuild() {
|
||||||
await fs.rm("build/build", { recursive: true, force: true })
|
await Promise.all(prevData.files.map(file => fs.rm(`build/build/${file}`).catch(() => null)))
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createBuildFolder() {
|
export async function createBuildFolder() {
|
||||||
|
|
@ -36,6 +39,14 @@ export async function getBuildFolderName() {
|
||||||
return await BuildCache.getWithSetDefault("build-key", () => RandomString(16))
|
return await BuildCache.getWithSetDefault("build-key", () => RandomString(16))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function linkToGame() {
|
||||||
|
const sourcePath = path.resolve("build/build")
|
||||||
|
const targetPath = path.resolve(getGamedataPath(), "development_resource_packs", await getBuildFolderName())
|
||||||
|
await fs.stat(targetPath).catch(async () => {
|
||||||
|
await fs.symlink(sourcePath, targetPath, "junction")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export async function getUUID(): Promise<[string, string]> {
|
export async function getUUID(): Promise<[string, string]> {
|
||||||
return await BuildCache.getWithSetDefault("uuid", () => {
|
return await BuildCache.getWithSetDefault("uuid", () => {
|
||||||
return [genUUID(), genUUID()]
|
return [genUUID(), genUUID()]
|
||||||
|
|
|
||||||
11
src/compilers/ui/prevdata.ts
Normal file
11
src/compilers/ui/prevdata.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import fs from "fs"
|
||||||
|
|
||||||
|
export let prevData: {
|
||||||
|
files: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
prevData = JSON.parse(fs.readFileSync("build/build/build.json", "utf-8"))
|
||||||
|
} catch (error) {
|
||||||
|
prevData = { files: [] }
|
||||||
|
}
|
||||||
|
|
@ -15,12 +15,18 @@ import { RandomNamespace } from "../compilers/Random.js"
|
||||||
|
|
||||||
import util from "node:util"
|
import util from "node:util"
|
||||||
|
|
||||||
|
interface ExtendUI {
|
||||||
|
name: string
|
||||||
|
namespace: string
|
||||||
|
toString(): string
|
||||||
|
}
|
||||||
|
|
||||||
export class UI<T extends Type, K extends Renderer | null = null> extends Class {
|
export class UI<T extends Type, K extends Renderer | null = null> extends Class {
|
||||||
readonly path: string
|
readonly path: string
|
||||||
readonly name: string
|
readonly name: string
|
||||||
readonly namespace: string
|
readonly namespace: string
|
||||||
|
|
||||||
readonly extend?: UI<Type, Renderer | null>
|
readonly extend?: UI<Type, Renderer | null> | ExtendUI
|
||||||
readonly extendable: boolean
|
readonly extendable: boolean
|
||||||
|
|
||||||
protected readonly controls = new Map<string, [UI<Type, Renderer | null>, Properties<Type, Renderer | null>]>()
|
protected readonly controls = new Map<string, [UI<Type, Renderer | null>, Properties<Type, Renderer | null>]>()
|
||||||
|
|
@ -53,7 +59,7 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
|
||||||
this.name = name?.match(/^(\w|\/)+/)?.[0] || RandomString(16)
|
this.name = name?.match(/^(\w|\/)+/)?.[0] || RandomString(16)
|
||||||
this.namespace = namespace || RandomNamespace()
|
this.namespace = namespace || RandomNamespace()
|
||||||
|
|
||||||
if (!path) this.path = `@/${this.namespace}.json`
|
if (!path) this.path = `asajs/${this.namespace}.json`
|
||||||
else this.path = path
|
else this.path = path
|
||||||
|
|
||||||
this.extendable = this.name.search("/") === -1
|
this.extendable = this.name.search("/") === -1
|
||||||
|
|
@ -132,8 +138,15 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
|
||||||
* @param namespace
|
* @param namespace
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
clone(properties?: Properties<T, K>, name?: string, namespace?: string) {
|
createExtends(properties?: Properties<T, K>, name?: string, namespace?: string) {
|
||||||
return ExtendsOf(this, properties, name, namespace)
|
if (!this.extendable) throw new Error("This element is not extendable")
|
||||||
|
const ui = new UI<T, K>(undefined, name, namespace)
|
||||||
|
if (properties) ui.setProperties(properties)
|
||||||
|
// @ts-ignore
|
||||||
|
ui.extend = this
|
||||||
|
// @ts-ignore
|
||||||
|
ui.extendType = this.type || this.extendType
|
||||||
|
return ui
|
||||||
}
|
}
|
||||||
|
|
||||||
protected toString() {
|
protected toString() {
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ import { AnimationKeyframe } from "./AnimationKeyframe.js"
|
||||||
import { AnimationProperties, KeyframeAnimationProperties } from "../types/properties/element/Animation.js"
|
import { AnimationProperties, KeyframeAnimationProperties } from "../types/properties/element/Animation.js"
|
||||||
import { Animation } from "./Animation.js"
|
import { Animation } from "./Animation.js"
|
||||||
import { SmartAnimation } from "../types/enums/SmartAnimation.js"
|
import { SmartAnimation } from "../types/enums/SmartAnimation.js"
|
||||||
import { Memory, MemoryModify } from "../compilers/Memory.js"
|
import { MemoryModify } from "../compilers/Memory.js"
|
||||||
|
|
||||||
type CompileBinding = `[${string}]`
|
type CompileBinding = `[${string}]`
|
||||||
|
|
||||||
|
|
@ -250,9 +250,7 @@ export function ExtendsOf<T extends Type, K extends Renderer | null>(
|
||||||
namespace?: string,
|
namespace?: string,
|
||||||
name?: string,
|
name?: string,
|
||||||
) {
|
) {
|
||||||
if (!element.extendable) {
|
if (!element.extendable) throw new Error("Cannot extend a UI that cannot be extended")
|
||||||
throw new Error("Cannot extend a UI that cannot be extended")
|
|
||||||
}
|
|
||||||
const ui = new UI<T, K>(undefined, name, namespace)
|
const ui = new UI<T, K>(undefined, name, namespace)
|
||||||
if (properties) ui.setProperties(properties)
|
if (properties) ui.setProperties(properties)
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
@ -262,6 +260,27 @@ export function ExtendsOf<T extends Type, K extends Renderer | null>(
|
||||||
return ui as typeof element
|
return ui as typeof element
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function VanillaExtendsOf<T extends Namespace, K extends Exclude<Element<T>, `${string}/${string}`>>(
|
||||||
|
originNamespace: T,
|
||||||
|
originName: K,
|
||||||
|
// @ts-ignore
|
||||||
|
properties?: Properties<VanillaType<T, K>, null>,
|
||||||
|
namespace?: string,
|
||||||
|
name?: string,
|
||||||
|
) {
|
||||||
|
// @ts-ignore
|
||||||
|
const ui = new UI<VanillaType<T, K>, null>(undefined, name, namespace)
|
||||||
|
if (properties) ui.setProperties(properties)
|
||||||
|
// @ts-ignore
|
||||||
|
ui.extend = {
|
||||||
|
name: originName,
|
||||||
|
namespace: originNamespace,
|
||||||
|
toString: () => `@${originNamespace}.${originName}`,
|
||||||
|
}
|
||||||
|
|
||||||
|
return ui
|
||||||
|
}
|
||||||
|
|
||||||
// Quick Keyframe
|
// Quick Keyframe
|
||||||
export function KeyframeOffset(
|
export function KeyframeOffset(
|
||||||
properties?: KeyframeAnimationProperties<AnimType.OFFSET>,
|
properties?: KeyframeAnimationProperties<AnimType.OFFSET>,
|
||||||
|
|
@ -359,7 +378,7 @@ export function AnimationAlpha(...keyframes: AnimWithSmartAnim<AnimType.ALPHA>)
|
||||||
return new Animation(AnimType.ALPHA, ...keyframes)
|
return new Animation(AnimType.ALPHA, ...keyframes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Animation Extendof
|
// Animation ExtendsOf
|
||||||
export function AnimationExtendsOf<T extends AnimType>(
|
export function AnimationExtendsOf<T extends AnimType>(
|
||||||
animation: AnimationKeyframe<T> | Animation<T>,
|
animation: AnimationKeyframe<T> | Animation<T>,
|
||||||
properties?: AnimationProperties<T>,
|
properties?: AnimationProperties<T>,
|
||||||
|
|
|
||||||
Reference in a new issue