@next2d/builder 0.1.11 → 0.3.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 +90 -57
- package/dist/cli.d.ts +7 -0
- package/dist/cli.js +68 -3
- package/dist/colors.d.ts +6 -0
- package/dist/colors.js +7 -0
- package/dist/context.d.ts +10 -1
- package/dist/context.js +7 -0
- package/dist/description.d.ts +2 -0
- package/dist/description.js +8 -0
- package/dist/electron-config.d.ts +62 -0
- package/dist/electron-config.js +134 -0
- package/dist/electron-host.d.ts +7 -0
- package/dist/electron-host.js +54 -0
- package/dist/electron-native.d.ts +15 -0
- package/dist/electron-native.js +73 -0
- package/dist/electron.d.ts +4 -9
- package/dist/electron.js +85 -133
- package/dist/index.js +21 -0
- package/dist/native.d.ts +9 -24
- package/dist/native.js +48 -106
- package/dist/project-vite.d.ts +3 -0
- package/dist/project-vite.js +21 -0
- package/dist/resolve-tool-packages.d.ts +1 -0
- package/dist/resolve-tool-packages.js +29 -0
- package/dist/steam-upload.d.ts +27 -0
- package/dist/steam-upload.js +131 -0
- package/dist/steam.d.ts +22 -0
- package/dist/steam.js +193 -0
- package/dist/tool-packages.d.ts +15 -0
- package/dist/tool-packages.js +74 -0
- package/dist/web.js +10 -4
- package/dist/xbox.d.ts +1 -1
- package/dist/xbox.js +60 -57
- package/docs/capacitor.md +201 -0
- package/docs/native-bridge.md +147 -0
- package/docs/steam.md +384 -0
- package/docs/xbox.md +145 -0
- package/package.json +9 -12
- package/templates/electron/entitlements.plist +12 -0
- package/templates/electron/icons/icon.icns +0 -0
- package/templates/electron/icons/icon.ico +0 -0
- package/templates/electron/icons/icon.png +0 -0
- package/templates/electron/index.js +119 -0
- package/templates/electron/local-assets.cjs +24 -0
- package/templates/electron/native-bridge.cjs +98 -0
- package/templates/electron/package.json +11 -0
- package/templates/electron/preload.cjs +11 -0
- package/templates/xbox/src/platform/StbTextRasterizer.cpp +14 -10
- package/templates/xbox/tests/check_local.sh +12 -4
- package/templates/xbox/tests/stb_safety_test.cpp +126 -0
- package/templates/xbox/third_party/LICENSES.md +15 -0
- package/templates/xbox/third_party/stb_image.h +15 -10
- package/templates/xbox/third_party/stb_truetype.h +4 -4
- package/templates/xbox/third_party/stb_vorbis.c +1 -1
package/dist/xbox.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// Xbox (GDK ネイティブ) ビルド。V8 に Next2D の JS を載せ、Dawn(WebGPU/D3D12)で
|
|
2
2
|
// 描画する C++ ホストを、テンプレートのスキャフォールド → 資材配置 → pak 埋め込み →
|
|
3
3
|
// CMake/GDK ビルドの順で書き出す。
|
|
4
|
-
import pc from "
|
|
4
|
+
import pc from "./colors.js";
|
|
5
5
|
import fs from "fs";
|
|
6
6
|
import os from "os";
|
|
7
7
|
import path from "path";
|
|
8
8
|
import cp from "child_process";
|
|
9
|
-
import {
|
|
9
|
+
import { loadProjectVite } from "./project-vite.js";
|
|
10
10
|
import { ctx } from "./context.js";
|
|
11
11
|
import { getTemplateDir } from "./utils.js";
|
|
12
12
|
import { XBOX_DIR_NAME, XBOX_CONFIG_NAME, XBOX_V8_VERSION, XBOX_V8_REVISION, XBOX_SCAFFOLD_EXCLUDES } from "./constants.js";
|
|
@@ -184,9 +184,15 @@ export const renderAssetsRc = (pakAbsPath) => {
|
|
|
184
184
|
* @method
|
|
185
185
|
* @public
|
|
186
186
|
*/
|
|
187
|
-
export const minifyJs = (name, code) => {
|
|
187
|
+
export const minifyJs = async (name, code) => {
|
|
188
188
|
try {
|
|
189
|
-
const
|
|
189
|
+
const vite = await loadProjectVite();
|
|
190
|
+
if (typeof vite.minifySync !== "function") {
|
|
191
|
+
// Vite 7 exposes esbuild rather than the Oxc minifier used by Vite 8.
|
|
192
|
+
const result = await vite.transformWithEsbuild(code, name, { "minify": true, "legalComments": "none" });
|
|
193
|
+
return result.code;
|
|
194
|
+
}
|
|
195
|
+
const result = vite.minifySync(name, code);
|
|
190
196
|
if (result.errors && result.errors.length > 0) {
|
|
191
197
|
const msg = result.errors[0]?.message ?? String(result.errors[0]);
|
|
192
198
|
console.log(pc.yellow(`Xbox: minify skipped for ${name} (${msg}); embedding as-is.`));
|
|
@@ -215,62 +221,59 @@ export const minifyJs = (name, code) => {
|
|
|
215
221
|
* @method
|
|
216
222
|
* @private
|
|
217
223
|
*/
|
|
218
|
-
const embedXboxAssets = () => {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
++minified;
|
|
248
|
-
}
|
|
249
|
-
return [key, Buffer.from(out, "utf8")];
|
|
224
|
+
const embedXboxAssets = async () => {
|
|
225
|
+
const xboxDir = `${process.cwd()}/${XBOX_DIR_NAME}`;
|
|
226
|
+
const pakPath = `${xboxDir}/assets.pak`;
|
|
227
|
+
const rcPath = `${xboxDir}/assets.rc`;
|
|
228
|
+
try {
|
|
229
|
+
// 収集: assets/app 一式 (キーは app 基準) + host スクリプト (js/ 基準)。
|
|
230
|
+
const entries = [];
|
|
231
|
+
entries.push(...walkFiles(`${xboxDir}/assets/app`, ""));
|
|
232
|
+
const bootstrap = `${xboxDir}/js/bootstrap.js`;
|
|
233
|
+
if (fs.existsSync(bootstrap)) {
|
|
234
|
+
entries.push(["js/bootstrap.js", bootstrap]);
|
|
235
|
+
}
|
|
236
|
+
const selftest = `${xboxDir}/js/selftest.js`;
|
|
237
|
+
if (fs.existsSync(selftest)) {
|
|
238
|
+
entries.push(["js/selftest.js", selftest]);
|
|
239
|
+
}
|
|
240
|
+
if (entries.length === 0) {
|
|
241
|
+
throw new Error("No Xbox assets found to embed (assets/app is empty).");
|
|
242
|
+
}
|
|
243
|
+
// (key, データ) を読み込み、pak バイナリへ直列化する。
|
|
244
|
+
// js/ のホストスクリプト(bootstrap.js/selftest.js)は minify + 難読化する。
|
|
245
|
+
// assets/app の JS は vite が本番ビルドで minify 済みのためそのまま。
|
|
246
|
+
let minified = 0;
|
|
247
|
+
const pakEntries = await Promise.all(entries.map(async ([key, abs]) => {
|
|
248
|
+
if (key.startsWith("js/") && key.endsWith(".js")) {
|
|
249
|
+
const src = fs.readFileSync(abs, { "encoding": "utf8" });
|
|
250
|
+
const out = await minifyJs(key, src);
|
|
251
|
+
if (out.length < src.length) {
|
|
252
|
+
++minified;
|
|
250
253
|
}
|
|
251
|
-
return [key,
|
|
252
|
-
});
|
|
253
|
-
const pak = buildPak(pakEntries);
|
|
254
|
-
if (minified > 0) {
|
|
255
|
-
console.log(pc.green(`Minified ${minified} host script(s) before embedding.`));
|
|
254
|
+
return [key, Buffer.from(out, "utf8")];
|
|
256
255
|
}
|
|
257
|
-
fs.
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
// 埋め込み済みの平文 `assets/`・`js/` は書き出し一覧から除外する。
|
|
263
|
-
// これらは assets.pak (=exe 内 RCDATA) に格納済みで、CMake も埋め込みモードでは
|
|
264
|
-
// exe 隣へステージしないため、xbox/ 直下に残しても不要かつ平文流出になる。
|
|
265
|
-
fs.rmSync(`${xboxDir}/assets`, { "recursive": true, "force": true });
|
|
266
|
-
fs.rmSync(`${xboxDir}/js`, { "recursive": true, "force": true });
|
|
267
|
-
console.log(pc.green("Excluded plaintext `assets/` and `js/` from the export (embedded in exe)."));
|
|
268
|
-
resolve();
|
|
269
|
-
}
|
|
270
|
-
catch (error) {
|
|
271
|
-
reject(`Failed to embed Xbox assets. ${error}`);
|
|
256
|
+
return [key, fs.readFileSync(abs)];
|
|
257
|
+
}));
|
|
258
|
+
const pak = buildPak(pakEntries);
|
|
259
|
+
if (minified > 0) {
|
|
260
|
+
console.log(pc.green(`Minified ${minified} host script(s) before embedding.`));
|
|
272
261
|
}
|
|
273
|
-
|
|
262
|
+
fs.writeFileSync(pakPath, pak);
|
|
263
|
+
// rc.exe が assets.pak を RCDATA "N2DASSETS" として取り込む .rc を生成する。
|
|
264
|
+
fs.writeFileSync(rcPath, renderAssetsRc(path.resolve(pakPath)), "utf8");
|
|
265
|
+
console.log(pc.green(`Embedded ${entries.length} Xbox asset file(s) into assets.pak `
|
|
266
|
+
+ `(${(pak.length / 1024 / 1024).toFixed(2)} MB).`));
|
|
267
|
+
// 埋め込み済みの平文 `assets/`・`js/` は書き出し一覧から除外する。
|
|
268
|
+
// これらは assets.pak (=exe 内 RCDATA) に格納済みで、CMake も埋め込みモードでは
|
|
269
|
+
// exe 隣へステージしないため、xbox/ 直下に残しても不要かつ平文流出になる。
|
|
270
|
+
fs.rmSync(`${xboxDir}/assets`, { "recursive": true, "force": true });
|
|
271
|
+
fs.rmSync(`${xboxDir}/js`, { "recursive": true, "force": true });
|
|
272
|
+
console.log(pc.green("Excluded plaintext `assets/` and `js/` from the export (embedded in exe)."));
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
throw new Error(`Failed to embed Xbox assets. ${error}`);
|
|
276
|
+
}
|
|
274
277
|
};
|
|
275
278
|
/**
|
|
276
279
|
* @description Xbox ビルドに使う V8 のパスを解決する。優先順:
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# iOS / Android(Capacitor)
|
|
2
|
+
|
|
3
|
+
[日本語](#日本語) | [English](#english)
|
|
4
|
+
|
|
5
|
+
## 日本語
|
|
6
|
+
|
|
7
|
+
### STEP1:対象OSのIDE・SDKを用意する
|
|
8
|
+
|
|
9
|
+
| 対象 | ユーザーが用意するもの |
|
|
10
|
+
|---|---|
|
|
11
|
+
| iOS | macOS、Xcode本体とiOS SDK。Xcodeを初回起動してセットアップを完了する。 |
|
|
12
|
+
| Android | Android Studio、Android SDK、使用するCapacitorに対応したJDK。 |
|
|
13
|
+
| 実機・配布ビルド | 対象端末と、その配布方法に必要な署名証明書・プロビジョニング設定またはAndroidの署名鍵。 |
|
|
14
|
+
|
|
15
|
+
使用するCapacitorのバージョンはbuilderの `src/tool-packages.ts` で固定している。
|
|
16
|
+
対応するネイティブ環境は[Capacitorの開発フロー](https://capacitorjs.com/docs/basics/workflow)から確認する。
|
|
17
|
+
Capacitorの `cli`・`core`・`ios`・`android` はbuilderが同じバージョンで取得するため、手動インストールは不要。
|
|
18
|
+
|
|
19
|
+
#### iOS:Xcodeの選択を確認する
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
xcode-select -p
|
|
23
|
+
xcodebuild -version
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`/Library/Developer/CommandLineTools` が選択されていると、IPA生成時に `xcodebuild requires Xcode` で失敗する。
|
|
27
|
+
今回のシェルだけXcodeを指定する場合は、次を設定してからSTEP3へ進む:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
|
|
31
|
+
xcodebuild -version
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
システム全体の既定を変える場合は、代わりに次を使う:
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
|
|
38
|
+
xcodebuild -version
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Xcodeの配置先が異なる場合はパスを変更する。builderは呼び出し元の `DEVELOPER_DIR` を引き継ぐ。
|
|
42
|
+
[Appleのコマンドラインツール設定](https://developer.apple.com/documentation/xcode/configuring-command-line-tools-settings)
|
|
43
|
+
|
|
44
|
+
### STEP2:アプリ設定とプラグインを用意する
|
|
45
|
+
|
|
46
|
+
ゲームルートの `capacitor.config.json` にアプリ固有の値を設定する。
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"appId": "app.example.game",
|
|
51
|
+
"appName": "My Game",
|
|
52
|
+
"webDir": "dist/ios/prd/"
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
| 項目 | 設定・管理方法 |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `appId` / `appName` | 自分のアプリ識別子・表示名に変更する。 |
|
|
59
|
+
| `webDir` | builderが今回のWeb出力先に更新するため、OSごとの手動切り替えは不要。 |
|
|
60
|
+
| `ios.path` / `android.path` | 必要な場合だけネイティブプロジェクトのカスタム出力先を指定する。 |
|
|
61
|
+
| ゲーム固有のCapacitor/Cordovaプラグイン | ゲームの依存として管理する。ゲーム側のフックも引き続き使用する。 |
|
|
62
|
+
| `@capacitor/core` | ゲームのJavaScriptで直接importする場合だけ、builderのCapacitorと互換性のあるバージョンをゲームの直接依存に追加する。 |
|
|
63
|
+
|
|
64
|
+
その他の項目は[Capacitor設定](https://capacitorjs.com/docs/config)を参照。
|
|
65
|
+
|
|
66
|
+
### STEP3:ネイティブプロジェクトを開き、署名・アイコンを設定する
|
|
67
|
+
|
|
68
|
+
対象OSのコマンドを実行する。
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
npx @next2d/builder --platform ios --env prd --open
|
|
72
|
+
npx @next2d/builder --platform android --env prd --open
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
未作成の `ios/` / `android/` を生成し、Web資産とネイティブ依存を同期してIDEを開く。
|
|
76
|
+
Xcode / Android Studioで、アプリのアイコン・署名・配布方法に必要な設定を行う。
|
|
77
|
+
これらのネイティブプロジェクトはゲーム側で保持する。再実行時も既存の設定・ネイティブコードを維持する。
|
|
78
|
+
|
|
79
|
+
### STEP4:ビルドして対象環境で確認する
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
npx @next2d/builder --platform ios --env prd --build
|
|
83
|
+
npx @next2d/builder --platform android --env prd --build
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
実行前にWeb資産・ネイティブ依存を再同期する。対象端末やシミュレーター/エミュレーターで起動・入力・保存を確認する。
|
|
87
|
+
Capacitorの `cap run` を使う場合は `--build` を `--preview` に置き換える。
|
|
88
|
+
途中のコマンドが失敗した場合はbuilderも失敗する。
|
|
89
|
+
|
|
90
|
+
テンプレートのnpmスクリプト `open:ios` / `open:android` / `build:ios` / `build:android` も使用できる。
|
|
91
|
+
環境指定は `npm run build:ios -- --env prd` のように渡す。
|
|
92
|
+
|
|
93
|
+
### 補足:既存プロジェクトの移行とSDKキャッシュ
|
|
94
|
+
|
|
95
|
+
1. ゲームから不要になった `@capacitor/cli`・`@capacitor/ios`・`@capacitor/android` の直接依存を外す。
|
|
96
|
+
`@capacitor/core` とゲーム固有プラグインはSTEP2の条件に従う。
|
|
97
|
+
2. 設定と `ios/` / `android/` は保持し、STEP3でネイティブ依存の参照先を再同期する。
|
|
98
|
+
|
|
99
|
+
builderはゲームルートでCapacitor CLIを実行し、取得したSDKのパスを子プロセスの `NODE_PATH` に追加する。
|
|
100
|
+
通常・ネストされたnpm依存配置や `file:../builder` に対応し、ゲーム側の補助スクリプトやSDKシンボリックリンクは不要。
|
|
101
|
+
SDKキャッシュは書き出し後もGradle / CocoaPodsが参照するため保持する。
|
|
102
|
+
npxキャッシュを削除した場合は、STEP3またはSTEP4で参照先を再同期する。
|
|
103
|
+
|
|
104
|
+
## English
|
|
105
|
+
|
|
106
|
+
### STEP1: Prepare the platform IDE and SDK
|
|
107
|
+
|
|
108
|
+
| Target | What you need to prepare |
|
|
109
|
+
|---|---|
|
|
110
|
+
| iOS | macOS, the full Xcode application and the iOS SDK. Complete Xcode's first-launch setup. |
|
|
111
|
+
| Android | Android Studio, the Android SDK and a JDK compatible with the Capacitor version in use. |
|
|
112
|
+
| Device and distribution builds | Target devices and signing certificates/provisioning settings or an Android signing key, as required by the distribution method. |
|
|
113
|
+
|
|
114
|
+
The builder pins the Capacitor version in `src/tool-packages.ts`.
|
|
115
|
+
Check the corresponding native environment through the [Capacitor development workflow](https://capacitorjs.com/docs/basics/workflow).
|
|
116
|
+
The builder acquires matching versions of Capacitor's `cli`, `core`, `ios` and `android`; no manual installation is needed.
|
|
117
|
+
|
|
118
|
+
#### iOS: Check the selected Xcode
|
|
119
|
+
|
|
120
|
+
```sh
|
|
121
|
+
xcode-select -p
|
|
122
|
+
xcodebuild -version
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
If `/Library/Developer/CommandLineTools` is selected, IPA generation fails with `xcodebuild requires Xcode`.
|
|
126
|
+
To select Xcode for the current shell, set this before STEP3:
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
|
|
130
|
+
xcodebuild -version
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Alternatively, to change the system-wide default:
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
|
|
137
|
+
xcodebuild -version
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Adjust the path if Xcode is installed elsewhere. The builder inherits the caller's `DEVELOPER_DIR`.
|
|
141
|
+
[Apple's command-line tools settings](https://developer.apple.com/documentation/xcode/configuring-command-line-tools-settings)
|
|
142
|
+
|
|
143
|
+
### STEP2: Prepare app configuration and plugins
|
|
144
|
+
|
|
145
|
+
Set game-specific values in `capacitor.config.json` at the game root.
|
|
146
|
+
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"appId": "app.example.game",
|
|
150
|
+
"appName": "My Game",
|
|
151
|
+
"webDir": "dist/ios/prd/"
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
| Setting | Configuration / ownership |
|
|
156
|
+
|---|---|
|
|
157
|
+
| `appId` / `appName` | Replace with your app identifier and display name. |
|
|
158
|
+
| `webDir` | The builder updates this to the current web output directory; no manual switching between operating systems is needed. |
|
|
159
|
+
| `ios.path` / `android.path` | Set only when using custom native project locations. |
|
|
160
|
+
| Game-specific Capacitor/Cordova plugins | Keep them in the game's dependencies. Game hooks continue to work. |
|
|
161
|
+
| `@capacitor/core` | Add a compatible version as a direct game dependency only when the game's JavaScript imports it directly. |
|
|
162
|
+
|
|
163
|
+
See [Capacitor configuration](https://capacitorjs.com/docs/config) for other settings.
|
|
164
|
+
|
|
165
|
+
### STEP3: Open the native project and configure signing and icons
|
|
166
|
+
|
|
167
|
+
Run the command for your target OS:
|
|
168
|
+
|
|
169
|
+
```sh
|
|
170
|
+
npx @next2d/builder --platform ios --env prd --open
|
|
171
|
+
npx @next2d/builder --platform android --env prd --open
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The builder creates missing `ios/` / `android/` projects, synchronizes web assets and native dependencies, then opens the IDE.
|
|
175
|
+
Configure app icons, signing and distribution-specific settings in Xcode / Android Studio.
|
|
176
|
+
Keep these native projects in the game. Subsequent runs preserve existing settings and native code.
|
|
177
|
+
|
|
178
|
+
### STEP4: Build and verify on the target environment
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
npx @next2d/builder --platform ios --env prd --build
|
|
182
|
+
npx @next2d/builder --platform android --env prd --build
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Web assets and native dependencies are synchronized before building. Verify launch, input and saved data on target devices or simulators/emulators.
|
|
186
|
+
Replace `--build` with `--preview` to use Capacitor's `cap run`.
|
|
187
|
+
If any command fails, the builder fails as well.
|
|
188
|
+
|
|
189
|
+
Template npm scripts `open:ios` / `open:android` / `build:ios` / `build:android` are also available.
|
|
190
|
+
Pass the environment as in `npm run build:ios -- --env prd`.
|
|
191
|
+
|
|
192
|
+
### Reference: Existing project migration and SDK cache
|
|
193
|
+
|
|
194
|
+
1. Remove direct dependencies on `@capacitor/cli`, `@capacitor/ios` and `@capacitor/android` that are no longer needed by the game.
|
|
195
|
+
Follow STEP2 for `@capacitor/core` and game-specific plugins.
|
|
196
|
+
2. Keep the configuration and `ios/` / `android/`, then use STEP3 to resynchronize native dependency paths.
|
|
197
|
+
|
|
198
|
+
The builder runs the Capacitor CLI from the game root and adds acquired SDK paths to the child process's `NODE_PATH`.
|
|
199
|
+
Regular and nested npm dependency layouts and `file:../builder` are supported; no game-side helper scripts or SDK symlinks are needed.
|
|
200
|
+
Keep the SDK cache after export because Gradle / CocoaPods reference it.
|
|
201
|
+
If you delete the npx cache, use STEP3 or STEP4 to resynchronize those paths.
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# ネイティブ機能の拡張(Electron Native Bridge)
|
|
2
|
+
|
|
3
|
+
Next2Dのデスクトップアプリから、OS APIや任意のネイティブSDKを利用するための汎用拡張です。EOS専用ではありません。ネイティブ機能はアプリ側が用意する実行ファイル(sidecar)に実装し、builderが起動・通信・同梱を担当します。
|
|
4
|
+
|
|
5
|
+
対象はElectronのmacOS/Windows/LinuxとSteamデスクトップ出力です。WebブラウザやiOS/AndroidにはこのAPIは提供されません。モバイルは [Capacitorガイド](capacitor.md) を参照してください。
|
|
6
|
+
|
|
7
|
+
## 責務と構成
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
Next2Dアプリ → window.next2dNative → Electron IPC → ネイティブ実行ファイル
|
|
11
|
+
└ OS API / 任意のSDK
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
- builder: CPU別ファイルの同梱、メソッド許可リスト、要求/応答・イベント通信、プロセス終了処理。
|
|
15
|
+
- アプリ: ネイティブ処理と入力検証、各OS向けコンパイル、SDKの初期化・後始末、ライセンスと権限設定。
|
|
16
|
+
- SDKの取得、ソースの自動コンパイル、認証・オンラインサービスの実装はbuilderの機能ではありません。
|
|
17
|
+
- `nativeBridge` 未設定ならプロセスを起動せず、`window.next2dNative` も公開しません。
|
|
18
|
+
|
|
19
|
+
## 1. ネイティブ実行ファイルを用意する
|
|
20
|
+
|
|
21
|
+
後述のSidecarプロトコルを実装した実行ファイルを、アプリ側でOS・CPUごとに用意します。使用言語はC++/Rust/Swiftなどから選べます。以下の `native-helper` と `system.info` は設定・通信の説明用の名前であり、実装サンプルは同梱していません。
|
|
22
|
+
|
|
23
|
+
## 2. electron.config.json に設定する
|
|
24
|
+
|
|
25
|
+
既存のアプリ設定に追加します。
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"architectures": { "macos": "arm64" },
|
|
30
|
+
"nativeBridge": {
|
|
31
|
+
"methods": ["system.info"],
|
|
32
|
+
"backgroundThrottling": true,
|
|
33
|
+
"targets": {
|
|
34
|
+
"macos-arm64": { "directory": "native/macos-arm64", "executable": "native-helper" }
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
| 設定 | 内容 |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `methods` | rendererから許可するメソッド名。英字開始、英数字・`_`・`.`、最大64文字 |
|
|
43
|
+
| `targets` | ビルドするOS・CPUに対応するネイティブファイル群 |
|
|
44
|
+
| `directory` | プロジェクトルート基準のディレクトリ。絶対パスも可能。全体を同梱 |
|
|
45
|
+
| `executable` | ディレクトリ直下の実行ファイル名。パスやシェルコマンドは不可 |
|
|
46
|
+
| `backgroundThrottling` | `true` は非アクティブ時のrendererの処理抑制を許可。リアルタイム用途では `false`。既存利用との互換性のため省略時は `false` |
|
|
47
|
+
|
|
48
|
+
バックグラウンド設定はrendererのタイマー・描画の指定であり、OS全体の省電力設定やsidecarのスケジューリングを変更しません。
|
|
49
|
+
|
|
50
|
+
対応キーは `macos-arm64`/`macos-x64`/`macos-universal`/`windows-x64`/`windows-arm64`/`linux-x64`/`linux-arm64`。未用意のターゲットへの出力はエラーになります。macOS既定値はuniversalなので、上例はarm64を明示しています。universalは実行ファイルと依存ライブラリすべてが両CPU対応である必要があります。builderはCPU形式を検査・変換しません。
|
|
51
|
+
|
|
52
|
+
専用ディレクトリには実行ファイルと必要なdylib/DLL/so、配布可能なデータだけを置きます。ソース、秘密鍵、管理者資格情報を置かないでください。シンボリックリンクと特殊ファイルは拒否します。
|
|
53
|
+
|
|
54
|
+
## 3. Next2Dアプリから呼び出す
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
const native = window.next2dNative;
|
|
58
|
+
if (native) {
|
|
59
|
+
const unsubscribe = native.onEvent(({ event, data }) => {
|
|
60
|
+
if (event === "system.ready") console.log("Native helper ready", data);
|
|
61
|
+
if (event === "bridge.closed") console.error("Native helper closed", data);
|
|
62
|
+
});
|
|
63
|
+
try {
|
|
64
|
+
const info = await native.request("system.info", {});
|
|
65
|
+
console.log(info.platform, info.logicalProcessors);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error("Native request failed", error);
|
|
68
|
+
} finally {
|
|
69
|
+
unsubscribe(); // 継続監視する場合は画面・サービスの破棄時に解除
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`request(method, params)` は応答を返すPromise、`onEvent(listener)` は解除関数を返します。アプリの通信・デバイス操作層にラップし、UIとは分離してください。Node API・任意パス・汎用IPC・シェル実行はrendererへ公開しません。sandbox/contextIsolationを維持し、IPCはアプリのメインフレームに限定します。引数はsidecarでも検証してください。
|
|
75
|
+
|
|
76
|
+
## 4. ビルド・配布
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
npx @next2d/builder --platform macos --arch arm64 --env local --preview
|
|
80
|
+
npx @next2d/builder --platform macos --arch arm64 --env prd
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
ローカルのbuilderでは `npm run build` 後、ゲームプロジェクトから `node ../builder/dist/index.js ...` で実行できます。
|
|
84
|
+
|
|
85
|
+
ネイティブファイルはASAR外の `process.resourcesPath/native`(macOSでは `.app/Contents/Resources/native`)へ配置され、Web配信する `resources` とは分離されます。共有ライブラリは実行ファイル相対で解決できるようにビルドしてください。最初の `request` で同梱実行ファイルが起動します。
|
|
86
|
+
|
|
87
|
+
署名・公証は [デスクトップガイド](steam.md) の設定を使用し、実行ファイルと依存ライブラリを含む完成アプリで検証します。利用するOS機能に応じた説明文・権限・entitlement等は別途必要です。例えばLANアクセスでは `macos.localNetworkUsageDescription` を設定できます。単純なOS情報取得の例では必要ありません。
|
|
88
|
+
|
|
89
|
+
ビルド専用設定は `NEXT2D_ELECTRON_CONFIG_FILE=/absolute/path/to/config.json` で指定可能です。存在しない指定先はエラーになります。一時設定はアプリ側で管理し、配布ディレクトリには混ぜないでください。同梱ファイルを秘密にする保証はありません。
|
|
90
|
+
|
|
91
|
+
## Sidecarプロトコル v1
|
|
92
|
+
|
|
93
|
+
stdin/stdoutでUTF-8 JSONを1行ずつ交換します。stdoutはプロトコル専用とし、各行をflushしてください。
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{"id":1,"method":"system.info","params":{}}
|
|
97
|
+
{"id":1,"result":{"platform":"macos","logicalProcessors":8}}
|
|
98
|
+
{"id":2,"error":"Unsupported method"}
|
|
99
|
+
{"event":"system.ready","data":{"protocol":1}}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
要求の整数IDを応答にそのまま返します。エラーは文字列の `error`、イベントは `event` と `data` を使います。`bridge.closed` はbuilder予約名です。業務エラーはその要求だけを失敗させます。
|
|
103
|
+
|
|
104
|
+
- 1行最大256KiB、同時要求128件、応答待ち15秒。SDK用途に固有のメソッドは予約しません。
|
|
105
|
+
- タイムアウトはネイティブ処理のキャンセルではありません。再試行・重複防止はアプリ側で設計します。
|
|
106
|
+
- プロトコル違反・プロセス終了で待機中の要求を失敗させ、`bridge.closed` を通知。自動再起動はしません。
|
|
107
|
+
- ブリッジの終了処理はstdinを閉じ、EOFでsidecarの後始末を促し、4秒後の強制終了を予約します。ただしElectron本体を4秒間終了待ちにする仕組みではなく、本体が先に終了するとタイマーは実行されません。必ずstdin EOFで速やかに終了する設計にしてください。プロトコル違反等では即時強制終了します。rendererクラッシュ時も終了処理を行いますが、強制終了・OS異常時の後始末は保証できません。
|
|
108
|
+
- 外部サービスの切断・保存等は必要に応じて終了前に独自のメソッドで行います。別の常駐プロセスを起動せず、stdin EOFでも終了するよう実装してください。
|
|
109
|
+
- stderrは読み捨て、rendererには転送しません。必要な診断ログはsidecar側で秘匿情報を除いて記録します。大量のイベントは発行元で制限・集約してください。
|
|
110
|
+
|
|
111
|
+
現状は1アプリにつき1つのsidecarです。複数SDKを使う場合はその実行ファイル内でメソッドを振り分けます。動的な任意実行や複数プロセスのプラグイン管理機構ではありません。
|
|
112
|
+
|
|
113
|
+
## ビルド時の準備スクリプト(任意)
|
|
114
|
+
|
|
115
|
+
`nativeBridge.prepare` にプロジェクト相対の `.js` / `.mjs` / `.cjs` を指定すると、通常のデスクトップ/Steam書き出しで、ネイティブ同梱前にNode.jsスクリプトを実行します。CLI・環境名・出力先は変わりません。未指定の場合は従来どおり `targets` のディレクトリ全体をコピーします。
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{ "nativeBridge": {
|
|
119
|
+
"prepare": "scripts/prepare-native.mjs",
|
|
120
|
+
"methods": ["system.info"],
|
|
121
|
+
"targets": { "windows-x64": { "directory": "native/windows-x64", "executable": "helper.exe" } }
|
|
122
|
+
} }
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
実行契約:`node <script> --target <OS-CPU> --source <絶対パス> --destination <絶対パス>`。cwdはプロジェクトルート。出力先はビルド専用の一時フォルダで、スクリプトが実行ファイル・ライブラリ・必要な設定だけを書き込みます。元ディレクトリがまだ存在しない場合のコンパイルもスクリプト側で行えます。プロセスの環境変数を継承し、シェルは介しません。終了コード非0・120秒タイムアウト・シンボリックリンク・実行ファイル欠落でビルドを停止します。
|
|
126
|
+
|
|
127
|
+
このスクリプトはVite設定同様、信頼するプロジェクトのコードとして実行されます。OS権限を制限するサンドボックスではありません。スクリプト自体はプロジェクト外へ解決されるパスを拒否します。準備スクリプトのパスはrendererへ渡さず、準備済みファイルはWebアセットと分離します。一時フォルダは成功・失敗時に削除します。秘密情報をstdout/stderrへ出さないでください。
|
|
128
|
+
|
|
129
|
+
## 応用例: Epic Online Services(EOS)
|
|
130
|
+
|
|
131
|
+
EOSも上記と同じ汎用プロトコルを利用する一例です。builder内にEOS SDK・認証情報・Lobby/P2P実装はありません。
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"nativeBridge": {
|
|
136
|
+
"methods": ["eos.status", "match.open", "match.close", "lobby.create", "lobby.join", "p2p.send"],
|
|
137
|
+
"backgroundThrottling": false,
|
|
138
|
+
"targets": {
|
|
139
|
+
"macos-arm64": { "directory": "native/eos/macos-arm64", "executable": "eos-sidecar" }
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
これらのメソッド名はアプリ側が定義する例で、builderの組み込みAPIではありません。アプリ側でEOS SDKを使うsidecarと各OS向けバイナリを作り、サービス設定・認証・退出・切断処理を実装します。rendererでは例えば `native.request("match.open", { protocol: 1, provider: "eos" })` をアプリ側の契約に合わせて呼び出します。
|
|
146
|
+
|
|
147
|
+
SDKによるネイティブ処理とゲーム固有の同期・命中・勝敗処理は分離します。サービス設定・利用条件・認証方式、複数端末接続、切断時の処理はアプリ側で検証が必要です。管理者やサーバー用の資格情報を同梱しないでください。この設定だけで別の通信方式がEOSへ自動移行することはありません。
|