Mod開発 > メモ > CraftTweakerとの連携

「Mod開発/メモ/CraftTweakerとの連携」の編集履歴(バックアップ)一覧に戻る

Mod開発/メモ/CraftTweakerとの連携 - (2019/08/20 (火) 18:51:11) のソース

*CraftTweakerとの連携方法(メモ)
**目的
自分のModで加工機械を追加し、その機械のレシピをCraftTweakerに対応させたい。
バージョンはMC1.7.10、CraftTweaker 3.0.13を使用
&tt(){script.zs}内で
#highlight(){
import mods.mymod.MyMachine;
MyMachine.addRecipe(...);}
みたいに書けるようにしたい。

*ZenScriptのクラスを登録する

**Githubを見てみる
1.7.10のブランチもタグもなかったのでMC1.12.2のコードを見てみた

https://github.com/CraftTweaker/CraftTweaker/blob/ffb96eba30f7bc2b765414de72c53881d2117a53/CraftTweaker2-API/src/main/java/crafttweaker/api/recipes/IRecipeManager.java

-ZenScript内で参照させるクラスに@ZenClass("...")と@ZenRegisterをつける
-メソッドには@ZenMethodをつけIItemStackやIIndegrient[][]などで引数を受け取る
という方法を採っているのではないか
別途登録処理が必要なのか、@ZenReigsterアノテーションをつけるだけでいいのか、そもそも@ZenRegisterアノテーションがMC1.7.10に存在しているのかが不明(なさそう)


**Jarをデコンパイルして中を見てみた
MC1.7.10、CraftTweaker 3.0.13を使用

@ZenRegisterアノテーションはなかった
ZenClassの登録方法は多分以下の通り

***1. MineTweakerAPI.registerClass(Class annotatedClass)を呼び出す
ただしannotatedClassは@ZenClassアノテーションをつけたクラス

@ZenClassアノテーションをつけたクラスの中身の実装方法については別に書くつもり

***2. GlobalRegistry.registerNativeClass(Class<?> cls)が呼び出される
clsは1.のannotatedClass
clsはZenTypeNativeに変換され、GlobalRegistry.rootに登録される
ZenTypeNativeも詳細は不明だが、@ZenClass("mods.mymod.MyMachine")とアノテーションをつけておくと、ZenScript内のパッケージmods.mymodやクラスMyMachineとして扱ってくれるようになる、と思う

**minetweaker.modsにIC2、MFR、NEIとの連携の処理がある
&tt(){@ModOnly({"IC2"}})のように書くと、IC2が導入されているときしか使えなくなるようだ

&tt(){minetweaker.mods.ic2.machines.BlastFurnace}
クラスの宣言部分は
#highlight(java){{
@ZenClass("mods.ic2.BlastFurnace")
@ModOnly({"IC2"})
public class BlastFurnace {}}
となっていて、@ZenClassアノテーションがついていることが確認できる
中のメソッドは、
#highlight(java){{
@ZenMethod
public static void addRecipe(@NotNull IItemStack output, @NotNull IIngredient ingredient) {
  if(ingredient.getAmount() < 0) {
    MineTweakerAPI.logWarning("invalid ingredient: " + ingredient + " - stack size not known");
  }
  else {
    MineTweakerAPI.apply(new MachineAddRecipeAction("blast furnace", Recipes.blastfurance, MineTweakerMC.getItemStacks(new IItemStack[]{output}), (NBTTagCompound)null, new IC2RecipeInput(ingredient)));
}
}}
のようになっていて、@ZenMethodアノテーションがついて、IItemStackやIIngredientを受け取っている。
そして&tt(){**Action}のようなオブジェクトをつくってapplyしている。この&tt(){**Action}については調査中
IItemStackやIIngredientをItemStackなどに変換するメソッドも存在するので([[https://docs.blamejared.com/ja/#Dev_Area/Ingredients/]])、&tt(){**Action}を使わなくても良いように思える

**ClassRegistry
&tt(){minetweaker.mods.ic2.ClassRegistry}の中身は以下のようになっている
#highlight(java){{
public class ClassRegistry {
   public static void getClasses(List arg) {
      arg.add(Crop.class);
      arg.add(CropsConfig.class);
      arg.add(GrowthRequirements.class);
      arg.add(SyntheticCrop.class);
      arg.add(IngredientExpansion.class);
      arg.add(ItemExpansion.class);
      arg.add(IC2BracketHandler.class);
      arg.add(IC2ExplosionWhitelist.class);
      arg.add(BlastFurnace.class);
      arg.add(BlockCutter.class);
      arg.add(Canner.class);
      arg.add(Compressor.class);
      arg.add(Extractor.class);
      arg.add(FluidHeatGenerator.class);
      arg.add(Macerator.class);
      arg.add(MatterAmplifier.class);
      arg.add(MetalFormer.class);
      arg.add(OreWasher.class);
      arg.add(Recycler.class);
      arg.add(ScrapBox.class);
      arg.add(SemiFluidGenerator.class);
      arg.add(ThermalCentrifuge.class);
   }
}
}}
&tt(){getClasses()}という&tt(){List}を受け取りそこに@ZenClassアノテーションのついたクラスをいれる静的メソッドがある。

この&tt(){ClassRegistry}を&tt(){MineTweakerAPI.registerClassRegistry}(Class registryClass, String
description)にわたすと、自動でそれぞれのZenClassクラスについて&tt(){MineTweakerAPI.registerClass(Class annotatedClass)}を呼び出してくれるようだ。
なおdescriptionはログの出力にだけ使われるようだ

*&tt(){IUndoableAction}について調べる
&tt(){IUndoableAction}の内容は以下の通り
#highlight(java){{
package minetweaker;

public interface IUndoableAction {
   void apply();

   boolean canUndo();

   void undo();

   String describe();

   String describeUndo();

   Object getOverrideKey();
}
}}
例えば&tt(){MyMachineAddRecipeAction}クラスで&tt(){IUndonableAction}を実装して、
#highlight(java){{
MineTweakerAPI.apply(new MyMachineAddRecipeAction(arg1, arg2...));}}
のようにすると、いろいろして&tt(){MTTweaker}クラスの&tt(){apply(IUndoableAction action)}メソッドが呼び出され、最終的に&tt(){MyMachineAddRecipeAction#apply()}が実行される。

&tt(){MTTweaker}はログの出力や履歴の表示などをしてくれるようなので、Zenスクリプトから呼び出されるメソッドは&tt(){IUndonableAction}を使って実装する方が良いと思う。