@series-inc/stowkit-cli 0.6.34 → 0.6.35

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.
@@ -0,0 +1,40 @@
1
+ import { cpSync, mkdirSync, existsSync } from "node:fs"
2
+ import { resolve, dirname } from "node:path"
3
+ import { fileURLToPath } from "node:url"
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url))
6
+ const root = resolve(__dirname, "..")
7
+
8
+ function copyDir(src, dest) {
9
+ if (!existsSync(src)) return false
10
+ mkdirSync(dest, { recursive: true })
11
+ cpSync(src, dest, { recursive: true })
12
+ return true
13
+ }
14
+
15
+ function copyFile(src, dest) {
16
+ if (!existsSync(src)) return false
17
+ mkdirSync(dirname(dest), { recursive: true })
18
+ cpSync(src, dest)
19
+ return true
20
+ }
21
+
22
+ const loaderPkg = resolve(root, "node_modules/@series-inc/stowkit-three-loader/public")
23
+ const readerPkg = resolve(root, "node_modules/@series-inc/stowkit-reader/dist")
24
+
25
+ let ok = true
26
+
27
+ // basis/ — engine default path: "basis/"
28
+ ok = copyDir(resolve(loaderPkg, "basis"), resolve(root, "public/basis")) && ok
29
+
30
+ // stowkit/draco/ — engine default path: "stowkit/draco/"
31
+ ok = copyDir(resolve(loaderPkg, "draco"), resolve(root, "public/stowkit/draco")) && ok
32
+
33
+ // stowkit_reader.wasm — engine default path: "stowkit_reader.wasm"
34
+ ok = copyFile(resolve(readerPkg, "stowkit_reader.wasm"), resolve(root, "public/stowkit_reader.wasm")) && ok
35
+
36
+ if (ok) {
37
+ console.log("Copied WASM decoders to public/")
38
+ } else {
39
+ console.warn("Warning: some decoder files were not found. Run npm install to ensure all packages are present.")
40
+ }
@@ -0,0 +1,84 @@
1
+ import * as THREE from "three"
2
+ import { AssetManager, VenusGame } from "@series-inc/rundot-3d-engine"
3
+ import { AudioSystem, PhysicsSystem } from "@series-inc/rundot-3d-engine/systems"
4
+ import RundotGameAPI from "@series-inc/rundot-game-sdk/api"
5
+ import { Prefabs } from "./Prefabs"
6
+
7
+ export class Game extends VenusGame {
8
+ protected getConfig() {
9
+ const isMobile = /Android|iPhone|iPad|iPod/i.test(navigator.userAgent) || "ontouchstart" in window
10
+ return {
11
+ backgroundColor: 0x87ceeb,
12
+ shadowMapEnabled: true,
13
+ shadowMapType: isMobile ? "basic" as const : "pcf_soft" as const,
14
+ toneMapping: "linear" as const,
15
+ toneMappingExposure: 1.0,
16
+ audioEnabled: true,
17
+ }
18
+ }
19
+
20
+ protected async onStart(): Promise<void> {
21
+ this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
22
+
23
+ // Initialize engine systems
24
+ AssetManager.init(this.scene)
25
+ AudioSystem.initialize()
26
+ await Promise.all([
27
+ PhysicsSystem.initialize(),
28
+ Prefabs.initialize(),
29
+ ])
30
+
31
+ await RundotGameAPI.preloader.setLoaderProgress(0.5)
32
+
33
+ this.setupLighting()
34
+ this.setupCamera()
35
+
36
+ // --- Your game setup goes here ---
37
+
38
+ await VenusGame.loadingFinished()
39
+ }
40
+
41
+ protected preRender(_deltaTime: number): void {
42
+ // Called every frame before render. Use for game updates.
43
+ }
44
+
45
+ protected async onDispose(): Promise<void> {
46
+ // Cleanup when game is destroyed.
47
+ }
48
+
49
+ private setupLighting(): void {
50
+ const sun = new THREE.DirectionalLight(0xffffff, 1.5)
51
+ sun.position.set(10, 20, 10)
52
+ sun.castShadow = true
53
+ sun.shadow.mapSize.set(1024, 1024)
54
+ sun.shadow.camera.left = -30
55
+ sun.shadow.camera.right = 30
56
+ sun.shadow.camera.top = 30
57
+ sun.shadow.camera.bottom = -30
58
+ sun.shadow.camera.near = 1
59
+ sun.shadow.camera.far = 100
60
+ this.scene.add(sun)
61
+ this.scene.add(sun.target)
62
+
63
+ const ambient = new THREE.AmbientLight(0xffffff, 0.5)
64
+ this.scene.add(ambient)
65
+ }
66
+
67
+ private setupCamera(): void {
68
+ const camera = new THREE.PerspectiveCamera(
69
+ 60,
70
+ window.innerWidth / window.innerHeight,
71
+ 0.1,
72
+ 500,
73
+ )
74
+ camera.position.set(0, 5, 10)
75
+ camera.lookAt(0, 0, 0)
76
+ this.scene.add(camera)
77
+ this.camera = camera
78
+
79
+ window.addEventListener("resize", () => {
80
+ camera.aspect = window.innerWidth / window.innerHeight
81
+ camera.updateProjectionMatrix()
82
+ })
83
+ }
84
+ }
@@ -0,0 +1,28 @@
1
+ import RundotGameAPI from "@series-inc/rundot-game-sdk/api"
2
+ import { GameObject } from "@series-inc/rundot-3d-engine"
3
+ import { PrefabCollection, PrefabLoader, StowKitSystem } from "@series-inc/rundot-3d-engine/systems"
4
+
5
+ export class Prefabs {
6
+ private static collection: PrefabCollection
7
+
8
+ private constructor() {
9
+ throw new Error("Prefabs is a static class and cannot be instantiated")
10
+ }
11
+
12
+ public static async initialize() {
13
+ const stowkit = StowKitSystem.getInstance()
14
+
15
+ const buildJson = (await import("../prefabs/build.json")).default
16
+ this.collection = await stowkit.loadFromBuildJson(buildJson, {
17
+ fetchBlob: (path) => RundotGameAPI.cdn.fetchAsset(path)
18
+ })
19
+ }
20
+
21
+ public static instantiate(name: string, parent?: GameObject) {
22
+ const prefab = this.collection.getPrefabByName(name)
23
+ if (!prefab) {
24
+ throw new Error(`Prefab not found: ${name}`)
25
+ }
26
+ return PrefabLoader.instantiatePrefab(prefab, parent)
27
+ }
28
+ }
@@ -0,0 +1,16 @@
1
+ import "./styles/main.css"
2
+ import RundotGameAPI from "@series-inc/rundot-game-sdk/api"
3
+ import { Game } from "./Game"
4
+
5
+ ;(async function () {
6
+ try {
7
+ await RundotGameAPI.preloader.showLoadScreen()
8
+ await RundotGameAPI.preloader.setLoaderProgress(0)
9
+
10
+ const game = await Game.create()
11
+ ;(window as any).game = game
12
+ } catch (error) {
13
+ console.error("Failed to start game:", error)
14
+ try { await RundotGameAPI.preloader.hideLoadScreen() } catch {}
15
+ }
16
+ })()
@@ -0,0 +1,22 @@
1
+ html, body {
2
+ width: 100%;
3
+ height: 100%;
4
+ margin: 0;
5
+ padding: 0;
6
+ overflow: hidden;
7
+ background-color: #333333;
8
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
9
+ }
10
+
11
+ #renderCanvas {
12
+ width: 100%;
13
+ height: 100%;
14
+ touch-action: none;
15
+ outline: none;
16
+ display: block;
17
+ }
18
+
19
+ * {
20
+ -webkit-tap-highlight-color: transparent;
21
+ box-sizing: border-box;
22
+ }
@@ -0,0 +1,6 @@
1
+ // Stub for Capacitor modules - not needed for web-only builds
2
+ export const Capacitor = { isNativePlatform: () => false, getPlatform: () => "web" }
3
+ export const Preferences = { get: async () => ({}), set: async () => {}, remove: async () => {} }
4
+ export const LocalNotifications = { schedule: async () => {}, addListener: () => ({ remove: () => {} }) }
5
+ export const App = { addListener: () => ({ remove: () => {} }) }
6
+ export const SplashScreen = { hide: async () => {} }
@@ -0,0 +1,27 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "useDefineForClassFields": true,
5
+ "module": "ESNext",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "skipLibCheck": true,
8
+ "allowJs": true,
9
+ "moduleResolution": "bundler",
10
+ "allowImportingTsExtensions": true,
11
+ "resolveJsonModule": true,
12
+ "isolatedModules": true,
13
+ "noEmit": true,
14
+ "strict": true,
15
+ "noUnusedLocals": false,
16
+ "noUnusedParameters": false,
17
+ "noFallthroughCasesInSwitch": true,
18
+ "experimentalDecorators": true,
19
+ "emitDecoratorMetadata": true,
20
+ "baseUrl": ".",
21
+ "paths": {
22
+ "@/*": ["src/*"]
23
+ }
24
+ },
25
+ "include": ["src/**/*", "vite-env.d.ts"],
26
+ "exclude": ["node_modules", "dist"]
27
+ }
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
@@ -0,0 +1,39 @@
1
+ import { defineConfig } from "vite"
2
+ import wasm from "vite-plugin-wasm"
3
+ import topLevelAwait from "vite-plugin-top-level-await"
4
+ import path from "path"
5
+
6
+ export default defineConfig(() => ({
7
+ base: "./",
8
+ resolve: {
9
+ dedupe: ['three', '@series-inc/rundot-game-sdk', '@series-inc/stowkit-three-loader', '@series-inc/stowkit-reader'],
10
+ alias: {
11
+ "@": path.resolve(__dirname, "./src"),
12
+ "@capacitor/core": path.resolve(__dirname, "./stubs/capacitor.ts"),
13
+ "@capacitor/app": path.resolve(__dirname, "./stubs/capacitor.ts"),
14
+ "@capacitor/local-notifications": path.resolve(__dirname, "./stubs/capacitor.ts"),
15
+ "@capacitor/preferences": path.resolve(__dirname, "./stubs/capacitor.ts"),
16
+ "@capacitor/splash-screen": path.resolve(__dirname, "./stubs/capacitor.ts"),
17
+ },
18
+ },
19
+ optimizeDeps: {
20
+ exclude: ["@dimforge/rapier3d"],
21
+ },
22
+ server: {
23
+ port: 3033,
24
+ host: "0.0.0.0",
25
+ allowedHosts: true,
26
+ },
27
+ build: {
28
+ outDir: "dist",
29
+ assetsDir: "assets",
30
+ emptyOutDir: true,
31
+ target: "esnext",
32
+ sourcemap: false,
33
+ },
34
+ publicDir: "public",
35
+ plugins: [
36
+ wasm(),
37
+ topLevelAwait(),
38
+ ],
39
+ }))