クラフトピアのModの開発を行うためには以下の準備が必要です。
- ソースの確認手段の準備
- C#の開発環境の用意
- CraftopiaModLoader(BepInEx)の設定変更
- CraftopiaModUploaderの準備
クラフトピアの本体プログラムに追加・改変を行うModを開発するわけですから、クラフトピアの本体がどのように動いているかを確認する必要があります。
クラフトピアはあえてMod開発がしやすいような仕組みを用いて開発されています。(プログラムの解析や複製が行われやすいというリスクを背負ってくれています)
クラフトピアのdllを解読するためのソフトがまず必要になります。逆コンパイラを準備しましょう。
有名なものでは「ILSpy」や「dnSpy」がよく使われています。
ここでは「dnSpy」を用いてソースを覗いてみましょう。
クラフトピアはあえてMod開発がしやすいような仕組みを用いて開発されています。(プログラムの解析や複製が行われやすいというリスクを背負ってくれています)
クラフトピアのdllを解読するためのソフトがまず必要になります。逆コンパイラを準備しましょう。
有名なものでは「ILSpy」や「dnSpy」がよく使われています。
ここでは「dnSpy」を用いてソースを覗いてみましょう。
- まずdnSpyの配布ページ*2に移動し、最新版を取得します。
- 適当なフォルダに展開し、dnSpy.exeを実行します。
- 「File⇒Open」を選択し、クラフトピアのコアdllである「AD_OverCraft.dll*3」を開きます。
- クラフトピアのプログラムはたいてい名前空間「Oc」もしくは「Oc.〜〜〜」の下にあるので、望む処理のものを探して確認します。
ソースはC#で記述されています。
Ctrl+Shift+Kで行う検索(Search)や、右クリックした変数がどこで使われているかの確認機能(Analyzer)を使って動作を確認していくとよいでしょう。

Modはクラフトピア本体やUnityに合わせ、プログラム言語「C#」で開発を行います。
総合開発環境であるマイクロソフトの「Visual Studio」が適当でしょう。C#のビルドが可能であれば他のものでも構いません。
有償版もありますが、無償版でも十分開発が行えます。ただし、マイクロソフトへのアカウント登録が必要です。
マイクロソフトのVisualStudioのページ*4からVisual Studio Communityをダウンロードしてインストールしてください。
「参照の追加」などこの後行うこともありますが、それは後述します。
総合開発環境であるマイクロソフトの「Visual Studio」が適当でしょう。C#のビルドが可能であれば他のものでも構いません。
有償版もありますが、無償版でも十分開発が行えます。ただし、マイクロソフトへのアカウント登録が必要です。
マイクロソフトのVisualStudioのページ*4からVisual Studio Communityをダウンロードしてインストールしてください。
「参照の追加」などこの後行うこともありますが、それは後述します。
まず、Modを使用するとき同様に、ワークショップからCraftopia Mod Loaderをサブスクライブします。
特に設定をしないで使用するとクラフトピア実行時には何もおこりませんが、
それではエラーが出た時に困りますし、ゲーム中にシステムメッセージ系に干渉しないとプログラムの結果を画面に出すことができません。
下準備として、ログを出せる環境を準備します。
※クラフトピアのアップデートをした際に設定が上書きされることがあります。設定したBepInEx.cfgのバックアップを取っておくことをおススメします。
BepInEx.cfgをメモ帳などで開き、以下のように設定を変更します
クラフトピアの本体を起動したときに、もう1つログなどが表示されているウインドウが表示されれば成功です。
このウインドウを閉じるとクラフトピアが強制終了します(終了時のセーブも行わない)。
特に設定をしないで使用するとクラフトピア実行時には何もおこりませんが、
それではエラーが出た時に困りますし、ゲーム中にシステムメッセージ系に干渉しないとプログラムの結果を画面に出すことができません。
下準備として、ログを出せる環境を準備します。
※クラフトピアのアップデートをした際に設定が上書きされることがあります。設定したBepInEx.cfgのバックアップを取っておくことをおススメします。
BepInEx.cfgをメモ帳などで開き、以下のように設定を変更します
- [Logging]の項目の「UnityLogListening」をtrue
- [Logging.Console]の項目の「Enabled」をtrue
クラフトピアの本体を起動したときに、もう1つログなどが表示されているウインドウが表示されれば成功です。
このウインドウを閉じるとクラフトピアが強制終了します(終了時のセーブも行わない)。
- クラフトピアのSteamWorkshopを開きます。
- 画面上部のワークショップの説明画面にある「詳細情報」ボタンを押します。
- GitHubに移動しますので、右上の「Code」(緑のボタン)から「Download ZIP」を選択し、ファイルを適当な場所にダウンロードします。
- ダウンロードしたファイルを適当な場所に解凍します(Craftopiaのゲームフォルダか、ModLoader(BepInEx)のあるフォルダが適当だと思います)
- 解凍したフォルダの「\Craftopia_OfficialSteamModTools-master\Mod_UploaderBinary\Version***\」(***は一番数字が新しいもの)にある「Mod_Uploader.exe」が本体です。
どこか使いやすい場所にショートカットでも作っておきましょう。
次に必要なファイルの参照設定を追加します。ソリューションエクスプローラーの「参照」の部分で右クリックで出てくる「参照の追加」をクリックします。
出てきたウインドウの右下の「参照」をクリックし、以下のファイルを選択、チェックボックスにチェックを入れます。
それぞれの場所は「Mod関連ファイルのフォルダ構造の理解」を参照してください。
このほかにも作成中のModで必要なものが出たらプロジェクトに追加をしていってください。
出てきたウインドウの右下の「参照」をクリックし、以下のファイルを選択、チェックボックスにチェックを入れます。
それぞれの場所は「Mod関連ファイルのフォルダ構造の理解」を参照してください。
このほかにも作成中のModで必要なものが出たらプロジェクトに追加をしていってください。
- BepInEx.dll
- 0Harmony.dll
- AD__Overcraft.dll
- UnityEngine.dll
- UnityEngine.CoreMolude.dll
Modの中身の記述を始めます。主なやることとしては以下のものがあります。
これが終わったらビルドを行います。
正常に設定ができていればエラーもワーニングもないはずです。
出力ファイル(Example.dll)をコピーし(出力場所はソリューション構成によって異なる)、\BepInEx\pluginsの中に貼り付けます。
他のModと混ざらないよう、pluginsの中に自作Mod用のフォルダを作り、そこにdllやreadme.txtなどを置くといいでしょう。
公開を行う前・公開しないModは\BepInEx\pluginsの中に置くことで動作します。(ダウンロードしてきたModも同様)
まずは公開する前に、自分のローカルで十分な動作確認とデバッグを行いましょう。
pluginsにdllを置いてクラフトピアを起動すると、ログウインドウに以下の表示が出てきます。うまく「Hello World」が表示されていれば成功です。
タイトル画面まで行くまでに結構なログが走るので、落ち着いてからスクロールバーで最初の方のログを確認しましょう。
- using ステートメントの設定
- BepInExの設定と割り込み位置の指定
- 処理の記述
using System; (他のSystem系は省略) using BepInEx; //これを追加 namespace Example{ [BepInPlugin("ModName", "DisplayModName", "1.0")] //引数はそれぞれ、Modの名称、Modの表示名、バージョン表記 //Modの名称が他のModと重複すると干渉するので、自分独自のユニークな名前を推奨。 //基底クラス[BaseUnityPlugin]を実装すること。 public class Class1:BaseUnityPlugin{ public void Awake(){ UnityEngine.Debug.Log("Hello, World!!"); } } } |
正常に設定ができていればエラーもワーニングもないはずです。
出力ファイル(Example.dll)をコピーし(出力場所はソリューション構成によって異なる)、\BepInEx\pluginsの中に貼り付けます。
他のModと混ざらないよう、pluginsの中に自作Mod用のフォルダを作り、そこにdllやreadme.txtなどを置くといいでしょう。
公開を行う前・公開しないModは\BepInEx\pluginsの中に置くことで動作します。(ダウンロードしてきたModも同様)
まずは公開する前に、自分のローカルで十分な動作確認とデバッグを行いましょう。
pluginsにdllを置いてクラフトピアを起動すると、ログウインドウに以下の表示が出てきます。うまく「Hello World」が表示されていれば成功です。
タイトル画面まで行くまでに結構なログが走るので、落ち着いてからスクロールバーで最初の方のログを確認しましょう。
まず、dnSpyを用いて、アイテム情報が入った変数を探し出します。"Item"という名前をヒントにSearchやAnalyzerを使って探しましょう。
経路は省略しますが、「Oc.Item.OcItemDataMng」クラスで定義されている「validItemDataList」(ItemData型)がそれです。
初期化が同クラスのOnUnityAwakeメソッドの冒頭で行われているのを確認してください。
経路は省略しますが、「Oc.Item.OcItemDataMng」クラスで定義されている「validItemDataList」(ItemData型)がそれです。
初期化が同クラスのOnUnityAwakeメソッドの冒頭で行われているのを確認してください。
取得したい変数が判ったら、この処理に割り込んで値を取得します。
割り込みにはHarmonyを使用します。Harmonyは簡単に言うとパッチを作成するためのライブラリ群です。詳細はここ*5を確認ください(英語)。
Harmonyは特定のメソッドの前(Prefix)、もしくは後ろ(Postfix)に処理を追加できます。
値を取得するには初期化の後に行う必要があるため、「OnUnityAwakeの後」「初期化後にOnUnityAwakeで必ず実行されるメソッドの前か後」に割り込ませます。
OnUnityAwake内のメソッドに割り込む場合、思っていた箇所以外で使用されていないかをAnalyzerで確認しておきましょう。
今回は、初期化の直後にある「Oc.Item.OcItemDataMng.SetUpCraftableItems()」メソッドに割り込みます。
割り込みにはHarmonyを使用します。Harmonyは簡単に言うとパッチを作成するためのライブラリ群です。詳細はここ*5を確認ください(英語)。
Harmonyは特定のメソッドの前(Prefix)、もしくは後ろ(Postfix)に処理を追加できます。
値を取得するには初期化の後に行う必要があるため、「OnUnityAwakeの後」「初期化後にOnUnityAwakeで必ず実行されるメソッドの前か後」に割り込ませます。
OnUnityAwake内のメソッドに割り込む場合、思っていた箇所以外で使用されていないかをAnalyzerで確認しておきましょう。
今回は、初期化の直後にある「Oc.Item.OcItemDataMng.SetUpCraftableItems()」メソッドに割り込みます。
まず、前回のもの(Class1)でusingステートメントに「HarmonyLib」を追加してください。
次にソリューションエクスプローラーでソリューションの下にあるExampleを右クリックをし、「追加⇒新しい項目」を選択します。
適当なクラス名を決めたら(ここではClass2とします)、リストの中から「クラス」を選択してください。
HelloWorldと同じように、ビルドしてModを更新しましょう。
クラフトピアを立ち上げた時に、ログにアイテムの一覧が出れば成功です。(タイトル画面が表示される前に出力されます。ログをさかのぼって確認してください。)
次にソリューションエクスプローラーでソリューションの下にあるExampleを右クリックをし、「追加⇒新しい項目」を選択します。
適当なクラス名を決めたら(ここではClass2とします)、リストの中から「クラス」を選択してください。
using System; (他のSystem系は省略) using HarmonyLib; //これを追加。ここではBepInExは不要 using Oc.Item; //割り込むクラスの名前空間を指定、このほかにも必要に応じてOcなどを追加する。 namespace Example{ [HarmonyPatch(typeof(OcItemDataMng), "SetupCraftableItems")] //割り込むクラスのタイプと割り込むメソッドを指定 //クラスの前に指定すること internal class Class2{ public static bool Prefix(ItemData[] ___validItemDataList){ //引数はプライベートメンバーの参照をしている。参照は「アンダーバー×3 + 変数名」 foreach(ItemData item in ___validItemDataList){ UnityEngine.Debug.Log($"ItemName {item.Id}:{item.DisplayName}"); } return true; //Prefixの返し値をfalseにすると、元のメソッド(この場合SetupCraftableItems)が実行されなくなる。 //言い換えると「Prefixで返し値をfalseにすると、Prefixが元メソッドを完全に上書きする」 //元のメソッドを利用する他のModがあると正常動作しなくなることがあるため、よほどでなければtrue推奨。 } } } |
クラフトピアを立ち上げた時に、ログにアイテムの一覧が出れば成功です。(タイトル画面が表示される前に出力されます。ログをさかのぼって確認してください。)
次にアイテムの情報を書き換えるModに改造します。石のつるはし(ID=56)の価格(int型)を書き換えてみましょう。
AccessTools.FieldRefAccessを用いてプライベートなメンバーを変更することができます。
引数は【AccessTools.FieldRefAccess<アクセスするインスタンスの型 , メンバーの型>(アクセスするインスタンス , メンバー名)】 です
書き換える内容についてはdnSpyであらかじめ確認をしておいてください。今回のものはItemData型のメンバーとして登録されています。
当たり前ですがメンバーの型やメンバー名を間違えると動きません。(インスタンスに関しても同様)(VS上ではエラーが出ず、動かしてみるまで判らない)
先ほどのクラス(Class2)のPrefixを次のように書き換えます。
今回はPostfixを使ってみましょう。SetupCraftableItemsメソッドは大したことをしてないので前でも後ろでも結果は変わりません。
先ほどまでと同様、ビルドしてpluginsに配置、クラフトピアを起動し石のつるはしの価格を確認しましょう。
クラフト画面を確認し、価格が9999になっていれば成功です。
失敗の場合、ゲーム起動時のログに赤文字のエラーが出ていることがあります。
AccessTools.FieldRefAccessを用いてプライベートなメンバーを変更することができます。
引数は【AccessTools.FieldRefAccess<アクセスするインスタンスの型 , メンバーの型>(アクセスするインスタンス , メンバー名)】 です
書き換える内容についてはdnSpyであらかじめ確認をしておいてください。今回のものはItemData型のメンバーとして登録されています。
当たり前ですがメンバーの型やメンバー名を間違えると動きません。(インスタンスに関しても同様)(VS上ではエラーが出ず、動かしてみるまで判らない)
先ほどのクラス(Class2)のPrefixを次のように書き換えます。
今回はPostfixを使ってみましょう。SetupCraftableItemsメソッドは大したことをしてないので前でも後ろでも結果は変わりません。
public static void Postfix(){ //今回validItemDataListは使ってないので引数不要。 //ただし、GetItemData_OrNull()内部で使用してるため、初期化後に実行する必要がある ItemData item = OcItemDataMng.Inst.GetItemData_OrNull(56); //ID56のアイテム情報を取得 ref int itemprice = ref AccessTools.FieldRefAccess<ItemData, int>(item, "price"); //価格を収納するメンバーpriceの場所を取得 itemprice = 9999; return; } |
クラフト画面を確認し、価格が9999になっていれば成功です。
失敗の場合、ゲーム起動時のログに赤文字のエラーが出ていることがあります。
※以下は義務ではありませんが、できるだけ対応するようにお願いします。
- アップロードするModは十分なデバッグを行い、最低でも自分の環境でエラーのないものを出すようにしてください。
- アップロードしてそのまま放置せず、たまにコメントを確認してバグ報告があったら対応してあげてください。
- 本体がバージョンアップされたら、自作Modの動作確認をもう一度行い、動かないようなら動くようにバージョンアップ対応してあげてください。
- 止むをえずサポートを停止する場合、そのことを説明文などに書いてあげてください。
(「更新停止」などと書いておく、もしくは動作確認のある最終バージョンを書いておく)
まず、アップロードする圧縮ファイルを作るための準備を行います。
適当な名前のフォルダを作成し、次のようなフォルダ構成を作ります。最低限必要なファイル以外は消しておきましょう(ショートカットなど)。
Modのdllは必ずpluginsかpatchersフォルダの下に置く必要があります。
適当な名前のフォルダを作成し、次のようなフォルダ構成を作ります。最低限必要なファイル以外は消しておきましょう(ショートカットなど)。
Modのdllは必ずpluginsかpatchersフォルダの下に置く必要があります。
\(Modを入れるフォルダ)---\plugins -+- Mod本体dll | +- 設定ファイル や readme等
できればModの動作や操作方法について記載された「Readme.txt」のような配布テキストを用意しておきましょう。
ポケットペア(公式)からMODの配布に関して、指定文章の記載が必要という指示があった場合*6は、該当の文章を配布テキストに記載します。
また、自身の免責に関する文章を書いておいてもいいかもしれません。(このModの動作による損害に関して一切の責任を負いません・・・のような)
ポケットペア(公式)からMODの配布に関して、指定文章の記載が必要という指示があった場合*6は、該当の文章を配布テキストに記載します。
また、自身の免責に関する文章を書いておいてもいいかもしれません。(このModの動作による損害に関して一切の責任を負いません・・・のような)
※同じファイルを再度アップロードするとModや情報が更新されます。
※上書きアップロードを行う時には、アップロード先を示した「ModInfo.txt」がModPathの階層に必要です。
無い場合は、自分のMODをサブスクライブし、該当のファイルを取得してください。
また、英語版の説明文は再アップされる内容で上書きされます。あらかじめ保存しコピペできるようにしておきましょう。
ModUploaderはSteamへのログインが必要なため、まずSteamを立ち上げておいてください。
次に、用意しておいた「Mod_Uploader.exe」を起動します。

起動したらそれぞれ必要な項目を埋めていきます。
フォルダの読み込み機能はないため、フォルダ名は手入力が必要です。
エクスプローラーのココをクリックして、フルパスをコピーし、該当部にペーストしましょう。

必要な項目の記入が終わったら、一番下にある「Upload」ボタンを押します。
しばらくすると一番下に「Upload Success」と出るのでこれでアップロードは完了です。
ただし、アップロード直後は「非公開」の状態ですので、設定が必要です。
次の項目で調整をしていきます。
※上書きアップロードを行う時には、アップロード先を示した「ModInfo.txt」がModPathの階層に必要です。
無い場合は、自分のMODをサブスクライブし、該当のファイルを取得してください。
また、英語版の説明文は再アップされる内容で上書きされます。あらかじめ保存しコピペできるようにしておきましょう。
ModUploaderはSteamへのログインが必要なため、まずSteamを立ち上げておいてください。
次に、用意しておいた「Mod_Uploader.exe」を起動します。

起動したらそれぞれ必要な項目を埋めていきます。
フォルダの読み込み機能はないため、フォルダ名は手入力が必要です。
エクスプローラーのココをクリックして、フルパスをコピーし、該当部にペーストしましょう。

項目 | 説明 |
---|---|
ModPath | MODの入っているパスを指定します。Modの入ったPluginsフォルダの一つ上のフォルダを指定します。 上のアップロード構成図の「modを入れるフォルダ」にあたるものを指定してください DLLを直接指定しないこと 指定フォルダ以下の余計なファイル・ショートカットは削除しておいてください(アップロードされてしまいます) |
ModName | ワークショップに表示されるModの名前です Steam言語設定の「英語」に収納されるため英名をおススメします。 アップロード後にも変更可能です |
ModDetails | ワークショップで選択した時に表示されるModの説明です。 Steam言語設定の「英語」に収納されるため、機械翻訳でもよいのでできれば英語での記述をおススメします。 アップロード後にも変更可能です |
ImagePath | ワークショップでのサムネイルを設定できます。設定すると下の四角にサムネイルが表示されます。 このサムネイルは大きさ固定のため大きい画像では大きく崩れますが、アップロード後のものは普通に表示されます アップロード後に追加・変更が可能です。 |
必要な項目の記入が終わったら、一番下にある「Upload」ボタンを押します。
しばらくすると一番下に「Upload Success」と出るのでこれでアップロードは完了です。
ただし、アップロード直後は「非公開」の状態ですので、設定が必要です。
次の項目で調整をしていきます。
先ほどアップロードされた説明は「言語:英語」に収納されています。(説明が英語のみの場合、あらゆる言語でここにあるタイトルと説明が表示されます)
言語をクリックすることで他言語(日本語を含む)の環境で見ている場合に個別に設定したタイトルや説明を表示することができるようになります。
アップローダーで英語で記入した場合は「言語:日本語」に変更し、日本語でのタイトルと説明を記入しましょう。
言語をクリックすることで他言語(日本語を含む)の環境で見ている場合に個別に設定したタイトルや説明を表示することができるようになります。
アップローダーで英語で記入した場合は「言語:日本語」に変更し、日本語でのタイトルと説明を記入しましょう。
説明画面に表示される画像や動画を追加したり変更することができます。
アップローダーでは1個しか画像を添付できませんでしたが、ここで追加の画像やユーチューブに投稿された動画を添付することができます。
アップローダーでは1個しか画像を添付できませんでしたが、ここで追加の画像やユーチューブに投稿された動画を添付することができます。
アップロードしたModに必要な前提Modがあればここで指定します。
ModUploaderを使用していれば自動的に「Craftopia ModLoader(BepInEx)」がついていますが、これに追加できます。
サブスクライブしたユーザーが指定したModをサブスクライブしていない時に警告を発することができます。
ModUploaderを使用していれば自動的に「Craftopia ModLoader(BepInEx)」がついていますが、これに追加できます。
サブスクライブしたユーザーが指定したModをサブスクライブしていない時に警告を発することができます。
コメントをかく