Skip to content

Core API ja

Tom_XV edited this page Sep 23, 2026 · 7 revisions

English | 日本語

中核のプラグインです。ファイルは DragNWash.ModFramework.dll、名前空間は DragNWash.ModFramework です。

[BepInDependency(ModFramework.Guid, BepInDependency.DependencyFlags.HardDependency)]

ModFramework

メンバー 内容
const string Guid 依存関係に使う "com.tomxv.dragnwash.modframework"
const string Version フレームワークのバージョン
bool IsReady フレームワークの起動が終わると true
event Action Ready 起動が終わったときに 1 回だけ呼ばれる。そのあとで追加したハンドラーはすぐ呼ばれる
void Register(ModInfo info) Mods 画面に Mod の情報を伝える。同じ GUID でもう一度登録すると置き換わる
void AddModsPage(ModsScreenPage page) Mod の詳細に独自のページを足す。1.5.0 からは About や Settings と並ぶ専用のタブになる(前はボタンで開いていた)

ModInfo

プロパティ 意味
Guid Mod の BepInEx の GUID。必須
DisplayName プレイヤー向けの名前。空白や記号も使える。省略すると BepInEx の名前
Description 1〜2 文の説明
Authors string[]
Website プロジェクトやダウンロードのページ
UpdateRepository GitHub リポジトリを "owner/name" で(中核 1.1.0 以降)。中核が 1 日 1 回最新リリースを読み、入っているバージョンより新しければ Mods 画面で Update の印と、リリースページを開くボタンを出す。リリースのタグはプラグインのバージョン(v1.2.0 や 1.2.0)にすること。ドラフトとプレリリースは知らせない。プレイヤーは確認を止められる
IsLibrary ほかの Mod が土台にする前提 Mod なら true。Mods 画面では一覧の下の Libraries のまとまりに入り(1.5.0。それより前は Library の印が付いていた)、必要としている Mod が一覧され、オフにする前に確認が出る
Icon Texture2D。正方形が理想。Awake で作ること(Assets 参照)。IconPath より優先
IconPath 登録時に読み込む PNG か JPG のファイル。Awake で登録すること
Network NetworkUse[]。Mod が接続するホストをすべて並べる(中核 1.2.0、実験的)。外と通信する Mod を参照

ModsScreenPage

BepInEx の設定項目では表せない設定のためのページです。1.5.0 からは、Mod が足したページはいくつあってもそれぞれ Mod の詳細にタブを 1 つずつもらい、Title がそのタブの名前になります。ページはタブの中の領域に組み立てます。Build が例外を投げたときは、中途半端なページの代わりに短いメッセージと Try again が出ます。

ModFramework.AddModsPage(new ModsScreenPage
{
    Guid = MyMod.Guid,
    Title = "Statistics",
    Build = panel =>
    {
        // panel は RectTransform で、呼ばれるたびに中身が消される。
        // UnityEngine.UI と TextMeshPro の部品で組み立てる。
    },
});

1.5.0 からは、ページの後ろの板が透けているので、決まった色の文字は明るい場面の上で読みにくくなることがあります。ModsScreenLook には、どんな背景でも読める画面自身の文字の色(Text、Muted、Accent、Error、Warning)と、設定の行と同じ見た目の Card、画面のものと同じ Button があります。色はいま使っている見た目(すりガラスか暗い色だけか)に合わせて変わり、見た目が変わると開いているページは組み立て直されるので、組み立てるときに読んでください。

Build = panel =>
{
    RectTransform card = ModsScreenLook.Card(panel);
    TextMeshProUGUI line = new GameObject("Line").AddComponent<TextMeshProUGUI>();
    line.transform.SetParent(card, false);
    line.text = "12 cars washed";
    line.color = ModsScreenLook.Text;
    ModsScreenLook.Button(panel, "Reset", () => ResetStats());
},

古い中核でも動かしたい Mod は、[MethodImpl(MethodImplOptions.NoInlining)] を付けた自分のメソッドの中から ModsScreenLook を使い、例外が出たら自分の色に戻すようにしてください。

GameOptions

ゲームの Options 画面に行を足す機能です。動きはゲームの流れどおりで、行を変えるとプレビューされてゲームの Save ボタンが出て、Save で確定、保存せずに Back で戻ると保存済みの値に戻り、Set Default では指定した既定値になります。ラベルと選択肢は英語で書いてください。翻訳 Mod がほかの UI テキストと同じように訳してくれます。

GameOptions.AddChoice(new OptionsChoice
{
    Id = "com.example.mymod.difficulty",   // 一意。同じ id をもう一度追加しても無視される
    Label = "Difficulty",
    Choices = new[] { "Relaxed", "Normal", "Messy" },
    Section = OptionsSection.Gameplay,       // Gameplay(既定)、Audio、Graphics
    DefaultIndex = 1,                        // -1 なら Set Default で変えない
    GetSaved = () => _difficulty.Value,
    Save = index => _difficulty.Value = index,
    Preview = index => ApplyDifficulty(index), // 任意。表示が変わるたびに呼ばれる
});

GameOptions.AddToggle("com.example.mymod.fastmode", "Fast Mode",
    getSaved: () => _fastMode.Value,
    save: value => _fastMode.Value = value,
    preview: null, section: OptionsSection.Gameplay, defaultValue: false);

// ほかの場所(独自のメニュー、設定ファイルの編集)で値を変えたあと:
GameOptions.Refresh("com.example.mymod.fastmode");

AddChoice はいつ呼んでもかまいません。行はゲームの設定ができた時点で出ます。Id、Label、2 つ以上の Choices、GetSaved、Save のどれかが欠けていると ArgumentException を投げます。

Services

ライブラリが、内部には触らせずに、ほかの Mod へ API を提供するためのしくみです。

// ライブラリ側(IScoreService はライブラリの DLL で公開する):
Services.Register<IScoreService>(new ScoreService(), new Version(1, 2), MyLibrary.Guid);

// ライブラリに BepInDependency を持つ Mod の Awake から:
var scores = Services.Get<IScoreService>();

// 強い依存関係がない、または最低バージョンが必要な Mod:
if (Services.TryGet<IScoreService>(out var s, new Version(1, 1))) { /* s を使う */ }
Services.WhenAvailable<IScoreService>(s => { /* 今すぐ、または登録された時点で呼ばれる */ });
メンバー 内容
bool Register<T>(T implementation, Version version = null, string ownerGuid = null) T の提供元を登録する。同じ T に 2 つ目の提供元は登録されず、ログに出る
T Get<T>() 提供元。なければ null
bool TryGet<T>(out T service, Version minimumVersion = null) 指定バージョン以上の提供元があれば、それを返す
Version GetVersion<T>() 提供元が登録したバージョン。なければ null
void WhenAvailable<T>(Action<T> callback) 今すぐ、または T が登録された時点でコールバックを呼ぶ

GameHooks

パッチを当てるゲームのコードが、動いているビルドにまだあるかを確かめます。こうしておけば、ゲームがアップデートされても落ちずに、その機能が 1 つ止まるだけで済みます。確認に失敗するとログに出て、Mods 画面に Unavailable on this game build(このゲームのビルドでは使えない)と表示されます。

// "ScrubController" は、パッチを当てるゲームの型の例です。
if (GameHooks.Require(MyMod.Guid, "Faster scrubbing", "ScrubController", "Update"))
{
    harmony.PatchAll(typeof(ScrubPatches));
}

// 自分で確認した結果を記録する:
var method = AccessTools.Method("ScrubController:Update");
GameHooks.Require(MyMod.Guid, "Faster scrubbing", method != null, "ScrubController.Update");
メンバー 内容
bool Require(string ownerGuid, string feature, string typeName, string methodName = null) 型(とメソッド)があれば true。typeName には Harmony と同じ "Type:Method" の 1 つの文字列も渡せる。Inspector の Code 表示がコピーする形そのもの(中核 1.2.0)
bool Require(string ownerGuid, string feature, bool passed, string detail) 自分でした確認を記録し、passed を返す
void Unavailable(string ownerGuid, string feature, string reason) ゲームのメンバーの有無以外の理由(クラッシュ後に止めた、このレンダラーでは使えない、など)で機能を使えない印にする。確認の失敗と同じように表示される(中核 1.2.0)
IReadOnlyList<string> UnavailableFeatures(string ownerGuid) 確認に失敗した、その Mod の機能

DeveloperTools(実験的、中核 1.2.0)

Mod を作る人や翻訳者向けの機能をまとめて切り替える 1 つのスイッチで、既定はオフです。場所は Options → Mods → Drag'n Wash ModFramework → Developer tools です。オフの間は Tool window は開かず、テクスチャのリロードも断られます。自分の Mod の書き出しやホットリロード、デバッグ用のキーやウィンドウも、このスイッチの内側に置いてください(GUIDE のルール 8)。

if (DeveloperTools.Enabled) ExportWorkingCopy();
DeveloperTools.WhenEnabled(StartWatchingFiles);   // 今すぐと、その後オンになるたびに
DeveloperTools.Changed += () => { if (!DeveloperTools.Enabled) StopWatchingFiles(); };
メンバー 内容
bool Enabled 開発者ツールがオンの間 true
event Action Changed Mods 画面か設定ファイルでスイッチが変わったときに呼ばれる
void WhenEnabled(Action onEnabled) オンなら今すぐ動かし、そのあともオンになるたびに動かす

GameEvents と SettingMeta(実験的、中核 1.2.0)

  • GameEvents には GameEvents.OnSceneLoaded、OnSceneUnloaded、OnGameStarted、OnQuitting があります。どれも自分の GUID で登録して、Mod ごとに切り離して呼ばれます。
  • SettingMeta では、ConfigDescription のタグに SettingMeta と SectionMeta を入れて、設定ページの並び順や上級者向けの項目、再起動が要るという印を決めます。文字列やキー割り当ても、ページの上で編集できます。

ほかの設定と同じキー

ショートカットのキーは Mod ごとに自分の BepInEx の設定に持っているので、2 つの Mod がお互い知らないまま同じキーを使っていることがあります。中核に聞けば、そのキーをほかに誰が使っているかが分かります。ただ、分かるのは知らせるところまでです。1 つのキーで 2 つのことをしたいプレイヤーもいて、それを決められるのは本人だけなので、キーを断ったり勝手に変えたりはしないでください。

// F5 の設定をほかに誰が持っているか。自分の Mod は除く(中核 1.4.2)
foreach (string other in ModFramework.WhoElseUses(KeyCode.F5, MyMod.Guid))
{
    Logger.LogInfo($"F5 is also used by {other}");   // "Drag'n Wash Localization: [Debug] DumpDialogueKey"
}

// 自分のキー設定の窓で、キーの下に出す(1.5.0)
string note = ModFramework.SharedKeyNote(_screenshotKey);   // ConfigEntry<KeyboardShortcut>
if (note != null)
{
    GUI.Label(noteRect, note, ToolWindow.Styles.WrappedLabel);
}

SharedKeyNote は、Mods 画面がショートカットの設定の下に出すのと同じ 1 行を返します。たとえば「C is also used by Screenshot key (Photo Mode). Both will answer it.」で、ほかの設定が 2 つ以上なら最後が「All of them will answer it.」になります。ほかの設定はそれぞれの設定ページでの名前で出て、別の Mod のものなら後ろに括弧で Mod の名前が付きます。自分の Mod のほかの設定も数に入ります。比べるのはメインのキーだけなので、Ctrl+C と C は同じキーとして扱います。ほかに誰もそのキーを持っていないとき、キーが None のとき、KeyboardShortcut の設定じゃないときは null です。Mods 画面もこの 1 行をここから取っているので、Mod が自分の窓に出す文と Mods 画面の文はいつも同じになります。Inspector の ? パネルも、キーの注意はこれで出しています。

メンバー 内容
IReadOnlyList<string> WhoElseUses(KeyCode key, string exceptGuid = null) そのキーのショートカット設定を持つ、読み込み済みの Mod の一覧。Mod: [Section] Key の形で、exceptGuid は除く(中核 1.4.2)
string SharedKeyNote(ConfigEntryBase shortcut) ほかの設定と同じキーになっているショートカットについて、Mods 画面が出す 1 行。なければ null(1.5.0)

SafeFile(1.5.0)

SafeFile.Write は、落ちたりほかのプログラムがファイルを開いたままだったりしても、ファイルが途中で切れた状態で残らないように書き込みます。渡した処理がまずターゲットの隣の一時ファイルに書いて、それが済んでから元の場所へ移すので、ファイルの中身は古いままか新しいものかのどちらかになります。隣に一時ファイルを開けないときはターゲットに直接書くので、この守りがなくなるだけで、中身は失いません。Flags and saves のセーブの書き込みと、Inspector の Export もこれを使っています。

SafeFile.Write(path, new UTF8Encoding(false), w => w.Write(json));
メンバー 内容
void Write(string path, Encoding encoding, Action<StreamWriter> write) 隣の一時ファイルを通して path を書く(1.5.0)

GameInfo

メンバー 意味
string UnityVersion 例:6000.3.14f1
GraphicsDeviceType GraphicsApi 使っているグラフィックス API
bool IsDirect3D12 Direct3D 12 なら true。テクスチャやフォントを起動時に読み込む必要がある(Assets 参照)
OperatingSystemFamily OperatingSystem Windows、Linux(Steam Deck)、MacOSX

中核にあるそのほかの機能

  • Mods 画面の オン・オフ は、プラグインが読み込まれる前に BepInEx/patchers/DragNWash.ModFramework.Preloader.dll が反映します
  • 起動後には 競合の検出 もします。複数の Mod がパッチを当てているゲームのメソッドをログに書き出し、Mods 画面でその Mod に印を付けます。詳しくは ほかの Mod と一緒に動かす を見てください
  • タイトル画面 では、ビルド番号の上にバージョンと、読み込んだ BepInEx プラグインの数を表示します

Clone this wiki locally