bard-legends-framework 1.11.5 → 1.12.1
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 +41 -15
- package/dist/index.d.ts +41 -15
- package/dist/index.js +3 -3
- package/dist/index.mjs +3 -3
- package/electron-forge.mjs +37 -0
- package/package.json +51 -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,10 +1,22 @@
|
|
|
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
6
|
import { LayoutStyles } from '@pixi/layout';
|
|
7
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
|
+
}
|
|
19
|
+
|
|
8
20
|
/**
|
|
9
21
|
* Binds a controller to its gateway (the class produced by `Gateway<T>()`). The controller must
|
|
10
22
|
* structurally match the gateway's controller type, so wiring the wrong controller to a gateway is
|
|
@@ -159,18 +171,6 @@ declare abstract class View extends IDAttachable {
|
|
|
159
171
|
update: (time: number, delta: number) => void;
|
|
160
172
|
}
|
|
161
173
|
|
|
162
|
-
type AudioAppearTransitionType = 'ease' | 'instant';
|
|
163
|
-
declare const SOUND_TRANSITION_DURATION = 1000;
|
|
164
|
-
declare class Audio {
|
|
165
|
-
private constructor();
|
|
166
|
-
setVolumes(volumes: {
|
|
167
|
-
master: number;
|
|
168
|
-
music: number;
|
|
169
|
-
sound: number;
|
|
170
|
-
}): void;
|
|
171
|
-
appear(on: boolean, type?: AudioAppearTransitionType): IdleSingleEvent;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
174
|
interface FocusingNewTargetInfo {
|
|
175
175
|
time: number;
|
|
176
176
|
duration: number;
|
|
@@ -327,6 +327,10 @@ declare class Game {
|
|
|
327
327
|
setResolution(resolution: number): void;
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
+
declare class ElectronGame {
|
|
331
|
+
static start(configuration: Partial<Omit<GameConfiguration, 'devMode' | 'maxScreenResolution'>>, setupOptions: GameSetupOptions): Promise<Game>;
|
|
332
|
+
}
|
|
333
|
+
|
|
330
334
|
interface SoundOptions {
|
|
331
335
|
readonly time?: number;
|
|
332
336
|
readonly volume?: number;
|
|
@@ -1372,4 +1376,26 @@ declare abstract class MovablePhysicsEntity extends PhysicsEntity {
|
|
|
1372
1376
|
convertToDTO(): PhysicsBodyDTO;
|
|
1373
1377
|
}
|
|
1374
1378
|
|
|
1375
|
-
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
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
6
|
import { LayoutStyles } from '@pixi/layout';
|
|
7
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
|
+
}
|
|
19
|
+
|
|
8
20
|
/**
|
|
9
21
|
* Binds a controller to its gateway (the class produced by `Gateway<T>()`). The controller must
|
|
10
22
|
* structurally match the gateway's controller type, so wiring the wrong controller to a gateway is
|
|
@@ -159,18 +171,6 @@ declare abstract class View extends IDAttachable {
|
|
|
159
171
|
update: (time: number, delta: number) => void;
|
|
160
172
|
}
|
|
161
173
|
|
|
162
|
-
type AudioAppearTransitionType = 'ease' | 'instant';
|
|
163
|
-
declare const SOUND_TRANSITION_DURATION = 1000;
|
|
164
|
-
declare class Audio {
|
|
165
|
-
private constructor();
|
|
166
|
-
setVolumes(volumes: {
|
|
167
|
-
master: number;
|
|
168
|
-
music: number;
|
|
169
|
-
sound: number;
|
|
170
|
-
}): void;
|
|
171
|
-
appear(on: boolean, type?: AudioAppearTransitionType): IdleSingleEvent;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
174
|
interface FocusingNewTargetInfo {
|
|
175
175
|
time: number;
|
|
176
176
|
duration: number;
|
|
@@ -327,6 +327,10 @@ declare class Game {
|
|
|
327
327
|
setResolution(resolution: number): void;
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
+
declare class ElectronGame {
|
|
331
|
+
static start(configuration: Partial<Omit<GameConfiguration, 'devMode' | 'maxScreenResolution'>>, setupOptions: GameSetupOptions): Promise<Game>;
|
|
332
|
+
}
|
|
333
|
+
|
|
330
334
|
interface SoundOptions {
|
|
331
335
|
readonly time?: number;
|
|
332
336
|
readonly volume?: number;
|
|
@@ -1372,4 +1376,26 @@ declare abstract class MovablePhysicsEntity extends PhysicsEntity {
|
|
|
1372
1376
|
convertToDTO(): PhysicsBodyDTO;
|
|
1373
1377
|
}
|
|
1374
1378
|
|
|
1375
|
-
|
|
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 };
|