Extend with JavaScript

Nekopanda edited this page May 2, 2015 · 15 revisions

スクリプトによる拡張

航海日誌拡張版1.6.0から外部スクリプトによる拡張が実装されました。同時に艦娘一覧などの一部のテーブルはスクリプトによる実装になりました。航海日誌拡張版はJavaScriptで拡張できます。

拡張可能なところ

  1. テーブルの項目を増やす
  2. テーブルのデザインを変える
  3. データ受信時に処理をする

基本的な使い方

logbook.jarと同じフォルダにあるscriptフォルダの下にスクリプトを置くと自動的に読み込まれます。スクリプトのファイル名は、どこに対する拡張かによって決まっています。

艦娘一覧テーブルなどは、ほぼすべての表示項目がスクリプトで生成されています。また、テーブル項目の色などのデザインもスクリプトで制御されています。デフォルトで用意されているスクリプトを見ればだいたい分かると思います。

注意点をいくつか

  • スクリプトファイルはUTF-8で保存してください。UTF-8でないとjava.nio.charset.MalformedInputExceptionが発生します。

  • 航海日誌拡張版に同梱してあるスクリプトは今後のアップデートで変更される可能性があります。新しく列を追加するような場合は、なるべく新しくjsファイルを作るようにしてください。

  • 例外を吐く場合は、logs/script.logに例外情報が出力されるのでそれを見てください。JavaScript中で例外が発生した場合はスタックトレースに<eval>:62のように行数が表示されます。ちなみに、このファイルは航海日誌拡張版を起動する度に前のログが削除されます。

スクリプトのファイル名

スクリプトのファイル名は以下のようになります。各スクリプトについては下の方に解説があります。

  • テーブルプリフィックス_*.js : テーブルの項目を増やすスクリプト
    例: ship_hoge.js, drop_hage.js, ...
  • テーブルプリフィックスstyle.js : テーブルのデザインを変えるスクリプト
    例: shipstyle.js, dropstyle.js, ...
  • update_*.js : データ受信時に処理をするスクリプト
    例: update_hoge.js, update_bar.js, ...

テーブルプリフィックスは例えば艦娘一覧テーブルだったらship、ドロップ報告書だったらdropのようにテーブルごとに決まっています。*は任意の文字列です。

テーブル名 テーブルプリフィックス
ドロップ報告書 drop
艦娘一覧 ship
装備一覧 item
遠征一覧 mission
グループエディタ shipgroup
開発報告書 createitem
建造報告書 createship
遠征報告書 missionresult
任務一覧 quest
資材チャート resource

JavaScriptの実行について

航海日誌拡張版はJava8に実装されているJavaScriptエンジンNashornを使って実行します。 JavaScriptからJavaへのアクセス方法は、The Nashorn Java APIによくまとまっています。(日本語は知らん)

テーブルの項目を増やす

スクリプトでテーブルのカラムを増やすことができます。

現在対応しているテーブルと、スクリプトが実装すべきインターフェースは以下の通り

テーブル スクリプトが実装すべきインターフェース
ドロップ報告書 logbook.scripting.BattleLogListener
艦娘一覧 logbook.scripting.ShipItemListener
装備一覧 logbook.scripting.ItemInfoListener
遠征一覧 logbook.scripting.MissionListener
任務一覧 logbook.scripting.QuestListener

例: 艦娘一覧への「改造可能」列の追加

航海日誌拡張版に付属のスクリプト ship_remodel.js を例に説明します。このスクリプトは艦娘が改造可能かどうかの列を艦娘一覧テーブルに追加します。以下、このスクリプトの全文です。コメントは説明のために追加しました。

load("script/utils.js");
function header() {
     return [ "改造可能" ];
}
function begin(specdiff) { }
function body(ship) {
    var afterlv = ship.shipInfo.afterlv; // ※1
    var canRemodel = (afterlv > 0) && (ship.lv >= afterlv);
    return toComparable([ canRemodel ? "可能" : null ]);
}
function end() { }

JavaのインターフェースをJavaScriptで実装するにはそのインターフェースの全てのメソッドをグローバルスコープの関数として定義します。ShipItemListenerインターフェースには4つのメソッド(header(),begin(),body(),end())があるので、スクリプトにはこの全てのメソッドを定義する必要があります。ただし、本当に重要なのはテーブルの列ヘッダーを返すheader()と、各レコードに対する表示内容を返すbody()の2つで、begin(),end()は特にやることがなければ空でOKです。

header()は、追加する列のヘッダーを配列で返します。body()ShipDtoを引数に取り、その艦娘が改造可能かを計算して、返しています。

渡されたオブジェクトからのデータの取り出し方法は、大きく以下の2つの方法があります。

  1. 航海日誌がJSONから取得済みのデータをオブジェクト(ここではShipDtoなど)から取り出す
  2. JSONを取り出して自分で見に行く

上記例は1の方法で取得しています。どんなデータが取り出せるかなどはJavadocを参照してください。

上記例では使っていませんが、航海日誌が取得していないデータなどはJSONから取り出す必要があります。ship.getJson()でJSONに直接触れます。艦これのJSONの仕様はAndanteさんのドキュメントを参照してください。ship.getJson()で取得できるJSONは、api_port/portapi_shipです。

※1の行で、ship.shipInfo.afterlvとありますが、これはship.getShipInfo().getAfterlv()と同じです(NashornのJava APIにより短縮形が書けるようになっています。)。同じように、JSONにアクセスするときはjson.getJsonObject("hoge")などとする必要はなく、json.hogeで直接アクセスできます。

  • 注意点1: body()の戻り値はComparable[]です。上のスクリプトではtoComparable()script/utils.jsで定義されています)でJavaScriptの配列からJavaの配列に変換していますが、実はJavaScriptの配列をそのまま返しても動きます。ただし、現在のNashornエンジンだとJavaScriptの配列をそのまま返すと型変換によりかなり遅くなることが分かっています。toComparable()を使ってJavaの配列に変換してから返すようにしてください。

  • 注意点2: JavaScriptによる実装はJavaに比べてかなり遅いです。特にJavaScriptの配列とJavaの配列の相互変換(Java.to()など)はかなり遅いようです。遅いコードを走らせてしまうと、GUIがもっさりするようになったり、戦闘履歴のロードが終わらなくなってしまうので(マジで!)、気をつけてください。

例: ドロップ報告書への対空カットインの追加

ドロップ報告書に対空カットインを追加するサンプルが templates\samples\drop_taiku_cutin.js にあります。

GlobalContext

ユーザのゲーム情報のほとんどはGlobalContextから取得できます。引数で渡されたデータだけでなく、GlobalContextからもデータを取得して表示することができます。

スクリプトの反映タイミング

スクリプトは航海日誌動作中に動的に読み込まれるので、スクリプトを変更した場合、次にテーブルの再読み込みが走った時に反映されます。ただし、起動中のヘッダーの変更には対応していないため、航海日誌が起動後最初に読み込んだヘッダーは、航海日誌が再起動するまで変更できません。

また、ドロップ報告書だけは、戦闘履歴のデータ量が多いため起動時のデータベースロード時にスクリプトが実行されます。動作中にスクリプトの変更を反映したい場合は、ドロップ報告書の操作データベースを再読み込みでデータベースをロードしなおしてください。

スクリプトの実行順

テーブル列の初期位置はスクリプトの実行順で決まります。スクリプトの実行順はスクリプトの名前順になります。例えば、ship_a.js, ship_b.js, ship_c.jsがあった場合、ship_a.jsship_b.jsship_c.jsの順に実行されます。航海日誌拡張版付属の艦娘一覧テーブル用スクリプトは以下のようになっています。

実行順 スクリプト名 内容
1 ship__1basic.js ソート順やレベルなどの基本項目
2 ship__2slot.js 装備や搭載数
3 ship__3status.js 能力値
4 ship_power.js 夜戦火力など
5 ship_remodel.js 改造可能か

上の3つはアンダーバー(_)を2つ重ねていますが、これは追加したスクリプトの項目が基本項目に割り込まないようにするためです。

列情報の保存

航海日誌拡張版はテーブルの列幅や列の順番などを記憶しています。このとき、列ヘッダーをキーとして使っています。なので、同じヘッダーの列が複数あると正しく記憶できません。これを回避するために、明示的にその列のキーを指定することができます。例えば、ship__1basic.jsheader()にある"燃料#現在の燃料"は、表示されるヘッダーは"燃料"ですが、列情報を保存するためのキーは"現在の燃料"です。このようにヘッダーを"表示名#キー"とすることでキーを明示的に指定できます。重複のありそうな列はキーを明示的に指定してください。

テーブルのデザインを変える

TableItemCreatorをスクリプトで実装することで、テーブルのデザインを変えることができます。書き方はscript\shipstyle.jsを参照してください。create()でテーブルの1行分に相当するTableItemを作って返します。dataで渡されるのは1行分の表示内容(Comparable[])ですが、data[0].get()でその行に対応するデータオブジェクトを取得できることがあります。

対応するテーブルと取得可能なデータオブジェクトについては以下の通り

テーブル名 data[0].get()で取得できるデータ
ドロップ報告書 BattleResultDto
艦娘一覧 ShipDto
装備一覧 ItemInfo
遠征一覧 MissionDto
任務一覧 QuestDto
建造報告書 GetShipDto
開発報告書 CreateItemDto
遠征報告書 MissionResultDto

データ受信時に処理をする

航海日誌本家に実装されている機能です。使い方は本家のマニュアルを参照してください。ただし、以下の様な違いがあります。

  • スクリプトの指定方法が本家だと設定画面からファイルを直接指定できますが、拡張版は上記のように規則に沿ったファイル名でスクリプト置くという方式を取っていて、本家の方法はサポートしていません。
  • 拡張版が対応しているのはJavaScriptのみです。

テーブルとの連携方法

ScriptDataクラスにkey-value形式でデータを保持できます。

データ受信時にScriptData.setData()でデータを入れると、テーブルスクリプトからScriptData.getData()で入れたデータを取得して表示というようなことが可能です。ただし、航海日誌拡張版が想定していないデータからの更新だと自動更新が反応しないので、テーブルが更新されません。テーブルの更新を発動させるには、ApplicationMain.main.get*で対象のテーブルを取得して、update()メソッドを呼び出してください。

// 任務一覧を更新させる
ApplicationMain = Java.type("logbook.gui.ApplicationMain");
ApplicationMain.main.getQuestTable().update();

同梱スクリプトのアップデート抑制

(ver1.8.1から)

スクリプトはscriptフォルダから読み込まれますが、航海日誌拡張版起動時にtemplates/scriptフォルダから更新のあったスクリプトをコピーして上書きします。同梱スクリプトを独自に変更したなどでこのアップデートを抑制したい場合は、script/ignore_update.txtにアップデートしないスクリプトの名前を書いてください。このファイルは航海日誌を一度でも起動すると空ファイルが作られます。

例) ignore_update.txt

ship_remodel.js
quest__basic.js

正しく読み込まれれば航海日誌を起動するとlogs/script.logに以下のようにログ出力されます。

XXX INFO script [XXX] 除外されているためアップデートされません: XXX\quest__basic.js
XXX INFO script [XXX] 除外されているためアップデートされません: XXX\ship_remodel.js
(一部長いのでXXXで省略)

※ver1.8.0以前の航海日誌拡張版を起動するとignore_update.txtが無視されて上書きされるので注意