← 一覧へ

F-coreを一から作り直した理由

F-coreは、自分自身のノベルゲームを作るために開発しているノベルゲームエンジンです。

最初の大きな節目として v0.1.0-alpha まで作りました。
一応、動くものはありました。GUIホストもあり、シナリオを読み、画面に表示し、操作もできる。外から見ると「エンジンらしい形」にはなっていました。

しかし、実際に作品を作ろうとした瞬間に問題が見えました。

GUIホストが、急激に肥大していったのです。

v0.1.0-alphaで起きたこと

プロトタイプ段階では、GUIホストに少しずつ機能を足していくのが一番速く見えます。

シナリオを読む。
描画する。
状態を持つ。
選択肢を扱う。
保存する。
デバッグしやすくする。
制作中に確認しやすくする。

こうした機能を足していくうちに、GUIホストがどんどん大きくなっていきました。

最初は「開発を速くするための薄いホスト」のつもりでした。
しかし実際には、GUIホストがランタイムの責務まで飲み込み始めていました。

これはかなり危険な兆候でした。

GUIホストが大きくなると、何がコアなのか分からなくなります。
どこが作品実行の責務で、どこが開発補助の責務なのかも曖昧になります。
さらに、セキュリティ境界も見えづらくなります。

F-coreでやりたいことは、そういう作りではありませんでした。

F-coreの設計思想との衝突

F-coreでは、最初からいくつかの方針を大事にしています。

  • 最小限のコア
  • 依存を増やしすぎない
  • 任意コード実行を避ける
  • プラグインを制御された境界で実行する
  • 実行モデルを監査しやすくする

つまり、便利なものを何でもGUIホストに詰め込む設計とは相性が悪い。

GUIホストが肥大すると、短期的には作業が進みます。
しかし長期的には、エンジンの中心が曖昧になります。

ノベルゲームエンジンとして大事なのは、派手なGUIではなく、作品を安全に、決定的に、長く動かせる実行モデルです。

v0.1.0-alpha は、その思想から外れ始めていました。

だから、作り直すことにしました。

破壊的変更を選んだ

今回は、互換性を保ったまま少しずつ直すのではなく、一から作り直すことにしました。

つまり、破壊的変更です。

この判断は軽くありません。
一度動いていたものを壊すことになるからです。
既存の実装を捨てることにもなります。

それでも、ここで曖昧な設計を温存すると、後からもっと大きな負債になります。

特にエンジン開発では、初期の責務分離を間違えると、後で直すのがかなり難しくなります。
GUI、ランタイム、プラグイン、保存、描画、開発支援が絡み合ったあとでは、どこを変更しても別の場所に影響が出るようになります。

だから、早い段階で壊しました。

作り直した後の方向性

作り直し後のF-coreでは、GUIホストを中心にしません。

中心に置くのは、コマンドIRとランタイムです。

シナリオはMarkdownからIRに変換されます。
ランタイムは { op, args } という小さな命令を受け取ります。
プラグインは saychoicesetasseteffectmenu のような明示的なコマンドとして扱います。

そして、プラグイン実行はWorker境界に寄せます。
実行前にはマニフェストを検証し、プラグインソースのハッシュも確認します。
式評価では evalnew Function を使わず、安全な演算子だけを許可します。

GUIホストは、あくまでホストです。
エンジンの本体ではありません。

この線引きをはっきりさせることが、今回の作り直しで一番大事な点でした。

Tauri-firstという選択

F-coreは、最終的にはTauriを本番ターゲットにします。

ElectronではなくTauriを選ぶ理由は、単に流行だからではありません。
配布サイズやメモリ消費を抑えたいこと。
保存や読み込みのようなOS側の処理を、Rust側の明確な境界に置きたいこと。
そして、Webだけで完結する開発体験も残したいこと。

そのため、F-coreでは本番はTauri-first、開発時はWeb fallbackという形を取ります。

ブラウザだけでもUI検証はできる。
しかし製品版としての配布はTauriを前提にする。

この分離も、GUIホストを肥大させないために必要でした。

今後書いていくこと

この記事は、F-coreを作り直した理由の記録です。

次回以降は、もう少し具体的な設計について書いていきます。

  • なぜElectronではなくTauri-firstなのか
  • MarkdownシナリオをどうIRに変換するのか
  • Worker sandboxでプラグインをどう隔離するのか
  • なぜ式評価にevalを使わないのか
  • 署名付きマニフェストで何を守っているのか
  • セーブデータをどう安全に保存・復元するのか

F-coreは、まだ初期段階の個人プロジェクトです。
しかし、初期段階だからこそ、設計思想を曖昧にしたくありません。

v0.1.0-alpha は、動くものを作るためには必要な段階でした。
同時に、それをそのまま伸ばしてはいけないことも教えてくれました。

だからF-coreは、一度壊して、作り直しました。

#日記 #F-core #ノベルゲームエンジン #Tauri #TypeScript #Rust