bard-legends-framework 1.11.4 → 1.12.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/AGENTS.md +52 -5
- package/bin/cli.mjs +12 -0
- package/dist/electron-main.d.mts +18 -0
- package/dist/electron-main.d.ts +18 -0
- package/dist/electron-main.js +1 -0
- package/dist/electron-main.mjs +1 -0
- package/dist/electron-preload.d.mts +9 -0
- package/dist/electron-preload.d.ts +9 -0
- package/dist/electron-preload.js +1 -0
- package/dist/electron-preload.mjs +1 -0
- package/dist/index.d.mts +136 -80
- package/dist/index.d.ts +136 -80
- package/dist/index.js +3 -3
- package/dist/index.mjs +3 -3
- package/electron-forge.mjs +37 -0
- package/package.json +52 -13
package/AGENTS.md
CHANGED
|
@@ -223,24 +223,71 @@ export class TitleScene extends Scene<void, TitleSceneOutputDTO> { // <Input, O
|
|
|
223
223
|
|
|
224
224
|
---
|
|
225
225
|
|
|
226
|
-
## Bootstrap
|
|
226
|
+
## Bootstrap (Electron)
|
|
227
|
+
|
|
228
|
+
The framework owns the whole Electron shell. A game has four one-liner entry files:
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
// src/main.ts — Electron main process
|
|
232
|
+
import { ElectronApp } from 'bard-legends-framework/main';
|
|
233
|
+
ElectronApp.start({ defaultWindowSize, minWindowSize, maxWindowSize });
|
|
234
|
+
|
|
235
|
+
// src/preload.ts — context bridge (exposes window.api)
|
|
236
|
+
import { ElectronPreload } from 'bard-legends-framework/preload';
|
|
237
|
+
ElectronPreload.expose();
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
```js
|
|
241
|
+
// forge.config.mjs — electron-forge build config
|
|
242
|
+
import { ElectronForge } from 'bard-legends-framework/forge';
|
|
243
|
+
export default ElectronForge.createForgeConfig();
|
|
244
|
+
```
|
|
227
245
|
|
|
228
246
|
```ts
|
|
229
|
-
|
|
247
|
+
// src/renderer.ts — the game
|
|
248
|
+
import { ElectronGame, Service } from 'bard-legends-framework';
|
|
230
249
|
|
|
231
250
|
// MANDATORY: register every controller and view via side-effecting import (Vite glob).
|
|
251
|
+
// Globs resolve relative to the importing file, so they must stay in the game's renderer entry.
|
|
232
252
|
import.meta.glob('./**/*.controller.ts', { eager: true });
|
|
233
253
|
import.meta.glob('./**/*.view.ts', { eager: true });
|
|
234
254
|
|
|
235
|
-
|
|
236
|
-
await game.setup({ assetDefinitions: [...SpriteAssets, ...FontAssets], spriteDefinitions: SpriteDefinitions });
|
|
255
|
+
await ElectronGame.start({ resolution: 2 }, { spriteAssetDefinitions, spriteDefinitions, /* fonts, sounds */ });
|
|
237
256
|
Service.get(GameCycleGateway).startGame(); // kick off the first scene via a gateway
|
|
238
257
|
```
|
|
239
258
|
|
|
259
|
+
- `ElectronApp.start` runs window management, fullscreen, focus events, encrypted save-file IO and
|
|
260
|
+
quit over IPC. `ElectronPreload.expose` publishes the typed `window.api` bridge (`ElectronBridge`).
|
|
261
|
+
`ElectronGame.start` fetches `devMode`/`maxScreenResolution` from the main process, creates the
|
|
262
|
+
`Game`, awaits `setup` (asset loading), wires window focus → `Game.pause` and tab visibility →
|
|
263
|
+
`Game.freeze`, and reports the renderer ready.
|
|
264
|
+
- **Custom IPC** (both directions):
|
|
265
|
+
- renderer → main: pass `ipcHandlers: { channelName: handler }` to `ElectronApp.start` and list
|
|
266
|
+
the channel in `ElectronPreload.expose({ invokes: ['channelName'] })`; it appears on
|
|
267
|
+
`window.api` as an async method.
|
|
268
|
+
- main → renderer: pass `onWindowCreated: mainWindow => { ... }` to `ElectronApp.start` and push
|
|
269
|
+
with `mainWindow.webContents.send(channel, data)`; list the channel in
|
|
270
|
+
`ElectronPreload.expose({ events: ['channelName'] })` and it appears on `window.api` as a
|
|
271
|
+
subscription method `(callback) => unsubscribe`.
|
|
272
|
+
- Type both by augmenting the `ElectronBridge` interface from any game module:
|
|
273
|
+
`declare module 'bard-legends-framework' { interface ElectronBridge { channelName(...): ...; } }`
|
|
274
|
+
- The `Game-Boilerplate` repo demonstrates both (`sendMessageToMain` invoke, `screenSize` event).
|
|
275
|
+
- The `@electron-forge/*` packages (cli, makers, plugin-vite) are **dependencies of the framework**
|
|
276
|
+
— game projects keep only `electron` and `vite` as devDependencies (forge requires `electron` in
|
|
277
|
+
the app's own devDependencies).
|
|
278
|
+
- Games never invoke `electron-forge` directly. The framework ships a CLI at `bin/cli.mjs` that
|
|
279
|
+
forwards to its own `@electron-forge/cli` (so the forge version always matches the framework's,
|
|
280
|
+
linked or published). Game scripts call it by path, which resolves in both modes:
|
|
281
|
+
```json
|
|
282
|
+
"start": "set \"ENVIRONMENT=dev\" && node node_modules/bard-legends-framework/bin/cli.mjs start",
|
|
283
|
+
"build": "npm run test-full && node node_modules/bard-legends-framework/bin/cli.mjs package",
|
|
284
|
+
"build-with-installer": "npm run test-full && node node_modules/bard-legends-framework/bin/cli.mjs make",
|
|
285
|
+
"deploy": "npm run test-full && node node_modules/bard-legends-framework/bin/cli.mjs publish"
|
|
286
|
+
```
|
|
240
287
|
- `Game` is the global singleton: `Game.instance`, `Game.camera`, `Game.time`, `Game.pause`
|
|
241
288
|
(a `Reducer<boolean>` — open an effect to pause), `Game.instance.screenSize`/`screenSizeCenter`
|
|
242
289
|
(`PersistentNotifier<Vector>`), `setResolution`, `screenPositonToStagePosition`.
|
|
243
|
-
- `setup` loads assets and must be awaited before any scene opens.
|
|
290
|
+
- `setup` loads assets and must be awaited before any scene opens (`ElectronGame.start` does both).
|
|
244
291
|
- If you add a module, no manual registration is needed **as long as** files keep the
|
|
245
292
|
`*.controller.ts` / `*.view.ts` suffixes so the globs pick them up.
|
|
246
293
|
|
package/bin/cli.mjs
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'child_process';
|
|
3
|
+
import { createRequire } from 'module';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
|
|
6
|
+
let require = createRequire(import.meta.url);
|
|
7
|
+
let forgePackageJsonPath = require.resolve('@electron-forge/cli/package.json');
|
|
8
|
+
let forgeBinPath = path.join(path.dirname(forgePackageJsonPath), require(forgePackageJsonPath).bin['electron-forge']);
|
|
9
|
+
|
|
10
|
+
spawn(process.execPath, [forgeBinPath, ...process.argv.slice(2)], { stdio: 'inherit' }).on('exit', code =>
|
|
11
|
+
process.exit(code ?? 0)
|
|
12
|
+
);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BrowserWindow } from 'electron';
|
|
2
|
+
|
|
3
|
+
interface ElectronWindowSize {
|
|
4
|
+
readonly width: number;
|
|
5
|
+
readonly height: number;
|
|
6
|
+
}
|
|
7
|
+
interface ElectronAppConfiguration {
|
|
8
|
+
readonly defaultWindowSize: ElectronWindowSize;
|
|
9
|
+
readonly minWindowSize: ElectronWindowSize;
|
|
10
|
+
readonly maxWindowSize: ElectronWindowSize;
|
|
11
|
+
readonly ipcHandlers?: Readonly<Record<string, (...args: never[]) => unknown>>;
|
|
12
|
+
readonly onWindowCreated?: (mainWindow: BrowserWindow) => void;
|
|
13
|
+
}
|
|
14
|
+
declare class ElectronApp {
|
|
15
|
+
static start(configuration: ElectronAppConfiguration): void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { ElectronApp, type ElectronAppConfiguration, type ElectronWindowSize };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BrowserWindow } from 'electron';
|
|
2
|
+
|
|
3
|
+
interface ElectronWindowSize {
|
|
4
|
+
readonly width: number;
|
|
5
|
+
readonly height: number;
|
|
6
|
+
}
|
|
7
|
+
interface ElectronAppConfiguration {
|
|
8
|
+
readonly defaultWindowSize: ElectronWindowSize;
|
|
9
|
+
readonly minWindowSize: ElectronWindowSize;
|
|
10
|
+
readonly maxWindowSize: ElectronWindowSize;
|
|
11
|
+
readonly ipcHandlers?: Readonly<Record<string, (...args: never[]) => unknown>>;
|
|
12
|
+
readonly onWindowCreated?: (mainWindow: BrowserWindow) => void;
|
|
13
|
+
}
|
|
14
|
+
declare class ElectronApp {
|
|
15
|
+
static start(configuration: ElectronAppConfiguration): void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { ElectronApp, type ElectronAppConfiguration, type ElectronWindowSize };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var electron=require('electron'),T=require('electron-squirrel-startup'),w=require('path'),child_process=require('child_process'),p=require('crypto'),y=require('fs/promises'),V=require('write-file-atomic'),helpersLib=require('helpers-lib');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var T__default=/*#__PURE__*/_interopDefault(T);var w__default=/*#__PURE__*/_interopDefault(w);var p__default=/*#__PURE__*/_interopDefault(p);var y__default=/*#__PURE__*/_interopDefault(y);var V__default=/*#__PURE__*/_interopDefault(V);var v=Object.defineProperty;var n=(d,e)=>v(d,"name",{value:e,configurable:true});var h=class{static{n(this,"SingleAsyncQueue");}constructor(){this.ƀkt=false,this.ƀjf=new helpersLib.Queue;}async enqueue(e){let t=this.ƀjf.empty,a=new Promise((i,r)=>this.ƀjf.add({operation:e,resolve:i,reject:r}));return t&&this.ƀjt(),a}ƀjt(){if(!this.ƀkt){let e=[];for(;this.ƀjf.notEmpty;){let t=this.ƀjf.pop();t&&e.push(t);}e.length>0&&this.ƀju(e);}}ƀju(e){let t=e.pop();if(!t)throw new Error("No executing entry found");this.ƀkt=true,t.operation().then(()=>{e.forEach(a=>a.resolve()),t.resolve(),this.ƀkt=false,this.ƀjt();}).catch(a=>{t.reject(a),e.length>0?this.ƀju(e):(this.ƀkt=false,this.ƀjt());});}};var g=w__default.default.join(electron.app.getPath("userData"),"saves"),_=1,f=p__default.default.scryptSync("gdfgmhur%+/&ty@ertbdf423-secret","ga!sgnwq6^/&(roofvafnl_salt",32),c=class{static{n(this,"MainSaveLoad");}static{this.ƀdq=new Map;}static ƀev(e){let t=this.ƀdq.get(e);return t||(t=new h,this.ƀdq.set(e,t)),t}static async save(e,t){return this.ƀev(t).enqueue(()=>this.ƀlm(e,t))}static async load(e){return this.ƀjj(e)}static async ƀlm(e,t){let a=this.ƀep(),i=w__default.default.join(g,t);if(await y__default.default.mkdir(g,{recursive:true}),!e)await y__default.default.rm(i,{force:true});else {let r=this.ƀdf(e,f),s=this.ƀdf(a,f),u={version:_,data:{initializationVector:r.initializationVector,encrypted:r.encrypted,authTag:r.authTag},machineId:{initializationVector:s.initializationVector,encrypted:s.encrypted,authTag:s.authTag}};await V__default.default(i,JSON.stringify(u),{encoding:"utf-8"});}}static async ƀjj(e){let t=w__default.default.join(g,e),a;try{a=await y__default.default.readFile(t,"utf-8");}catch{return}let i=JSON.parse(a),r={version:i.version,data:{initializationVector:Buffer.from(i.data.initializationVector),encrypted:Buffer.from(i.data.encrypted),authTag:Buffer.from(i.data.authTag)},machineId:{initializationVector:Buffer.from(i.machineId.initializationVector),encrypted:Buffer.from(i.machineId.encrypted),authTag:Buffer.from(i.machineId.authTag)}},s=this.ƀct(r.data.encrypted,f,r.data.initializationVector,r.data.authTag);if(this.ƀct(r.machineId.encrypted,f,r.machineId.initializationVector,r.machineId.authTag)===this.ƀep())return s}static ƀdf(e,t){let a=p__default.default.randomBytes(12),i=p__default.default.createCipheriv("aes-256-gcm",t,a),r=Buffer.concat([i.update(e,"utf8"),i.final()]),s=i.getAuthTag();return {initializationVector:a,encrypted:r,authTag:s}}static ƀct(e,t,a,i){let r=p__default.default.createDecipheriv("aes-256-gcm",t,a);return r.setAuthTag(i),Buffer.concat([r.update(e),r.final()]).toString("utf8")}static ƀep(){return process.platform==="win32"?child_process.execSync("wmic csproduct get uuid /format:value",{encoding:"utf8"}).split("=")[1].trim():process.platform==="darwin"?child_process.execSync("ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformUUID/{print $3}'",{encoding:"utf8"}).trim().replace(/"/g,""):child_process.execSync("cat /sys/class/dmi/id/product_uuid",{encoding:"utf8"}).trim()}};var I=class{static{n(this,"ElectronApp");}static start(e){process.env.ELECTRON_DISABLE_SECURITY_WARNINGS="true",T__default.default&&electron.app.quit();let t=process.env.ENVIRONMENT==="dev",a=n(()=>{let i=new electron.BrowserWindow({width:e.defaultWindowSize.width,height:e.defaultWindowSize.height,webPreferences:{preload:w__default.default.join(__dirname,"preload.js")},backgroundColor:"#000",show:false,autoHideMenuBar:true});i.once("ready-to-show",()=>{i.show();}),i.setMenu(null),MAIN_WINDOW_VITE_DEV_SERVER_URL?i.loadURL(MAIN_WINDOW_VITE_DEV_SERVER_URL):i.loadFile(w__default.default.join(__dirname,`../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`)),this.ƀkm(i,e,t),e.onWindowCreated?.(i),t&&(i.setSize(1616,1616),i.setPosition(-7,0),i.webContents.openDevTools());},"createWindow");electron.app.on("ready",a),electron.app.on("window-all-closed",()=>{process.platform!=="darwin"&&electron.app.quit();}),electron.app.on("activate",()=>{electron.BrowserWindow.getAllWindows().length===0&&a();});}static ƀkm(e,t,a){electron.ipcMain.handle("save",async(i,r,s)=>{await c.save(r,s);}),electron.ipcMain.handle("load",async(i,r)=>c.load(r)),electron.ipcMain.handle("getOptions",async()=>({devMode:a,maxScreenResolution:t.maxWindowSize})),Object.entries(t.ipcHandlers??{}).forEach(([i,r])=>{electron.ipcMain.handle(i,(s,...u)=>r(...u));}),e.on("focus",()=>{e.webContents.send("onWindowFocus",true);}),e.on("blur",()=>{e.webContents.send("onWindowFocus",false);}),electron.ipcMain.on("rendererReady",()=>{e.webContents.send("onWindowFocus",e.isFocused());}),electron.ipcMain.on("setFullScreen",(i,r)=>{r?(e.setResizable(false),e.setMaximumSize(0,0),e.setFullScreen(true),e.setMovable(false),e.setMaximizable(false),e.setMinimizable(false),e.setMenuBarVisibility(false)):(e.setFullScreen(false),e.setResizable(true),a||(e.setMaximumSize(t.maxWindowSize.width,t.maxWindowSize.height),e.setMinimumSize(t.minWindowSize.width,t.minWindowSize.height),e.setSize(t.defaultWindowSize.width,t.defaultWindowSize.height),e.center()),e.setMovable(true),e.setMaximizable(true),e.setMinimizable(true),e.setMenuBarVisibility(true));}),electron.ipcMain.on("quit",()=>{electron.app.quit();});}};exports.ElectronApp=I;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {app,BrowserWindow,ipcMain}from'electron';import T from'electron-squirrel-startup';import w from'path';import {execSync}from'child_process';import p from'crypto';import y from'fs/promises';import V from'write-file-atomic';import {Queue}from'helpers-lib';var v=Object.defineProperty;var n=(d,e)=>v(d,"name",{value:e,configurable:true});var h=class{static{n(this,"SingleAsyncQueue");}constructor(){this.ƀkt=false,this.ƀjf=new Queue;}async enqueue(e){let t=this.ƀjf.empty,a=new Promise((i,r)=>this.ƀjf.add({operation:e,resolve:i,reject:r}));return t&&this.ƀjt(),a}ƀjt(){if(!this.ƀkt){let e=[];for(;this.ƀjf.notEmpty;){let t=this.ƀjf.pop();t&&e.push(t);}e.length>0&&this.ƀju(e);}}ƀju(e){let t=e.pop();if(!t)throw new Error("No executing entry found");this.ƀkt=true,t.operation().then(()=>{e.forEach(a=>a.resolve()),t.resolve(),this.ƀkt=false,this.ƀjt();}).catch(a=>{t.reject(a),e.length>0?this.ƀju(e):(this.ƀkt=false,this.ƀjt());});}};var g=w.join(app.getPath("userData"),"saves"),_=1,f=p.scryptSync("gdfgmhur%+/&ty@ertbdf423-secret","ga!sgnwq6^/&(roofvafnl_salt",32),c=class{static{n(this,"MainSaveLoad");}static{this.ƀdq=new Map;}static ƀev(e){let t=this.ƀdq.get(e);return t||(t=new h,this.ƀdq.set(e,t)),t}static async save(e,t){return this.ƀev(t).enqueue(()=>this.ƀlm(e,t))}static async load(e){return this.ƀjj(e)}static async ƀlm(e,t){let a=this.ƀep(),i=w.join(g,t);if(await y.mkdir(g,{recursive:true}),!e)await y.rm(i,{force:true});else {let r=this.ƀdf(e,f),s=this.ƀdf(a,f),u={version:_,data:{initializationVector:r.initializationVector,encrypted:r.encrypted,authTag:r.authTag},machineId:{initializationVector:s.initializationVector,encrypted:s.encrypted,authTag:s.authTag}};await V(i,JSON.stringify(u),{encoding:"utf-8"});}}static async ƀjj(e){let t=w.join(g,e),a;try{a=await y.readFile(t,"utf-8");}catch{return}let i=JSON.parse(a),r={version:i.version,data:{initializationVector:Buffer.from(i.data.initializationVector),encrypted:Buffer.from(i.data.encrypted),authTag:Buffer.from(i.data.authTag)},machineId:{initializationVector:Buffer.from(i.machineId.initializationVector),encrypted:Buffer.from(i.machineId.encrypted),authTag:Buffer.from(i.machineId.authTag)}},s=this.ƀct(r.data.encrypted,f,r.data.initializationVector,r.data.authTag);if(this.ƀct(r.machineId.encrypted,f,r.machineId.initializationVector,r.machineId.authTag)===this.ƀep())return s}static ƀdf(e,t){let a=p.randomBytes(12),i=p.createCipheriv("aes-256-gcm",t,a),r=Buffer.concat([i.update(e,"utf8"),i.final()]),s=i.getAuthTag();return {initializationVector:a,encrypted:r,authTag:s}}static ƀct(e,t,a,i){let r=p.createDecipheriv("aes-256-gcm",t,a);return r.setAuthTag(i),Buffer.concat([r.update(e),r.final()]).toString("utf8")}static ƀep(){return process.platform==="win32"?execSync("wmic csproduct get uuid /format:value",{encoding:"utf8"}).split("=")[1].trim():process.platform==="darwin"?execSync("ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformUUID/{print $3}'",{encoding:"utf8"}).trim().replace(/"/g,""):execSync("cat /sys/class/dmi/id/product_uuid",{encoding:"utf8"}).trim()}};var I=class{static{n(this,"ElectronApp");}static start(e){process.env.ELECTRON_DISABLE_SECURITY_WARNINGS="true",T&&app.quit();let t=process.env.ENVIRONMENT==="dev",a=n(()=>{let i=new BrowserWindow({width:e.defaultWindowSize.width,height:e.defaultWindowSize.height,webPreferences:{preload:w.join(__dirname,"preload.js")},backgroundColor:"#000",show:false,autoHideMenuBar:true});i.once("ready-to-show",()=>{i.show();}),i.setMenu(null),MAIN_WINDOW_VITE_DEV_SERVER_URL?i.loadURL(MAIN_WINDOW_VITE_DEV_SERVER_URL):i.loadFile(w.join(__dirname,`../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`)),this.ƀkm(i,e,t),e.onWindowCreated?.(i),t&&(i.setSize(1616,1616),i.setPosition(-7,0),i.webContents.openDevTools());},"createWindow");app.on("ready",a),app.on("window-all-closed",()=>{process.platform!=="darwin"&&app.quit();}),app.on("activate",()=>{BrowserWindow.getAllWindows().length===0&&a();});}static ƀkm(e,t,a){ipcMain.handle("save",async(i,r,s)=>{await c.save(r,s);}),ipcMain.handle("load",async(i,r)=>c.load(r)),ipcMain.handle("getOptions",async()=>({devMode:a,maxScreenResolution:t.maxWindowSize})),Object.entries(t.ipcHandlers??{}).forEach(([i,r])=>{ipcMain.handle(i,(s,...u)=>r(...u));}),e.on("focus",()=>{e.webContents.send("onWindowFocus",true);}),e.on("blur",()=>{e.webContents.send("onWindowFocus",false);}),ipcMain.on("rendererReady",()=>{e.webContents.send("onWindowFocus",e.isFocused());}),ipcMain.on("setFullScreen",(i,r)=>{r?(e.setResizable(false),e.setMaximumSize(0,0),e.setFullScreen(true),e.setMovable(false),e.setMaximizable(false),e.setMinimizable(false),e.setMenuBarVisibility(false)):(e.setFullScreen(false),e.setResizable(true),a||(e.setMaximumSize(t.maxWindowSize.width,t.maxWindowSize.height),e.setMinimumSize(t.minWindowSize.width,t.minWindowSize.height),e.setSize(t.defaultWindowSize.width,t.defaultWindowSize.height),e.center()),e.setMovable(true),e.setMaximizable(true),e.setMinimizable(true),e.setMenuBarVisibility(true));}),ipcMain.on("quit",()=>{app.quit();});}};export{I as ElectronApp};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface ElectronCustomChannels {
|
|
2
|
+
readonly invokes?: readonly string[];
|
|
3
|
+
readonly events?: readonly string[];
|
|
4
|
+
}
|
|
5
|
+
declare class ElectronPreload {
|
|
6
|
+
static expose(customChannels?: ElectronCustomChannels): void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export { type ElectronCustomChannels, ElectronPreload };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface ElectronCustomChannels {
|
|
2
|
+
readonly invokes?: readonly string[];
|
|
3
|
+
readonly events?: readonly string[];
|
|
4
|
+
}
|
|
5
|
+
declare class ElectronPreload {
|
|
6
|
+
static expose(customChannels?: ElectronCustomChannels): void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export { type ElectronCustomChannels, ElectronPreload };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var electron=require('electron');var p=Object.defineProperty;var n=(s,o)=>p(s,"name",{value:o,configurable:true});var u=class{static{n(this,"ElectronPreload");}static expose(o={}){let v=Object.fromEntries((o.invokes??[]).map(e=>[e,(...r)=>electron.ipcRenderer.invoke(e,...r)])),a=Object.fromEntries((o.events??[]).map(e=>[e,r=>{let i=n((d,c)=>r(c),"handler");return electron.ipcRenderer.on(e,i),()=>{electron.ipcRenderer.removeListener(e,i);}}]));electron.contextBridge.exposeInMainWorld("api",{...v,...a,save:n(async function(e,r){return electron.ipcRenderer.invoke("save",e,r)},"save"),load:n(async function(e){return electron.ipcRenderer.invoke("load",e)},"load"),getOptions:n(async function(){return electron.ipcRenderer.invoke("getOptions")},"getOptions"),setFullScreen:n(e=>electron.ipcRenderer.send("setFullScreen",e),"setFullScreen"),rendererReady:n(()=>electron.ipcRenderer.send("rendererReady"),"rendererReady"),onWindowFocus:n(e=>{let r=n((i,d)=>e(d),"handler");return electron.ipcRenderer.on("onWindowFocus",r),()=>{electron.ipcRenderer.removeListener("onWindowFocus",r);}},"onWindowFocus"),quit:n(()=>electron.ipcRenderer.send("quit"),"quit")});}};exports.ElectronPreload=u;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {ipcRenderer,contextBridge}from'electron';var p=Object.defineProperty;var n=(s,o)=>p(s,"name",{value:o,configurable:true});var u=class{static{n(this,"ElectronPreload");}static expose(o={}){let v=Object.fromEntries((o.invokes??[]).map(e=>[e,(...r)=>ipcRenderer.invoke(e,...r)])),a=Object.fromEntries((o.events??[]).map(e=>[e,r=>{let i=n((d,c)=>r(c),"handler");return ipcRenderer.on(e,i),()=>{ipcRenderer.removeListener(e,i);}}]));contextBridge.exposeInMainWorld("api",{...v,...a,save:n(async function(e,r){return ipcRenderer.invoke("save",e,r)},"save"),load:n(async function(e){return ipcRenderer.invoke("load",e)},"load"),getOptions:n(async function(){return ipcRenderer.invoke("getOptions")},"getOptions"),setFullScreen:n(e=>ipcRenderer.send("setFullScreen",e),"setFullScreen"),rendererReady:n(()=>ipcRenderer.send("rendererReady"),"rendererReady"),onWindowFocus:n(e=>{let r=n((i,d)=>e(d),"handler");return ipcRenderer.on("onWindowFocus",r),()=>{ipcRenderer.removeListener("onWindowFocus",r);}},"onWindowFocus"),quit:n(()=>ipcRenderer.send("quit"),"quit")});}};export{u as ElectronPreload};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import * as actions_lib from 'actions-lib';
|
|
2
|
-
import { IDAttachable, AttachmentID, Attachable,
|
|
2
|
+
import { IdleSingleEvent, IDAttachable, AttachmentID, Attachable, IdleSequence, Variable, Reducer, Sequence, SingleNotifier, Notifier, SingleEvent, Action, ClassID, NotifierCallbackFunction, IAttachment } from 'actions-lib';
|
|
3
3
|
import { Vector, DynamicID, Vec2, RGBColor, Radian, Rectangle, Grid, GridNeighborType, Line } from 'helpers-lib';
|
|
4
|
-
import p2$1 from 'p2';
|
|
5
4
|
import * as Pixi from 'pixi.js';
|
|
5
|
+
import p2$1 from 'p2';
|
|
6
|
+
import { LayoutStyles } from '@pixi/layout';
|
|
7
|
+
|
|
8
|
+
type AudioAppearTransitionType = 'ease' | 'instant';
|
|
9
|
+
declare const SOUND_TRANSITION_DURATION = 1000;
|
|
10
|
+
declare class Audio {
|
|
11
|
+
private constructor();
|
|
12
|
+
setVolumes(volumes: {
|
|
13
|
+
master: number;
|
|
14
|
+
music: number;
|
|
15
|
+
sound: number;
|
|
16
|
+
}): void;
|
|
17
|
+
appear(on: boolean, type?: AudioAppearTransitionType): IdleSingleEvent;
|
|
18
|
+
}
|
|
6
19
|
|
|
7
20
|
/**
|
|
8
21
|
* Binds a controller to its gateway (the class produced by `Gateway<T>()`). The controller must
|
|
@@ -158,18 +171,6 @@ declare abstract class View extends IDAttachable {
|
|
|
158
171
|
update: (time: number, delta: number) => void;
|
|
159
172
|
}
|
|
160
173
|
|
|
161
|
-
type AudioAppearTransitionType = 'ease' | 'instant';
|
|
162
|
-
declare const SOUND_TRANSITION_DURATION = 1000;
|
|
163
|
-
declare class Audio {
|
|
164
|
-
private constructor();
|
|
165
|
-
setVolumes(volumes: {
|
|
166
|
-
master: number;
|
|
167
|
-
music: number;
|
|
168
|
-
sound: number;
|
|
169
|
-
}): void;
|
|
170
|
-
appear(on: boolean, type?: AudioAppearTransitionType): IdleSingleEvent;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
174
|
interface FocusingNewTargetInfo {
|
|
174
175
|
time: number;
|
|
175
176
|
duration: number;
|
|
@@ -322,9 +323,14 @@ declare class Game {
|
|
|
322
323
|
readonly devMode: boolean;
|
|
323
324
|
constructor(partialConfiguration?: Partial<GameConfiguration>);
|
|
324
325
|
setup(setupOptions: GameSetupOptions): Promise<void>;
|
|
326
|
+
generateTexture(options: Pixi.GenerateTextureOptions | Pixi.Container): Pixi.Texture;
|
|
325
327
|
setResolution(resolution: number): void;
|
|
326
328
|
}
|
|
327
329
|
|
|
330
|
+
declare class ElectronGame {
|
|
331
|
+
static start(configuration: Partial<Omit<GameConfiguration, 'devMode' | 'maxScreenResolution'>>, setupOptions: GameSetupOptions): Promise<Game>;
|
|
332
|
+
}
|
|
333
|
+
|
|
328
334
|
interface SoundOptions {
|
|
329
335
|
readonly time?: number;
|
|
330
336
|
readonly volume?: number;
|
|
@@ -407,40 +413,17 @@ declare class MusicPlayer extends IDAttachable {
|
|
|
407
413
|
close(): IdleSingleEvent;
|
|
408
414
|
}
|
|
409
415
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
PointerUp = "pointerup",
|
|
416
|
-
PointerUpOutside = "pointerupoutside",
|
|
417
|
-
PointerMove = "pointermove",
|
|
418
|
-
PointerCancel = "pointercancel",
|
|
419
|
-
PointerOver = "pointerover",
|
|
420
|
-
PointerOut = "pointerout",
|
|
421
|
-
PointerEnter = "pointerenter",
|
|
422
|
-
PointerLeave = "pointerleave",
|
|
423
|
-
Added = "added",
|
|
424
|
-
Removed = "removed",
|
|
425
|
-
Update = "update",
|
|
426
|
-
Change = "change",
|
|
427
|
-
Wheel = "wheel"
|
|
416
|
+
interface PixiDisplayObject {
|
|
417
|
+
x: number;
|
|
418
|
+
y: number;
|
|
419
|
+
rotation: number;
|
|
420
|
+
alpha: number;
|
|
428
421
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
declare enum Cursor {
|
|
435
|
-
Default = "default",
|
|
436
|
-
Pointer = "pointer"
|
|
437
|
-
}
|
|
438
|
-
declare abstract class ContainerAttributes extends IDAttachable {
|
|
439
|
-
protected constructor();
|
|
440
|
-
get size(): Vector;
|
|
441
|
-
set size(value: Vector);
|
|
442
|
-
getSize(): Vector;
|
|
443
|
-
setSize(value: Vector): this;
|
|
422
|
+
declare abstract class DisplayObjectAttributes extends IDAttachable {
|
|
423
|
+
protected readonly _pixiDisplayObject: PixiDisplayObject;
|
|
424
|
+
protected constructor(_pixiDisplayObject: PixiDisplayObject);
|
|
425
|
+
protected abstract _applyScale(x: number, y: number): void;
|
|
426
|
+
protected abstract _getHoldFromModifier(holdFrom: Vector): Vector;
|
|
444
427
|
/**
|
|
445
428
|
* @param value The position to set
|
|
446
429
|
* @param options.holdFrom An anchor point to hold the position from
|
|
@@ -457,7 +440,6 @@ declare abstract class ContainerAttributes extends IDAttachable {
|
|
|
457
440
|
set x(value: number);
|
|
458
441
|
get y(): number;
|
|
459
442
|
set y(value: number);
|
|
460
|
-
on<T extends ContainerEventType>(eventType: T): Sequence<ContainerEventTypeToResultType[T]>;
|
|
461
443
|
setRotation(value: Radian): this;
|
|
462
444
|
get rotation(): Radian;
|
|
463
445
|
set rotation(value: Radian);
|
|
@@ -466,38 +448,9 @@ declare abstract class ContainerAttributes extends IDAttachable {
|
|
|
466
448
|
*/
|
|
467
449
|
get rotationValue(): number;
|
|
468
450
|
set rotationValue(value: number);
|
|
469
|
-
setZIndex(value: number): this;
|
|
470
|
-
get zIndex(): number;
|
|
471
|
-
set zIndex(value: number);
|
|
472
|
-
setSkewX(radian: Radian): this;
|
|
473
|
-
get skewX(): Radian;
|
|
474
|
-
set skewX(radian: Radian);
|
|
475
|
-
setSkewY(radian: Radian): this;
|
|
476
|
-
get skewY(): Radian;
|
|
477
|
-
set skewY(radian: Radian);
|
|
478
|
-
setSortableChildren(value: boolean): this;
|
|
479
|
-
get sortableChildren(): boolean;
|
|
480
|
-
set sortableChildren(value: boolean);
|
|
481
451
|
setAlpha(value: number): this;
|
|
482
452
|
get alpha(): number;
|
|
483
453
|
set alpha(value: number);
|
|
484
|
-
setInteractive(value: boolean): this;
|
|
485
|
-
get interactive(): boolean;
|
|
486
|
-
set interactive(value: boolean);
|
|
487
|
-
/**
|
|
488
|
-
* Renders this subtree as an isolated render group: its cached render instructions are not
|
|
489
|
-
* rebuilt when other parts of the scene change, and moving the group only updates one transform.
|
|
490
|
-
* Use for subtrees that move as a whole (world under a camera) or rarely change (HUD vs world).
|
|
491
|
-
*/
|
|
492
|
-
setRenderGroup(value?: boolean): this;
|
|
493
|
-
setCursor(value: Cursor): this;
|
|
494
|
-
get cursor(): Cursor;
|
|
495
|
-
set cursor(value: Cursor);
|
|
496
|
-
protected getMask(): Pixi.Container;
|
|
497
|
-
setMask(mask: ContainerAttributes | undefined): this;
|
|
498
|
-
hitTest(stagePosition: Vector): boolean;
|
|
499
|
-
get boundingBox(): Rectangle;
|
|
500
|
-
ignoreBounds(value?: boolean): this;
|
|
501
454
|
setMirror(mirror?: boolean): this;
|
|
502
455
|
get mirror(): boolean;
|
|
503
456
|
set mirror(value: boolean);
|
|
@@ -572,11 +525,40 @@ declare class Sprite extends Container {
|
|
|
572
525
|
download(): this;
|
|
573
526
|
}
|
|
574
527
|
|
|
528
|
+
type LayoutStyle = LayoutStyles;
|
|
529
|
+
declare enum ContainerEventType {
|
|
530
|
+
Click = "click",
|
|
531
|
+
MouseOver = "mouseover",
|
|
532
|
+
MouseOut = "mouseout",
|
|
533
|
+
PointerDown = "pointerdown",
|
|
534
|
+
PointerUp = "pointerup",
|
|
535
|
+
PointerUpOutside = "pointerupoutside",
|
|
536
|
+
PointerMove = "pointermove",
|
|
537
|
+
PointerCancel = "pointercancel",
|
|
538
|
+
PointerOver = "pointerover",
|
|
539
|
+
PointerOut = "pointerout",
|
|
540
|
+
PointerEnter = "pointerenter",
|
|
541
|
+
PointerLeave = "pointerleave",
|
|
542
|
+
Added = "added",
|
|
543
|
+
Removed = "removed",
|
|
544
|
+
Update = "update",
|
|
545
|
+
Change = "change",
|
|
546
|
+
Wheel = "wheel"
|
|
547
|
+
}
|
|
548
|
+
type ContainerEventTypeToResultType = {
|
|
549
|
+
[K in ContainerEventType]: K extends ContainerEventType.Wheel ? {
|
|
550
|
+
deltaY: number;
|
|
551
|
+
} : undefined;
|
|
552
|
+
};
|
|
553
|
+
declare enum Cursor {
|
|
554
|
+
Default = "default",
|
|
555
|
+
Pointer = "pointer"
|
|
556
|
+
}
|
|
575
557
|
interface SetParentOptions {
|
|
576
558
|
addUnder: boolean;
|
|
577
559
|
cropOverflowingParts: boolean;
|
|
578
560
|
}
|
|
579
|
-
declare class Container extends
|
|
561
|
+
declare class Container extends DisplayObjectAttributes {
|
|
580
562
|
protected static allContainers: Map<number, Container>;
|
|
581
563
|
readonly filters: Filters;
|
|
582
564
|
protected addChildTo: Container;
|
|
@@ -584,8 +566,50 @@ declare class Container extends ContainerAttributes {
|
|
|
584
566
|
addUnder: boolean;
|
|
585
567
|
cropOverflowingParts: boolean;
|
|
586
568
|
};
|
|
587
|
-
constructor();
|
|
569
|
+
constructor(pixiContainer?: Pixi.Container);
|
|
588
570
|
destroy(): void;
|
|
571
|
+
protected _applyScale(x: number, y: number): void;
|
|
572
|
+
protected _getHoldFromModifier(holdFrom: Vector): Vector;
|
|
573
|
+
get size(): Vector;
|
|
574
|
+
set size(value: Vector);
|
|
575
|
+
getSize(): Vector;
|
|
576
|
+
setSize(value: Vector): this;
|
|
577
|
+
/**
|
|
578
|
+
* Makes this object a flex item of a LayoutContainer parent, treated as a box measured by its bounds.
|
|
579
|
+
* @param style Optional per-item overrides (alignSelf, margins, width, height...)
|
|
580
|
+
* @returns this
|
|
581
|
+
*/
|
|
582
|
+
setLayout(style?: LayoutStyle): this;
|
|
583
|
+
on<T extends ContainerEventType>(eventType: T): Sequence<ContainerEventTypeToResultType[T]>;
|
|
584
|
+
setZIndex(value: number): this;
|
|
585
|
+
get zIndex(): number;
|
|
586
|
+
set zIndex(value: number);
|
|
587
|
+
setSkewX(radian: Radian): this;
|
|
588
|
+
get skewX(): Radian;
|
|
589
|
+
set skewX(radian: Radian);
|
|
590
|
+
setSkewY(radian: Radian): this;
|
|
591
|
+
get skewY(): Radian;
|
|
592
|
+
set skewY(radian: Radian);
|
|
593
|
+
setSortableChildren(value: boolean): this;
|
|
594
|
+
get sortableChildren(): boolean;
|
|
595
|
+
set sortableChildren(value: boolean);
|
|
596
|
+
setInteractive(value: boolean): this;
|
|
597
|
+
get interactive(): boolean;
|
|
598
|
+
set interactive(value: boolean);
|
|
599
|
+
/**
|
|
600
|
+
* Renders this subtree as an isolated render group: its cached render instructions are not
|
|
601
|
+
* rebuilt when other parts of the scene change, and moving the group only updates one transform.
|
|
602
|
+
* Use for subtrees that move as a whole (world under a camera) or rarely change (HUD vs world).
|
|
603
|
+
*/
|
|
604
|
+
setRenderGroup(value?: boolean): this;
|
|
605
|
+
setCursor(value: Cursor): this;
|
|
606
|
+
get cursor(): Cursor;
|
|
607
|
+
set cursor(value: Cursor);
|
|
608
|
+
protected getMask(): Pixi.Container;
|
|
609
|
+
setMask(mask: Container | undefined): this;
|
|
610
|
+
hitTest(stagePosition: Vector): boolean;
|
|
611
|
+
get boundingBox(): Rectangle;
|
|
612
|
+
ignoreBounds(value?: boolean): this;
|
|
589
613
|
getBoundingMask(): Sprite;
|
|
590
614
|
displayParent(parent: Container | number, partialOptions?: Partial<SetParentOptions>): this;
|
|
591
615
|
}
|
|
@@ -982,6 +1006,16 @@ declare class ScrollMaskUI extends Container {
|
|
|
982
1006
|
constructor(container: Container, size: Vector, padding: number, direction?: ScrollDirection);
|
|
983
1007
|
}
|
|
984
1008
|
|
|
1009
|
+
/**
|
|
1010
|
+
* A flexbox container.
|
|
1011
|
+
*/
|
|
1012
|
+
declare class LayoutContainer extends Container {
|
|
1013
|
+
constructor(style?: LayoutStyle);
|
|
1014
|
+
setLayout(style: LayoutStyle): this;
|
|
1015
|
+
debug(): this;
|
|
1016
|
+
debugBackground(): this;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
985
1019
|
interface KeyboardKeyInfo {
|
|
986
1020
|
readonly key: string;
|
|
987
1021
|
readonly code: string;
|
|
@@ -1342,4 +1376,26 @@ declare abstract class MovablePhysicsEntity extends PhysicsEntity {
|
|
|
1342
1376
|
convertToDTO(): PhysicsBodyDTO;
|
|
1343
1377
|
}
|
|
1344
1378
|
|
|
1345
|
-
|
|
1379
|
+
interface ElectronAppOptions {
|
|
1380
|
+
readonly devMode: boolean;
|
|
1381
|
+
readonly maxScreenResolution: {
|
|
1382
|
+
readonly width: number;
|
|
1383
|
+
readonly height: number;
|
|
1384
|
+
} | undefined;
|
|
1385
|
+
}
|
|
1386
|
+
interface ElectronBridge {
|
|
1387
|
+
save(data: string | undefined, fileName: string): Promise<void>;
|
|
1388
|
+
load(fileName: string): Promise<string | undefined>;
|
|
1389
|
+
getOptions(): Promise<ElectronAppOptions>;
|
|
1390
|
+
setFullScreen(fullScreen: boolean): void;
|
|
1391
|
+
rendererReady(): void;
|
|
1392
|
+
onWindowFocus(callback: (focused: boolean) => void): () => void;
|
|
1393
|
+
quit(): void;
|
|
1394
|
+
}
|
|
1395
|
+
declare global {
|
|
1396
|
+
interface Window {
|
|
1397
|
+
api: ElectronBridge;
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
export { AdvancedSound, type AdvancedSoundOptions, AnimationFlicker, AnimationInterpolationFunctions, type AnimationOptions, Animations, AnimationsCompletionHandlingType, Animator, type AnimatorAnimation, type AssetDefinition, type AudioAppearTransitionType, BORDER_MATERIAL_NAME, BardLegendsTestingHelper, type BlendMode, type BorderProperties, Camera, CameraGateway, type CircleShapeData, ClosestAvailableSpaceHelper, type CollisionDetails, type CollisionReport, Container, ContainerEventType, ControllerDecorator, type CreateDashedLineOptions, type CreatePhysicsWorldRequestDTO, Cursor, DEFAULT_SHADER_RESOLUTION, DeltaTime, DisplayObjectArray, type DisplayObjectArrayOptions, type DropShadowOptions, type ElectronAppOptions, type ElectronBridge, ElectronGame, Entity, EntityDecorator, type EntityID, type ExplosionHit, FadeInContent, type FadeInContentOptions, FocusingAnimation, Game, Gateway, type GlowEffectOptions, type GlowOptions, type GlowingShapeDefinition, Graphics, type HitTestOptions, ImmovablePhysicsEntity, type InteractingBodyGroups, type KeyboardKeyInfo, KeyboardService, LayoutContainer, type LayoutStyle, type MapSizeDTO, type MaterialContactDefinition, type MaterialDefinition, MenuEntity, type MenuOptions, MenuUI, MenuView, MouseService, MouseTargetFocusService, MovableEntity, MovablePhysicsEntity, Music, MusicPlayer, type MusicPlayerOptions, type PartialTextOptions, PathFinder, type PathFinderResult, type PhysicsBodyDTO, PhysicsEntity, type PhysicsEntityDefinition, type PhysicsExplosionOptions, PhysicsGateway, PhysicsShapeType, type PhysicsWorldID, Placeholder, type PolygonDefinition, type PolygonShapeData, ROTATIONAL_SPEED_LIMIT, type RayCast, type RayCastHit, ReAnimateHandlingType, type RectangleShapeData, RichText, type RichTextOptions, type RichTextRectangleCut, type RichTextStyles, SOUND_TRANSITION_DURATION, SPEED_LIMIT, Scene, SceneDecorator, ScrollAreaUI, ScrollDirection, type ScrollInContentOptions, ScrollMaskUI, Service, ServiceDecorator, type SetParentOptions, type ShapeDefinition, SingletonEntity, SlideInContent, SlideInContentByIndex, SlideStateAnimation, SlideStateAnimationState, Sound, type SoundDefinition, type SoundID, type SoundIDRegistry, type SoundOptions, Sprite, type SpriteDefinition, type SpriteID, type SpriteIDRegistry, StateAnimation, type StateAnimationOptions, type StateAnimationState, Text, type TextAlignment, type TextOptions, ThroughEmptyStateAnimation, UpdatableContainer, UpdateCycle, VectorFieldPathFinder, VectorSet, View, ViewDecorator, type ViewDecoratorMeta };
|