ikasabaが勝手に編集するRimWorldのwiki

Zhentar Introduction to PatchOperation : Zhentarのパッチング入門

written by Zhentar
translated by oramu
元記事:https://gist.github.com/Zhentar/4a1b71cea45b9337f7...


パッチングによってDefs全体をコピーせずに編集することができるようになる11の新たな操作が可能となりました。これによってmod間の互換性が大幅に向上します - つまり2つのmodが同じDefの異なる部分を干渉することなく修正できるのです。このガイドでは、利用可能な各操作の基本についてのみ説明します。

パッチはmodフォルダの "Patches"という名前のサブフォルダ("MyMod\Defs"や "MyMod\Textures"と同じように "MyMod\Patches"など)にxmlファイルとして保存されます。Example.

各パッチ操作には "xpath"ノードがあり、これでその操作が作用するxmlノードのxpathセレクタを指定する必要があります。このガイドはxpathチュートリアルではありません。 ですからあなたがxpathを知らなくても、問題として扱いません。しかしminimurgleならあなたを助けてくれます!(元記事:https://ludeon.com/forums/index.php?topic=32785.0

操作の説明のために、以下のシンプルなサンプルdefを例に使うこととします。

def:
<DesignationCategoryDef>
  <defName>ExampleCategory</defName>
  <label>Example</label>
  <specialDesignatorClasses>
    <li>Designator_Cancel</li>
  </specialDesignatorClasses>
</DesignationCategoryDef>

そしてこれから用いる例でのxpathセレクタでは上記の"specialDesignatorClasses"ノードを指定することとします。

パッチ操作

基本操作

次の4つが基本的な操作となります。:Add(追加), Insert(挿入), Remove(削除), Replace(置換)

PatchOperationAdd
(xpathセレクタによって)指定されたノードに子ノード(訳注:原文は child。サブノード・下層ノード)を追加します。

code:
<Operation Class="PatchOperationAdd">
  <xpath>*/DesignationCategoryDef[defName = "ExampleCategory"]/specialDesignatorClasses</xpath>
  <value>
    <li>ZhentarExample.ExampleDesignator</li>
  </value>
</Operation>

この操作によってサンプルdefは次のように編集されます。

result:
<DesignationCategoryDef>
  <defName>ExampleCategory</defName>
  <label>Example</label>
  <specialDesignatorClasses>
    <li>Designator_Cancel</li>
    <li>ZhentarExample.ExampleDesignator</li>
  </specialDesignatorClasses>
</DesignationCategoryDef>


PatchOperationInsert
指定されたノードに兄弟ノード(訳注:原文はsibling。階層が同じ・並列関係にあるノード)を追加します。

code:
<Operation Class="PatchOperationInsert">
  <xpath>*/DesignationCategoryDef[defName = "ExampleCategory"]/specialDesignatorClasses</xpath>
  <value>
    <description>Pointless example designators.</description>
  </value>
</Operation>

この操作によってサンプルdefは次のように編集されます。

result:
<DesignationCategoryDef>
  <defName>ExampleCategory</defName>
  <label>Example</label>
  <specialDesignatorClasses>
    <li>Designator_Cancel</li>
  </specialDesignatorClasses>
  <description>Pointless example designators.</description>
</DesignationCategoryDef>

PatchOperationRemove
指定されたノードを削除します。(訳注:指定ノード内の子ノードも削除される)

code:
<Operation Class="PatchOperationRemove">
  <xpath>*/DesignationCategoryDef[defName = "ExampleCategory"]/specialDesignatorClasses</xpath>
</Operation>

この操作によってサンプルdefは次のように編集されます。

result:
<DesignationCategoryDef>
  <defName>ExampleCategory</defName>
  <label>Example</label>
</DesignationCategoryDef>

PatchOperationReplace
指定されたノードを置換します。

code:
<Operation Class="PatchOperationReplace">
  <xpath>*/DesignationCategoryDef[defName = "ExampleCategory"]/specialDesignatorClasses</xpath>
  <value>
    <specialDesignatorClasses/>
  </value>
</Operation>

この操作によってサンプルdefは次のように編集されます。

result:
<DesignationCategoryDef>
  <defName>ExampleCategory</defName>
  <label>Example</label>
  <specialDesignatorClasses/>
</DesignationCategoryDef>
属性操作
属性(Attribute)に対しては、Add(追加)、Set(設定)、およびRemove(削除)という3つの操作があります。
PatchOperationAttributeAdd と PatchOperationAttributeSet はともに属性を追加し指定された値に設定します。異なるのは、Addでは属性がまだ存在しない場合にのみ値を設定する一方で、Setはすでに存在する値を上書きする点です。

code:
<Operation Class="PatchOperationAttributeSet">
  <xpath>*/DesignationCategoryDef[defName = "ExampleCategory"]/specialDesignatorClasses</xpath>
  <attribute>ExampleAttribute</attribute>
  <value>ExampleValue</value>
</Operation>

この操作によってサンプルdefは次のように編集されます。

result:
<DesignationCategoryDef>
  <defName>ExampleCategory</defName>
  <label>Example</label>
  <specialDesignatorClasses ExampleAttribute="ExampleValue">
    <li>Designator_Cancel</li>
  </specialDesignatorClasses>
</DesignationCategoryDef>


PatchOperationAttributeRemove
属性を削除します。サンプルdefにはもとから属性がありませんので、今回は想像にお任せするということで・・・
高度な操作
最後に、4つのより高度な操作を紹介しておきます。
PatchOperationAddModExtensionPatchOperationSetNamePatchOperationSequence そして PatchOperationTest です。

PatchOperationAddModExtension はまさにその名の通りで、ModExtensionを追加します。ModExtensionがなにかということについては・・・  別のガイドに委ねます。

PatchOperationSetName はノード名を別の名前に変えます。この操作はパッチの完結性のために取り入れられただけで実用例がありません。

PatchOperationSequence と PatchOperationTest は件付きでパッチを実行するために使用することができます。これは同じ要素を2回追加することを防ぐために使用できるので、modの互換性向上に役立ちます。
PatchOperationSequence はリスト内の各操作を順番に行い、エラーがあれば中止します。
PatchOperationTest は単純にxpathセレクタが任意の要素と一致するかどうかを判断するだけです。

次の例はcostList要素が存在しない場合は追加するコードです。

code:
<Operation Class="PatchOperationSequence">
  <success>Always</success>
  <operations>
    <li Class="PatchOperationTest">
      <xpath>*/ThingDef[defName = "DiningChair"]/costList</xpath>
      <success>Invert</success>
    </li>
    <li Class="PatchOperationAdd">
      <xpath>*/ThingDef[defName = "DiningChair"]</xpath>
      <value>
        <costList />
      </value>
    </li>
  </operations>
</Operation>
(訳注:PatchOperationSequence を開始。PatchOperationTestでcostListをチェック。<success>Invert</success>で成否をひっくり返してPatchOperationAddに繋げている)>

パッチングテクニック

このセクションではいくつかのより高度なテクニックが適用できる状況について説明します。

次の例をサンプルにします。
def:
<Defs>
  <BlahDef Name="BlahBase" Abstract="True">
    <label>Blah</label>
  </BlahDef>
  <BlahDef>
    <defName>Zip<defName>
    <bleh>50<bleh>
  </BlahDef>
  <BlahDef>
    <defName>Zop<defName>
    <bleh>50<bleh>
  </BlahDef>
  <BlahDef>
    <defName>Zap<defName>
    <bleh>50<bleh>
  </BlahDef>
</Defs>
(訳注:このサンプルさっぱりわかりません。意味のない単なるサンプルということでしょうか?)>
Abstracts要素へのパッチング
LocalInjuryBaseやBuildingBaseのようなAbstract要素にパッチするにはどうしたらいいのでしょう?  明らかにxpathにはいくつかの修正が必要になります。上記のBlahBaseに <category>Item</category> を追加してみましょう。

code:
<Operation Class="PatchOperationAdd">
  <xpath>*/BlahDef[@Name="BlahBase"]</xpath>
  <value><category>Item</category></value>
</Operation>

結果:

result:
<Defs>
  <BlahDef Name="BlahBase" Abstract="True">
    <label>Blah</label>
    <category>Item</category>
  </BlahDef>
  <BlahDef>
    <defName>Zip<defName>
    <bleh>50<bleh>
  </BlahDef>
  <BlahDef>
    <defName>Zop<defName>
    <bleh>50<bleh>
  </BlahDef>
  <BlahDef>
    <defName>Zap<defName>
    <bleh>50<bleh>
  </BlahDef>
</Defs>

[@Name="BlahBase"] セレクタでName属性がBlahDef にあるかテストし、そうであればその属性値がBlahBaseであるかテストしています。
複数選択
複数のdefに同じことをする場合、xpathを一つのパッチに集約できることを知っていましたか?
下に示した例では3つのBlahDefのblehの値を 20に設定し直します。

code:
<Operation Class="PatchOperationReplace">
  <xpath>*/BlahDef[defName="Zip" or defName="Zop" or defName="Zap"]/bleh</xpath>
  <value><bleh>20</bleh></value>
</Operation>

結果:

rewsult:
<Defs>
  <BlahDef Name="BlahBase" Abstract="True">
    <label>Blah</label>
  </BlahDef>
  <BlahDef>
    <defName>Zip<defName>
    <bleh>20<bleh>
  </BlahDef>
  <BlahDef>
    <defName>Zop<defName>
    <bleh>20<bleh>
  </BlahDef>
  <BlahDef>
    <defName>Zap<defName>
    <bleh>20<bleh>
  </BlahDef>
</Defs>

or演算子がどのようにつかわれているかに注目してください。
3つのパッチ操作を1つに集約することはmodのロード時間に劇的な効果をもたらします。というのも、ゲームプログラムはxmlデータベースを一回通過するだけで済むからです。

記事作成:oramu

誤字脱字誤訳のほか、問題がありましたら、記事作成者oramuまでご一報いただければ対処いたします。
コメントをしていただくか、お手数ですがDicord鯖「RIMMOD相談所」までお願いいたします。

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

メンバーのみ編集できます

メンバー募集!