Advertisement
hevohevo

FML(Forge#1180)の個人的な解析メモ

Aug 11th, 2014
279
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.41 KB | None | 0 0
  1. # Minecraft Forge(#1080) Event サイクル。たぶんマイクラ1.7系共通
  2.  
  3. - NOINIT("Uninitialized",null),
  4. - LOADING("Loading",null),
  5. - CONSTRUCTING("Constructing mods",FMLConstructionEvent.class),
  6. - PREINITIALIZATION("Pre-initializing mods", FMLPreInitializationEvent.class),
  7. - INITIALIZATION("Initializing mods", FMLInitializationEvent.class),
  8. - POSTINITIALIZATION("Post-initializing mods", FMLPostInitializationEvent.class),
  9. - AVAILABLE("Mod loading complete", FMLLoadCompleteEvent.class),
  10. - SERVER_ABOUT_TO_START("Server about to start", FMLServerAboutToStartEvent.class),
  11. - SERVER_STARTING("Server starting", FMLServerStartingEvent.class),
  12. - SERVER_STARTED("Server started", FMLServerStartedEvent.class),
  13. - SERVER_STOPPING("Server stopping", FMLServerStoppingEvent.class),
  14. - SERVER_STOPPED("Server stopped", FMLServerStoppedEvent.class),
  15. - ERRORED("Mod Loading errored",null)
  16.  
  17.  
  18. ## ゲーム本体の起動
  19.  
  20. - NOINIT("Uninitialized",null),
  21. - LOADING("Loading",null),
  22.  
  23. ## MOD群の初期化
  24.  
  25. - CONSTRUCTING("Constructing mods",FMLConstructionEvent.class),
  26. - PREINITIALIZATION("Pre-initializing mods", FMLPreInitializationEvent.class),
  27. - INITIALIZATION("Initializing mods", FMLInitializationEvent.class),
  28. - POSTINITIALIZATION("Post-initializing mods", FMLPostInitializationEvent.class),
  29. - AVAILABLE("Mod loading complete", FMLLoadCompleteEvent.class),
  30.  
  31. ## サーバースタート
  32.  
  33. - SERVER_ABOUT_TO_START("Server about to start", FMLServerAboutToStartEvent.class),
  34. - SERVER_STARTING("Server starting", FMLServerStartingEvent.class),
  35. - SERVER_STARTED("Server started", FMLServerStartedEvent.class),
  36.  
  37. ## サーバーストップ
  38.  
  39. - SERVER_STOPPING("Server stopping", FMLServerStoppingEvent.class),
  40. - SERVER_STOPPED("Server stopped", FMLServerStoppedEvent.class),
  41. - ERRORED("Mod Loading errored",null);
  42.  
  43. # 以下、modの初期化部分について重点的に調べる。つまりForgeModLoaderの部分
  44.  
  45. # 各Modの情報は、ModContainerオブジェクトに格納される
  46.  
  47. - cpw.mods.fml.common.ModContainer
  48. - Mod名とかMod依存関係とか
  49. - boolean registerBus(EventBus, LoadController)で、LoadControllerのEventBusに自身の初期化メソッドを追加
  50.  
  51. # EventBus は、com.google.common.eventbus を使っている。
  52.  
  53. - googleさんの提供するイベント駆動基盤
  54. - http://docs.guava-libraries.googlecode.com/git-history/v10.0/javadoc/com/google/common/eventbus/package-summary.html
  55. - 日本語で解説 http://cco.hatenablog.jp/entry/20111210/1323509513
  56. - ``@Subscribeアノテーションを使うことでevent handlerとなる公開メソッドを実装することができます。イベントである引数は必ず1つのみであることに注意が必要です。``
  57. - 日本語で解説 http://blog.kengo-toda.jp/entry/20111006/1317907239
  58. - ``リスナーはどのようなクラスでもよく、メソッドを@Subscribeアノテーションで修飾するだけで使えます。``
  59. - ``リスナーが@Subscribeで修飾されたメソッドを複数個持っている場合、これらが実行される順番は環境依存となります。``
  60. - 上記を読んで理解した内容
  61. - Busにあらかじめレシーバーを複数登録(bus.register(receiver))しておく。
  62. - レシーバーには@Subscribeをつけたメソッド(引数は1つのobject)を定義しておく。メソッド名は問わない。ただし複数あるとその実行順序は環境依存となるので注意
  63. - Busに対してメッセージをポスト(bus.post(object))すると、そのobjectのタイプに応じたレシーバーのSubscribeメソッドを実行
  64. - ただし、同じタイプのオブジェクトを受け取るようなレシーバーを複数登録してしまうと、その実行順序は環境依存
  65. - (感想)これは、シンプルで使いやすそう!
  66.  
  67.  
  68. # LoadController について
  69.  
  70. - cpw.mods.fml.common.LoadController
  71. - イベント駆動部分の主体。以下private変数を一部抜粋
  72. - ```private masterChannel = new EventBus("FMLMainChannel");```、 LoadControllerが自身の中で@subscribeされているメソッドの駆動用チャンネル。EventBusで実装
  73. - ```private ImmutableMap eventChannels<modid, そのmodのEventBus>```、 各Modの初期化メソッド駆動用チャンネルを集めたもの。Mapで実装
  74. - LoadController内で@Subscribe定義されているもの(メッセージがポストされたらどちらかを実行)
  75. - ```public void buildModList(FMLLoadEvent event)```
  76. - 有効なModごとのEventBus作って、eventChannelに登録、各Modの状態リスト作成、リソースパックにModを登録(?)
  77. - ```public void propogateStateMessage(FMLEvent stateEvent)```
  78. - 外部からきたメッセージを振り分ける。"FMLPreInitializationEvent"なら上記のModList作成を行う。それ以外なら有効なModContainer全部にメッセージ伝達
  79. - 有効なModContainer全部にメッセージ伝達するメソッド ```private void sendEventToModContainer(FMLEvent stateEvent, ModContainer mc)```
  80. - Mod依存関係や、バージョンの解決などを行っている。
  81.  
  82.  
  83. # まとめ
  84.  
  85. ## 階層型のイベント駆動になっており。興味深い。
  86.  
  87. - 「LoadController」の挙動 (EventBusで実装されたイベント駆動)
  88. - "FMLPreInitializationEvent"受信: 有効なModリストを作ったり、有効ModごとにEventBus作ってMapに保存。そして以下を実行
  89. - それ以外受信: 有効なModContainer全てへメッセージを伝播(というイメージ)
  90. - 各「ModContainer」の挙動 (イメージ、実際はLoadControllerがeventChannelsを使って処理)
  91. - 何らかのメッセージを受信: 自身が依存しているModや必要バージョンなどを確認し、依存ModがまだERRORED状態なら自身もERROREDとなる
  92. - "Skipping event %s and marking errored mod %s since required dependency %s has errored"
  93. - 依存関係等問題なければ、自身の初期化用EventBusに対してメッセージを伝播。
  94. - 各「Modの初期化EventBus」の挙動 (EventBusで実装されたイベント駆動)
  95. - 何らかのメッセージを受信: メッセージにより反応するレシーバメソッドをすべて実行。つまり対応する初期化メソッドを全て実行。ただし、複数あるとき実行順は環境依存
  96.  
  97. ## つまりわかりやすく言うと
  98.  
  99. - 100個のModがあったら、どのように初期化作業が進むか。
  100. - "FMLPreInitializationEvent"メッセージ来た=> 有効なModリストなどの作成後、100個のModにメッセージ送信。それぞれのModは対応する初期化メソッド実行
  101. - "FMLInitializationEvent"メッセージ来た=> 100個のModにメッセージ送信。それぞれのModは対応する初期化メソッド実行
  102. - "FMLPostInitializationEvent"メッセージ来た=> 100個のModにメッセージ送信。それぞれのModは対応する初期化メソッド実行
  103.  
  104. ## 未解読、謎の部分
  105.  
  106. - 依存関係により初期化失敗したModの後処理はどうなっているのか?
  107. - たぶん、"FMLPreInitializationEvent"などのメッセージを発信するエンジンのコードを読まないと・・・力尽きて今日は無理です。
  108.  
  109. ## 感想
  110.  
  111. - どんなModが追加されるのかわからないわけで、各Modの初期化を完全に正常に行うことをある程度あきらめた設計に思える。
  112. - つまり、「初期化せよ」というメッセージは送るが、後はそれぞれのModのメソッドにまかせた!という設計。
  113.  
  114. --------------------------------------------------------------------------とりあえずここまで、以下はメモ書き
  115.  
  116.  
  117. # 基本は、アノテーションを宣言しつつ既存のイベントメソッド上書き/追加
  118.  
  119. ## @Eventhandler アノテーション
  120.  
  121. - 例1:FMLInitializationEvent イベントに初期化メソッドを複数追加
  122.  
  123. ```
  124. @EventHandler
  125. public hoge(FMLInitializationEvent, event);
  126.  
  127. @EventHandler
  128. public init(FMLInitializationEvent, event);
  129.  
  130. @EventHandler
  131. public load(FMLInitializationEvent, event);
  132. ```
  133.  
  134. - "FMLInitializationEvent"メッセージが来てイベント駆動したときに、上記3つのメソッド全てが実行される。ただし、実行順序は環境依存。
  135.  
  136. # とはいえ
  137.  
  138. Forge的には、以下の名前のメソッドを一つずつ追加することを推奨しているようだ。
  139.  
  140. - FMLPreInitializationEvent
  141. - public void preInit(FMLPreInitializationEvent event) { }
  142. - FMLInitializationEvent
  143. - public void init(FMLInitializationEvent event) {}
  144. - これについては、 load()を使っている人も多い模様。
  145. - FMLPostInitializationEvent
  146. - public void postInit(FMLPostInitializationEvent event) {}
  147.  
  148.  
  149. ## cpw.mods.fml.common.Mod より抜粋
  150.  
  151. ```
  152. /**
  153. * Marks the associated method as handling an FML lifecycle event.
  154. * The method must have a single parameter, one of the following types. This annotation
  155. * replaces the multiple different annotations that previously were used.
  156. *
  157. * Current event classes. This first section is standard lifecycle events. They are dispatched
  158. * at various phases as the game starts. Each event should have information useful to that
  159. * phase of the lifecycle. They are fired in this order.
  160. *
  161. * These suggestions are mostly just suggestions on what to do in each event.
  162. * <ul>
  163. * <li> {@link FMLPreInitializationEvent} : Run before anything else. Read your config, create blocks,
  164. * items, etc, and register them with the {@link GameRegistry}.</li>
  165. * <li> {@link FMLInitializationEvent} : Do your mod setup. Build whatever data structures you care about. Register recipes,
  166. * send {@link FMLInterModComms} messages to other mods.</li>
  167. * <li> {@link FMLPostInitializationEvent} : Handle interaction with other mods, complete your setup based on this.</li>
  168. * </ul>
  169. * <p>These are the server lifecycle events. They are fired whenever a server is running, or about to run. Each time a server
  170. * starts they will be fired in this sequence.
  171. * <ul>
  172. * <li> {@link FMLServerAboutToStartEvent} : Use if you need to handle something before the server has even been created.</li>
  173. * <li> {@link FMLServerStartingEvent} : Do stuff you need to do to set up the server. register commands, tweak the server.</li>
  174. * <li> {@link FMLServerStartedEvent} : Do what you need to with the running server.</li>
  175. * <li> {@link FMLServerStoppingEvent} : Do what you need to before the server has started it's shutdown sequence.</li>
  176. * <li> {@link FMLServerStoppedEvent} : Do whatever cleanup you need once the server has shutdown. Generally only useful
  177. * on the integrated server.</li>
  178. * </ul>
  179. * The second set of events are more specialized, for receiving notification of specific
  180. * information.
  181. * <ul>
  182. * <li> {@link FMLFingerprintViolationEvent} : Sent just before {@link FMLPreInitializationEvent}
  183. * if something is wrong with your mod signature</li>
  184. * <li> {@link IMCEvent} : Sent just after {@link FMLInitializationEvent} if you have IMC messages waiting
  185. * from other mods</li>
  186. * </ul>
  187. *
  188. * @author cpw
  189. *
  190. */
  191. ```
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement