aether-engine 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/biome.json +51 -0
- package/bun.lock +192 -0
- package/index.ts +1 -0
- package/package.json +25 -0
- package/serve.ts +125 -0
- package/src/audio/AudioEngine.ts +61 -0
- package/src/components/Animator3D.ts +65 -0
- package/src/components/AudioSource.ts +26 -0
- package/src/components/BitmapText.ts +25 -0
- package/src/components/Camera.ts +33 -0
- package/src/components/CameraFollow.ts +5 -0
- package/src/components/Collider.ts +16 -0
- package/src/components/Components.test.ts +68 -0
- package/src/components/Light.ts +15 -0
- package/src/components/MeshRenderer.ts +58 -0
- package/src/components/ParticleEmitter.ts +59 -0
- package/src/components/RigidBody.ts +9 -0
- package/src/components/ShadowCaster.ts +3 -0
- package/src/components/SkinnedMeshRenderer.ts +25 -0
- package/src/components/SpriteAnimator.ts +42 -0
- package/src/components/SpriteRenderer.ts +26 -0
- package/src/components/Transform.test.ts +39 -0
- package/src/components/Transform.ts +54 -0
- package/src/core/AssetManager.ts +123 -0
- package/src/core/Input.test.ts +67 -0
- package/src/core/Input.ts +94 -0
- package/src/core/Scene.ts +24 -0
- package/src/core/SceneManager.ts +57 -0
- package/src/core/Storage.ts +161 -0
- package/src/desktop/SteamClient.ts +52 -0
- package/src/ecs/System.ts +11 -0
- package/src/ecs/World.test.ts +29 -0
- package/src/ecs/World.ts +149 -0
- package/src/index.ts +115 -0
- package/src/math/Color.ts +100 -0
- package/src/math/Vector2.ts +96 -0
- package/src/math/Vector3.ts +103 -0
- package/src/math/math.test.ts +168 -0
- package/src/renderer/GlowMaterial.ts +66 -0
- package/src/renderer/LitMaterial.ts +337 -0
- package/src/renderer/Material.test.ts +23 -0
- package/src/renderer/Material.ts +80 -0
- package/src/renderer/OcclusionMaterial.ts +43 -0
- package/src/renderer/ParticleMaterial.ts +66 -0
- package/src/renderer/Shader.ts +44 -0
- package/src/renderer/SkinnedLitMaterial.ts +55 -0
- package/src/renderer/WaterMaterial.ts +298 -0
- package/src/renderer/WebGLRenderer.ts +917 -0
- package/src/systems/Animation3DSystem.ts +148 -0
- package/src/systems/AnimationSystem.ts +58 -0
- package/src/systems/AudioSystem.ts +62 -0
- package/src/systems/LightingSystem.ts +114 -0
- package/src/systems/ParticleSystem.ts +278 -0
- package/src/systems/PhysicsSystem.ts +211 -0
- package/src/systems/Systems.test.ts +165 -0
- package/src/systems/TextSystem.ts +153 -0
- package/src/ui/AnimationEditor.tsx +639 -0
- package/src/ui/BottomPanel.tsx +443 -0
- package/src/ui/EntityExplorer.tsx +420 -0
- package/src/ui/GameState.ts +286 -0
- package/src/ui/Icons.tsx +239 -0
- package/src/ui/InventoryPanel.tsx +335 -0
- package/src/ui/PlayerHUD.tsx +250 -0
- package/src/ui/SpriteEditor.tsx +3241 -0
- package/src/ui/SpriteSheetManager.tsx +198 -0
- package/src/utils/GLTFLoader.ts +257 -0
- package/src/utils/ObjLoader.ts +81 -0
- package/src/utils/idb.ts +137 -0
- package/src/utils/packer.ts +85 -0
- package/test_obj.ts +12 -0
- package/tsconfig.json +21 -0
- package/tsconfig.tsbuildinfo +1 -0
package/README.md
ADDED
package/biome.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.4.10/schema.json",
|
|
3
|
+
"vcs": {
|
|
4
|
+
"enabled": true,
|
|
5
|
+
"clientKind": "git",
|
|
6
|
+
"useIgnoreFile": true
|
|
7
|
+
},
|
|
8
|
+
"files": {
|
|
9
|
+
"ignoreUnknown": false
|
|
10
|
+
},
|
|
11
|
+
"formatter": {
|
|
12
|
+
"enabled": true,
|
|
13
|
+
"indentStyle": "tab"
|
|
14
|
+
},
|
|
15
|
+
"linter": {
|
|
16
|
+
"enabled": true,
|
|
17
|
+
"rules": {
|
|
18
|
+
"recommended": true,
|
|
19
|
+
"a11y": {
|
|
20
|
+
"useButtonType": "off",
|
|
21
|
+
"noLabelWithoutControl": "off",
|
|
22
|
+
"noStaticElementInteractions": "off",
|
|
23
|
+
"useKeyWithClickEvents": "off",
|
|
24
|
+
"useKeyWithMouseEvents": "off",
|
|
25
|
+
"useAltText": "off",
|
|
26
|
+
"noSvgWithoutTitle": "off",
|
|
27
|
+
"useHtmlLang": "off"
|
|
28
|
+
},
|
|
29
|
+
"suspicious": {
|
|
30
|
+
"noExplicitAny": "off",
|
|
31
|
+
"noImplicitAnyLet": "off"
|
|
32
|
+
},
|
|
33
|
+
"style": {
|
|
34
|
+
"noNonNullAssertion": "off"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"javascript": {
|
|
39
|
+
"formatter": {
|
|
40
|
+
"quoteStyle": "double"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"assist": {
|
|
44
|
+
"enabled": true,
|
|
45
|
+
"actions": {
|
|
46
|
+
"source": {
|
|
47
|
+
"organizeImports": "on"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
package/bun.lock
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lockfileVersion": 1,
|
|
3
|
+
"workspaces": {
|
|
4
|
+
"": {
|
|
5
|
+
"name": "aether",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@gltf-transform/core": "^4.3.0",
|
|
8
|
+
"@tauri-apps/api": "^2.10.1",
|
|
9
|
+
"gl-matrix": "^3.4.4",
|
|
10
|
+
"solid-js": "^1.9.12",
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@biomejs/biome": "^2.4.10",
|
|
14
|
+
"@types/bun": "latest",
|
|
15
|
+
"@types/gl-matrix": "^3.2.0",
|
|
16
|
+
"@types/pngjs": "^6.0.5",
|
|
17
|
+
"bun-plugin-solid": "^1.0.0",
|
|
18
|
+
"pngjs": "^7.0.0",
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"typescript": "^5",
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
"packages": {
|
|
26
|
+
"@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="],
|
|
27
|
+
|
|
28
|
+
"@babel/compat-data": ["@babel/compat-data@7.29.0", "", {}, "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="],
|
|
29
|
+
|
|
30
|
+
"@babel/core": ["@babel/core@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="],
|
|
31
|
+
|
|
32
|
+
"@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="],
|
|
33
|
+
|
|
34
|
+
"@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" } }, "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg=="],
|
|
35
|
+
|
|
36
|
+
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="],
|
|
37
|
+
|
|
38
|
+
"@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/traverse": "^7.28.6", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow=="],
|
|
39
|
+
|
|
40
|
+
"@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
|
|
41
|
+
|
|
42
|
+
"@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.28.5", "", { "dependencies": { "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5" } }, "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg=="],
|
|
43
|
+
|
|
44
|
+
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="],
|
|
45
|
+
|
|
46
|
+
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="],
|
|
47
|
+
|
|
48
|
+
"@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.27.1", "", { "dependencies": { "@babel/types": "^7.27.1" } }, "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw=="],
|
|
49
|
+
|
|
50
|
+
"@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="],
|
|
51
|
+
|
|
52
|
+
"@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.28.6", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg=="],
|
|
53
|
+
|
|
54
|
+
"@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg=="],
|
|
55
|
+
|
|
56
|
+
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
|
|
57
|
+
|
|
58
|
+
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
|
|
59
|
+
|
|
60
|
+
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
|
|
61
|
+
|
|
62
|
+
"@babel/helpers": ["@babel/helpers@7.29.2", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.29.0" } }, "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw=="],
|
|
63
|
+
|
|
64
|
+
"@babel/parser": ["@babel/parser@7.29.2", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA=="],
|
|
65
|
+
|
|
66
|
+
"@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w=="],
|
|
67
|
+
|
|
68
|
+
"@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A=="],
|
|
69
|
+
|
|
70
|
+
"@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.28.6", "", { "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA=="],
|
|
71
|
+
|
|
72
|
+
"@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw=="],
|
|
73
|
+
|
|
74
|
+
"@babel/preset-typescript": ["@babel/preset-typescript@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", "@babel/plugin-transform-typescript": "^7.28.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g=="],
|
|
75
|
+
|
|
76
|
+
"@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="],
|
|
77
|
+
|
|
78
|
+
"@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="],
|
|
79
|
+
|
|
80
|
+
"@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
|
|
81
|
+
|
|
82
|
+
"@biomejs/biome": ["@biomejs/biome@2.4.10", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.10", "@biomejs/cli-darwin-x64": "2.4.10", "@biomejs/cli-linux-arm64": "2.4.10", "@biomejs/cli-linux-arm64-musl": "2.4.10", "@biomejs/cli-linux-x64": "2.4.10", "@biomejs/cli-linux-x64-musl": "2.4.10", "@biomejs/cli-win32-arm64": "2.4.10", "@biomejs/cli-win32-x64": "2.4.10" }, "bin": { "biome": "bin/biome" } }, "sha512-xxA3AphFQ1geij4JTHXv4EeSTda1IFn22ye9LdyVPoJU19fNVl0uzfEuhsfQ4Yue/0FaLs2/ccVi4UDiE7R30w=="],
|
|
83
|
+
|
|
84
|
+
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vuzzI1cWqDVzOMIkYyHbKqp+AkQq4K7k+UCXWpkYcY/HDn1UxdsbsfgtVpa40shem8Kax4TLDLlx8kMAecgqiw=="],
|
|
85
|
+
|
|
86
|
+
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.4.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-14fzASRo+BPotwp7nWULy2W5xeUyFnTaq1V13Etrrxkrih+ez/2QfgFm5Ehtf5vSjtgx/IJycMMpn5kPd5ZNaA=="],
|
|
87
|
+
|
|
88
|
+
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.4.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-7MH1CMW5uuxQ/s7FLST63qF8B3Hgu2HRdZ7tA1X1+mk+St4JOuIrqdhIBnnyqeyWJNI+Bww7Es5QZ0wIc1Cmkw=="],
|
|
89
|
+
|
|
90
|
+
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.4.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-WrJY6UuiSD/Dh+nwK2qOTu8kdMDlLV3dLMmychIghHPAysWFq1/DGC1pVZx8POE3ZkzKR3PUUnVrtZfMfaJjyQ=="],
|
|
91
|
+
|
|
92
|
+
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.4.10", "", { "os": "linux", "cpu": "x64" }, "sha512-tZLvEEi2u9Xu1zAqRjTcpIDGVtldigVvzug2fTuPG0ME/g8/mXpRPcNgLB22bGn6FvLJpHHnqLnwliOu8xjYrg=="],
|
|
93
|
+
|
|
94
|
+
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.4.10", "", { "os": "linux", "cpu": "x64" }, "sha512-kDTi3pI6PBN6CiczsWYOyP2zk0IJI08EWEQyDMQWW221rPaaEz6FvjLhnU07KMzLv8q3qSuoB93ua6inSQ55Tw=="],
|
|
95
|
+
|
|
96
|
+
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.4.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-umwQU6qPzH+ISTf/eHyJ/QoQnJs3V9Vpjz2OjZXe9MVBZ7prgGafMy7yYeRGnlmDAn87AKTF3Q6weLoMGpeqdQ=="],
|
|
97
|
+
|
|
98
|
+
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.10", "", { "os": "win32", "cpu": "x64" }, "sha512-aW/JU5GuyH4uxMrNYpoC2kjaHlyJGLgIa3XkhPEZI0uKhZhJZU8BuEyJmvgzSPQNGozBwWjC972RaNdcJ9KyJg=="],
|
|
99
|
+
|
|
100
|
+
"@gltf-transform/core": ["@gltf-transform/core@4.3.0", "", { "dependencies": { "property-graph": "^4.0.0" } }, "sha512-ZeaQfszGJ9LYwELszu45CuDQCsE26lJNNe36FVmN8xclaT6WDdCj7fwGpQXo0/l/YgAVAHX+uO7YNBW75/SRYw=="],
|
|
101
|
+
|
|
102
|
+
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
|
103
|
+
|
|
104
|
+
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
|
|
105
|
+
|
|
106
|
+
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
|
107
|
+
|
|
108
|
+
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
|
109
|
+
|
|
110
|
+
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
|
111
|
+
|
|
112
|
+
"@tauri-apps/api": ["@tauri-apps/api@2.10.1", "", {}, "sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw=="],
|
|
113
|
+
|
|
114
|
+
"@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="],
|
|
115
|
+
|
|
116
|
+
"@types/gl-matrix": ["@types/gl-matrix@3.2.0", "", { "dependencies": { "gl-matrix": "*" } }, "sha512-CY4JAtSOGQX7rVgqVuOk7ZfaLv8VeadDMPj3smMOy8Hp/YiHONa3Mr0mEUgbo0eEwV7+Owpf6BwspcA7hv4NXg=="],
|
|
117
|
+
|
|
118
|
+
"@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
|
|
119
|
+
|
|
120
|
+
"@types/pngjs": ["@types/pngjs@6.0.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-0k5eKfrA83JOZPppLtS2C7OUtyNAl2wKNxfyYl9Q5g9lPkgBl/9hNyAu6HuEH2J4XmIv2znEpkDd0SaZVxW6iQ=="],
|
|
121
|
+
|
|
122
|
+
"babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.40.6", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-v3P1MW46Lm7VMpAkq0QfyzLWWkC8fh+0aE5Km4msIgDx5kjenHU0pF2s+4/NH8CQn/kla6+Hvws+2AF7bfV5qQ=="],
|
|
123
|
+
|
|
124
|
+
"babel-preset-solid": ["babel-preset-solid@1.9.12", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.40.6" }, "peerDependencies": { "@babel/core": "^7.0.0", "solid-js": "^1.9.12" }, "optionalPeers": ["solid-js"] }, "sha512-LLqnuKVDlKpyBlMPcH6qEvs/wmS9a+NczppxJ3ryS/c0O5IiSFOIBQi9GzyiGDSbcJpx4Gr87jyFTos1MyEuWg=="],
|
|
125
|
+
|
|
126
|
+
"baseline-browser-mapping": ["baseline-browser-mapping@2.10.12", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-qyq26DxfY4awP2gIRXhhLWfwzwI+N5Nxk6iQi8EFizIaWIjqicQTE4sLnZZVdeKPRcVNoJOkkpfzoIYuvCKaIQ=="],
|
|
127
|
+
|
|
128
|
+
"browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="],
|
|
129
|
+
|
|
130
|
+
"bun-plugin-solid": ["bun-plugin-solid@1.0.0", "", { "dependencies": { "@babel/core": ">=7.0.0", "@babel/preset-typescript": ">=7.0.0", "babel-preset-solid": ">=1.8.0" } }, "sha512-H4ZcW4afCLYLDtBsog5cvCfQo8f5E7SD8AeT1woVmIKBOMguy/ml9f1jz9UlikN/i+VK1bS6GII46ZR2OdhbBQ=="],
|
|
131
|
+
|
|
132
|
+
"bun-types": ["bun-types@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="],
|
|
133
|
+
|
|
134
|
+
"caniuse-lite": ["caniuse-lite@1.0.30001781", "", {}, "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw=="],
|
|
135
|
+
|
|
136
|
+
"convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
|
|
137
|
+
|
|
138
|
+
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
|
139
|
+
|
|
140
|
+
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
|
141
|
+
|
|
142
|
+
"electron-to-chromium": ["electron-to-chromium@1.5.328", "", {}, "sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w=="],
|
|
143
|
+
|
|
144
|
+
"entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
|
|
145
|
+
|
|
146
|
+
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
|
|
147
|
+
|
|
148
|
+
"gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
|
|
149
|
+
|
|
150
|
+
"gl-matrix": ["gl-matrix@3.4.4", "", {}, "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ=="],
|
|
151
|
+
|
|
152
|
+
"html-entities": ["html-entities@2.3.3", "", {}, "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA=="],
|
|
153
|
+
|
|
154
|
+
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
|
155
|
+
|
|
156
|
+
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
|
|
157
|
+
|
|
158
|
+
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
|
|
159
|
+
|
|
160
|
+
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
|
161
|
+
|
|
162
|
+
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
|
163
|
+
|
|
164
|
+
"node-releases": ["node-releases@2.0.36", "", {}, "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA=="],
|
|
165
|
+
|
|
166
|
+
"parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
|
|
167
|
+
|
|
168
|
+
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
|
169
|
+
|
|
170
|
+
"pngjs": ["pngjs@7.0.0", "", {}, "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow=="],
|
|
171
|
+
|
|
172
|
+
"property-graph": ["property-graph@4.1.0", "", {}, "sha512-AvPcP7XECNWy4LGmFQ77k7un4lSKM4eS29PTvW4ck95uYeLxXPWJM7hLuBqK91FaHqCcgJvIUCuNJjjxKE7VKQ=="],
|
|
173
|
+
|
|
174
|
+
"semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
|
175
|
+
|
|
176
|
+
"seroval": ["seroval@1.5.1", "", {}, "sha512-OwrZRZAfhHww0WEnKHDY8OM0U/Qs8OTfIDWhUD4BLpNJUfXK4cGmjiagGze086m+mhI+V2nD0gfbHEnJjb9STA=="],
|
|
177
|
+
|
|
178
|
+
"seroval-plugins": ["seroval-plugins@1.5.1", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-4FbuZ/TMl02sqv0RTFexu0SP6V+ywaIe5bAWCCEik0fk17BhALgwvUDVF7e3Uvf9pxmwCEJsRPmlkUE6HdzLAw=="],
|
|
179
|
+
|
|
180
|
+
"solid-js": ["solid-js@1.9.12", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "~1.5.0", "seroval-plugins": "~1.5.0" } }, "sha512-QzKaSJq2/iDrWR1As6MHZQ8fQkdOBf8GReYb7L5iKwMGceg7HxDcaOHk0at66tNgn9U2U7dXo8ZZpLIAmGMzgw=="],
|
|
181
|
+
|
|
182
|
+
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
183
|
+
|
|
184
|
+
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
|
|
185
|
+
|
|
186
|
+
"update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
|
|
187
|
+
|
|
188
|
+
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
|
|
189
|
+
|
|
190
|
+
"babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="],
|
|
191
|
+
}
|
|
192
|
+
}
|
package/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log("Hello via Bun!");
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aether-engine",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "src/index.ts",
|
|
5
|
+
"types": "src/index.ts",
|
|
6
|
+
"module": "src/index.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"devDependencies": {
|
|
9
|
+
"@biomejs/biome": "^2.4.10",
|
|
10
|
+
"@types/bun": "latest",
|
|
11
|
+
"@types/gl-matrix": "^3.2.0",
|
|
12
|
+
"@types/pngjs": "^6.0.5",
|
|
13
|
+
"bun-plugin-solid": "^1.0.0",
|
|
14
|
+
"pngjs": "^7.0.0"
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"typescript": "^5"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@tauri-apps/api": "^2.10.1",
|
|
21
|
+
"@gltf-transform/core": "^4.3.0",
|
|
22
|
+
"gl-matrix": "^3.4.4",
|
|
23
|
+
"solid-js": "^1.9.12"
|
|
24
|
+
}
|
|
25
|
+
}
|
package/serve.ts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { serve } from "bun";
|
|
3
|
+
import { SolidPlugin } from "bun-plugin-solid";
|
|
4
|
+
|
|
5
|
+
// Trigger an initial build
|
|
6
|
+
await Bun.build({
|
|
7
|
+
entrypoints: ["./dev/main.tsx"],
|
|
8
|
+
outdir: "./dev/dist",
|
|
9
|
+
plugins: [SolidPlugin()],
|
|
10
|
+
sourcemap: "inline",
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
console.log("Serving at http://localhost:3000");
|
|
14
|
+
|
|
15
|
+
serve({
|
|
16
|
+
port: 3000,
|
|
17
|
+
async fetch(req: Request) {
|
|
18
|
+
const url = new URL(req.url);
|
|
19
|
+
|
|
20
|
+
if (url.pathname === "/__aether_dev/list-sprites" && req.method === "GET") {
|
|
21
|
+
const dirPath = join(process.cwd(), "public/assets/sprites");
|
|
22
|
+
const fs = require("node:fs");
|
|
23
|
+
if (!fs.existsSync(dirPath)) {
|
|
24
|
+
return new Response(JSON.stringify([]), {
|
|
25
|
+
headers: { "Content-Type": "application/json" },
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
const files = fs.readdirSync(dirPath);
|
|
29
|
+
const sprites = files
|
|
30
|
+
.filter((f: string) => f.endsWith(".json"))
|
|
31
|
+
.map((f: string) => f.replace(".json", ""));
|
|
32
|
+
return new Response(JSON.stringify(sprites), {
|
|
33
|
+
headers: { "Content-Type": "application/json" },
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Integrated DevTools Asset Persistance API (Stripped from production logic)
|
|
38
|
+
if (
|
|
39
|
+
url.pathname === "/__aether_dev/save-sprite-meta" &&
|
|
40
|
+
req.method === "POST"
|
|
41
|
+
) {
|
|
42
|
+
const data = await req.json();
|
|
43
|
+
const name = data.name || "unnamed_sprite";
|
|
44
|
+
const dirPath = join(process.cwd(), "public/assets/sprites");
|
|
45
|
+
const fs = require("node:fs");
|
|
46
|
+
if (!fs.existsSync(dirPath)) fs.mkdirSync(dirPath, { recursive: true });
|
|
47
|
+
await Bun.write(
|
|
48
|
+
join(dirPath, `${name}.json`),
|
|
49
|
+
JSON.stringify(data.metadata, null, 2),
|
|
50
|
+
);
|
|
51
|
+
return new Response(
|
|
52
|
+
JSON.stringify({
|
|
53
|
+
success: true,
|
|
54
|
+
assetPath: `/public/assets/sprites/${name}.json`,
|
|
55
|
+
}),
|
|
56
|
+
{ headers: { "Content-Type": "application/json" } },
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (url.pathname === "/__aether_dev/save-sprite" && req.method === "POST") {
|
|
61
|
+
const data = await req.json();
|
|
62
|
+
const name = data.name || "unnamed_sprite";
|
|
63
|
+
const base64Data = data.png.replace(/^data:image\/png;base64,/, "");
|
|
64
|
+
|
|
65
|
+
const dirPath = join(process.cwd(), "public/assets/sprites");
|
|
66
|
+
const fs = require("node:fs");
|
|
67
|
+
if (!fs.existsSync(dirPath)) {
|
|
68
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
await Bun.write(
|
|
72
|
+
join(dirPath, `${name}.png`),
|
|
73
|
+
Buffer.from(base64Data, "base64"),
|
|
74
|
+
);
|
|
75
|
+
await Bun.write(
|
|
76
|
+
join(dirPath, `${name}.json`),
|
|
77
|
+
JSON.stringify(data.metadata, null, 2),
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return new Response(
|
|
81
|
+
JSON.stringify({
|
|
82
|
+
success: true,
|
|
83
|
+
assetPath: `/public/assets/sprites/${name}.png`,
|
|
84
|
+
}),
|
|
85
|
+
{ headers: { "Content-Type": "application/json" } },
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Static Asset Serving
|
|
90
|
+
if (url.pathname.startsWith("/public/")) {
|
|
91
|
+
const decoded = decodeURIComponent(url.pathname);
|
|
92
|
+
const filePath = join(process.cwd(), decoded);
|
|
93
|
+
const file = Bun.file(filePath);
|
|
94
|
+
const exists = await file.exists();
|
|
95
|
+
console.log(
|
|
96
|
+
`[serve] path: ${url.pathname} -> decoded: ${decoded} -> filePath: ${filePath} -> exists: ${exists}`,
|
|
97
|
+
);
|
|
98
|
+
if (exists) {
|
|
99
|
+
return new Response(file);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (url.pathname === "/") {
|
|
104
|
+
let html = await Bun.file("./dev/index.html").text();
|
|
105
|
+
html = html.replace(
|
|
106
|
+
"<head>",
|
|
107
|
+
`<head>\n <meta name="aether-app-id" content="${process.cwd()}" />`,
|
|
108
|
+
);
|
|
109
|
+
return new Response(html, { headers: { "Content-Type": "text/html" } });
|
|
110
|
+
}
|
|
111
|
+
if (url.pathname === "/dist/main.js") {
|
|
112
|
+
// Rebuild on request for fast dev iteration
|
|
113
|
+
await Bun.build({
|
|
114
|
+
entrypoints: ["./dev/main.tsx"],
|
|
115
|
+
outdir: "./dev/dist",
|
|
116
|
+
plugins: [SolidPlugin()],
|
|
117
|
+
sourcemap: "inline",
|
|
118
|
+
});
|
|
119
|
+
return new Response(Bun.file("./dev/dist/main.js"), {
|
|
120
|
+
headers: { "Content-Type": "application/javascript" },
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return new Response("Not Found", { status: 404 });
|
|
124
|
+
},
|
|
125
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// biome-ignore lint/complexity/noStaticOnlyClass: Engine architecture uses static manager classes
|
|
2
|
+
export class AudioEngine {
|
|
3
|
+
private static _context: AudioContext | null = null;
|
|
4
|
+
private static _buffers = new Map<string, AudioBuffer>();
|
|
5
|
+
|
|
6
|
+
private static _decoderContext: OfflineAudioContext | null = null;
|
|
7
|
+
public static hasUserInteracted: boolean = false;
|
|
8
|
+
private static _listenersAttached: boolean = false;
|
|
9
|
+
|
|
10
|
+
static attachListeners() {
|
|
11
|
+
if (AudioEngine._listenersAttached) return;
|
|
12
|
+
AudioEngine._listenersAttached = true;
|
|
13
|
+
const resumeAudio = () => {
|
|
14
|
+
AudioEngine.hasUserInteracted = true;
|
|
15
|
+
if (!AudioEngine._context) {
|
|
16
|
+
AudioEngine._context = new (
|
|
17
|
+
window.AudioContext || (window as any).webkitAudioContext
|
|
18
|
+
)();
|
|
19
|
+
}
|
|
20
|
+
if (AudioEngine._context.state === "suspended") {
|
|
21
|
+
AudioEngine._context.resume();
|
|
22
|
+
}
|
|
23
|
+
["keydown", "mousedown", "touchstart", "pointerdown"].forEach((e) => {
|
|
24
|
+
window.removeEventListener(e, resumeAudio);
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
["keydown", "mousedown", "touchstart", "pointerdown"].forEach((e) => {
|
|
28
|
+
window.addEventListener(e, resumeAudio, { once: true });
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static get context() {
|
|
33
|
+
AudioEngine.attachListeners();
|
|
34
|
+
if (!AudioEngine._context) {
|
|
35
|
+
// Do not instantiate immediately unless interacted, or if forced
|
|
36
|
+
// Developers won't be able to access context actively until interaction
|
|
37
|
+
}
|
|
38
|
+
return AudioEngine._context;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static async load(url: string, name: string) {
|
|
42
|
+
AudioEngine.attachListeners();
|
|
43
|
+
const response = await fetch(url);
|
|
44
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
45
|
+
|
|
46
|
+
if (!AudioEngine._decoderContext) {
|
|
47
|
+
AudioEngine._decoderContext = new (
|
|
48
|
+
window.OfflineAudioContext || (window as any).webkitOfflineAudioContext
|
|
49
|
+
)(1, 1, 44100);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const audioBuffer =
|
|
53
|
+
await AudioEngine._decoderContext.decodeAudioData(arrayBuffer);
|
|
54
|
+
AudioEngine._buffers.set(name, audioBuffer);
|
|
55
|
+
return audioBuffer;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static getBuffer(name: string): AudioBuffer | undefined {
|
|
59
|
+
return AudioEngine._buffers.get(name);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { GLTFAnimation, GLTFSkin, GLTFNode } from "../utils/GLTFLoader";
|
|
2
|
+
import { mat4, quat, vec3 } from "gl-matrix";
|
|
3
|
+
|
|
4
|
+
export class Animator3D {
|
|
5
|
+
public animations: Map<string, GLTFAnimation> = new Map();
|
|
6
|
+
public currentAnimation: string | null = null;
|
|
7
|
+
|
|
8
|
+
public skins: GLTFSkin[] = [];
|
|
9
|
+
public nodes: GLTFNode[] = [];
|
|
10
|
+
|
|
11
|
+
public time: number = 0;
|
|
12
|
+
public speed: number = 1.0;
|
|
13
|
+
public loop: boolean = true;
|
|
14
|
+
public isPlaying: boolean = true;
|
|
15
|
+
|
|
16
|
+
// Output buffer size: maximum 64 bones * 16 floats per mat4 = 1024 floats
|
|
17
|
+
public jointMatrices: Float32Array = new Float32Array(64 * 16);
|
|
18
|
+
public localTransforms: mat4[] = [];
|
|
19
|
+
|
|
20
|
+
constructor(animations: GLTFAnimation[], skins: GLTFSkin[], nodes: GLTFNode[]) {
|
|
21
|
+
for (const anim of animations) {
|
|
22
|
+
this.animations.set(anim.name, anim);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (animations.length > 0) {
|
|
26
|
+
this.currentAnimation = animations[0].name;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Deep clone nodes and skins so each instance can animate independently
|
|
30
|
+
// In a production engine, you'd want to share the base skeleton and only unique the local transforms
|
|
31
|
+
this.nodes = nodes.map(n => ({
|
|
32
|
+
...n,
|
|
33
|
+
translation: vec3.clone(n.translation),
|
|
34
|
+
rotation: quat.clone(n.rotation),
|
|
35
|
+
scale: vec3.clone(n.scale),
|
|
36
|
+
globalMatrix: mat4.clone(n.globalMatrix)
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
this.skins = skins;
|
|
40
|
+
|
|
41
|
+
for(let i=0; i<this.nodes.length; i++) {
|
|
42
|
+
this.localTransforms.push(mat4.create());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
for(let i=0; i<this.jointMatrices.length; i+=16) {
|
|
46
|
+
mat4.identity(new Float32Array(this.jointMatrices.buffer, i * 4, 16));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public play(name: string, loop: boolean = true) {
|
|
51
|
+
if (this.animations.has(name)) {
|
|
52
|
+
this.currentAnimation = name;
|
|
53
|
+
this.time = 0;
|
|
54
|
+
this.loop = loop;
|
|
55
|
+
this.isPlaying = true;
|
|
56
|
+
} else {
|
|
57
|
+
console.warn(`Animation ${name} not found.`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public stop() {
|
|
62
|
+
this.isPlaying = false;
|
|
63
|
+
this.time = 0;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export class AudioSource {
|
|
2
|
+
public bufferName: string = "";
|
|
3
|
+
public volume: number = 1.0;
|
|
4
|
+
public loop: boolean = false;
|
|
5
|
+
|
|
6
|
+
// Triggers
|
|
7
|
+
public shouldPlay: boolean = false;
|
|
8
|
+
public isPlaying: boolean = false;
|
|
9
|
+
|
|
10
|
+
// Internal WebAudio states
|
|
11
|
+
public _sourceNode?: AudioBufferSourceNode;
|
|
12
|
+
public _gainNode?: GainNode;
|
|
13
|
+
|
|
14
|
+
constructor(bufferName: string = "", volume: number = 1.0) {
|
|
15
|
+
this.bufferName = bufferName;
|
|
16
|
+
this.volume = volume;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
play() {
|
|
20
|
+
this.shouldPlay = true;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
stop() {
|
|
24
|
+
this.shouldPlay = false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Color } from "../math/Color";
|
|
2
|
+
|
|
3
|
+
export class BitmapText {
|
|
4
|
+
public _text: string = "";
|
|
5
|
+
public fontId: string;
|
|
6
|
+
public color: Color = Color.White();
|
|
7
|
+
|
|
8
|
+
public isDirty: boolean = true;
|
|
9
|
+
|
|
10
|
+
constructor(text: string, fontId: string) {
|
|
11
|
+
this._text = text;
|
|
12
|
+
this.fontId = fontId;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
get text(): string {
|
|
16
|
+
return this._text;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
set text(value: string) {
|
|
20
|
+
if (this._text !== value) {
|
|
21
|
+
this._text = value;
|
|
22
|
+
this.isDirty = true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { mat4 } from "gl-matrix";
|
|
2
|
+
|
|
3
|
+
export class Camera {
|
|
4
|
+
public projectionMatrix: mat4 = mat4.create();
|
|
5
|
+
public viewMatrix: mat4 = mat4.create();
|
|
6
|
+
public isOrthographic: boolean = false;
|
|
7
|
+
|
|
8
|
+
// Perspective properties
|
|
9
|
+
public fov: number = (45 * Math.PI) / 180;
|
|
10
|
+
public aspect: number = 1.0;
|
|
11
|
+
public near: number = 0.1;
|
|
12
|
+
public far: number = 1000.0;
|
|
13
|
+
|
|
14
|
+
// Orthographic properties
|
|
15
|
+
public orthoSize: number = 5;
|
|
16
|
+
|
|
17
|
+
updateProjection(width: number, height: number) {
|
|
18
|
+
this.aspect = width / Math.max(height, 1);
|
|
19
|
+
if (this.isOrthographic) {
|
|
20
|
+
const w = this.orthoSize * this.aspect;
|
|
21
|
+
const h = this.orthoSize;
|
|
22
|
+
mat4.ortho(this.projectionMatrix, -w, w, -h, h, this.near, this.far);
|
|
23
|
+
} else {
|
|
24
|
+
mat4.perspective(
|
|
25
|
+
this.projectionMatrix,
|
|
26
|
+
this.fov,
|
|
27
|
+
this.aspect,
|
|
28
|
+
this.near,
|
|
29
|
+
this.far,
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|