👦

Ingress IITC-CE で遊ぼう

2023/08/15に公開

Ingress IITC-CE で遊ぼう

Ingressって?

NIAという組織がかれこれ10年くらい続けている位置情報を用いた社会実験。位置情報ゲーム。体育祭的に二色の組に分かれて熾烈な抗争をする。Ingressという名前だが、NginxやKubernetesとは関係ない。とりあえずインストールしてアカウントを作らないと何もできないのでアカウントを作ろう。

このゲームを始めるなら緑色の陣営にするとQOLが向上するらしい

IITC-CEって?

Ingress Intel Total Conversion Community Editionのこと。
実体はiitc.appに公開されたGreasyMonkeyスクリプトのツールセット。
(開発が終了しているiitc.meの有志開発継続版)

Ingressのアカウントを作成したユーザが参照できるIntelmapという
使えない地図アプリ社会実験マップを見やすくする機能を持つ。

機能の一部で本来公開されていないAPIを実行している為、非公式な外部ツールという位置づけであり、Niantic社は非公式な外部ツールを使う事を禁止しているので利用は自己責任。

↓IITCで見やすくなった地図。どちらが陣取りできているかが勝負のゲームらしいが。
intel2iitc.png

↓IITCで見やすくなったPOI。POIというのはPoint of Interestの事。陣取りゲームの、拠点。
intel2iitc_portal_detail.png

IITC-CEのインストール方法

開発に重きを置く為、ダッシュボードでプラグインを編集可能な
パソコン、ブラウザ拡張機能のTemperMonkeyを前提とする。

  1. GoogleChromeブラウザをインストール
  2. TemperMonkeyプラグインをインストール
  3. iitc.app→"Desktop"→"RELEASE VERSION"→TemperMonkeyにプラグインをインストール
  4. IntelMapにアクセス、TemperMonkeyプラグインを有効化
     ちなみにその他の拡張pluginはiitc.app→"Desktop"の下の方にある。

IntelMapでIITCが動作していればアドレスバー付近に以下のようなアイコンが表示されるはず。
アイコンの数字は今そのURLで有効化されているプラグインの数を示している。
tempermonkeyicon.png

スマホの場合

専用アプリを使い、スマートフォンに自作のプラグインをインストールすることもできる。
現代のスマートフォンの小さいタッチ画面で開発するのは非常に難しいので紹介のみ。

おすすめ拡張プラグイン

  • 標準ライブラリ系
    • Draw tools: Leafletで地図上に簡単にお絵かきができるようになる。描画に使うのでほぼ必須。
    • Raw portal JSON data: APIで得られるデータの参照。デバッグ用に使う。ほぼ必須。
    • OpenStreetMap.org map: スマホアプリ中はGoogleMapではなくOpenStreetMapを地図レイヤーに使うので、ほぼ必須。
    • Highlight portals based on history:過去行った事がある場所の表示ができる。
    • Missions: ミッションというスタンプラリー情報を呼び出す。
  • サードパーティライブラリ系

IntelMapで遊ぼう

IntelMapを見ながら現実世界でIngressゲームを実際に遊んでみよう

  • IntelMapで地図にお絵かきする
    • Draw Toolsを使ってLine、Polygon、Circleを書く
    • LeafLetを使ってMarkerを立てる
  • IntelMap地図を見ながらスタンプラリーを作成する
    • Ultimate Mission Makerを使ってご当地の観光ルートを作る
  • IntelMapで地図を見ながら現実のPOIを見に行き写真を撮影してゲームに反映させる

IITC-CEで遊ぼう

その前に・・・知っておくべきいくつかの情報を列挙

IITC-CEで与えられるデータは限られている

  • IITC-CEが与える代表的なデータ
    • 現在のPOIの名前、現在のPOIの画像URL、現在のPOIの座標
    • 現在のPOIのゲーム情報(拠点に装備した物や拠点間の接続状態)
    • 現在の特定エリアのゲームスコアボード
    • 現在の特定エリアのゲームチャットログ
    • 現在の自身のインベントリ(所持アイテム)情報、POI訪問履歴(要サブスク)

他の情報は自分が作成するか、他所から情報を修飾する

  • IITC-CEが与えない代表的なデータ
    • 未来の情報(シミュレーション)
    • 過去のゲームの状態
    • 現在のPOIに関する詳しい情報
    • 現在の自身の位置情報
    • 自身以外の情報

自作IITC-CE Pluginを動かしてみよう!: HelloWorld編

まずは動かしてみよう。

  1. alert-helloworld.jsの中身をすべてコピー

  2. ChromeでTemperMonkeyのアイコンをクリック
    tempermonkeyicon.png

  3. 新規スクリプトを追加... をクリック
    tempermonkey_newscript.png

  4. エディタが開くので、Ctrl+a → Ctrl+vで丸ごと貼り付け、Ctrl+sで保存

  5. https://intel.ingress.com/intel にアクセス

  6. IntelMapが開いた途端にHello World!というアラートボックスが出てきたら成功

window.alertを上書きするフレンズ

自作スクリプト(alert-helloworld.js)に関して解説

alert-helloworld.js
// ==UserScript==
// @id             alert-helloworld
// @name           IITC plugin: alert-HelloWorld
// @category       Debug
// @version        0.0.1.20220000
// @namespace      https://github.com/IITC-CE/ingress-intel-total-conversion
// @updateURL      https://raw.githubusercontent.com/syakesaba/iitc-plugin-alert-helloworld/main/alert-helloworld.js
// @downloadURL    https://raw.githubusercontent.com/syakesaba/iitc-plugin-alert-helloworld/main/alert-helloworld.js
// @description    HelloWorld for you all.
// @author         syakesaba
// @match          https://*.ingress.com/intel*
// @match          https://*.ingress.com/mission/*
// @include        https://*.ingress.com/intel*
// @include        https://*.ingress.com/mission/*
// @grant          none
// ==/UserScript==

function wrapper(plugin_info) {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};

//PLUGIN AUTHORS: writing a plugin outside of the IITC build environment? if so, delete these lines!!
//(leaving them in place might break the 'About IITC' page or break update checks)
plugin_info.buildName = 'release';
plugin_info.dateTimeVersion = '2022-10-22-180000';
plugin_info.pluginId = 'alert-helloworld';
//END PLUGIN AUTHORS NOTE

// use own namespace for plugin
window.plugin.alertHelloWorld = function() {};

//--------------------------SCRIPT BEGIN

window.plugin.alertHelloWorld.main = function() {
    window.alert("Hello World!");
}

var setup = function () {
  window.plugin.alertHelloWorld.main();
}

//---------------------------SCRIPT END

setup.info = plugin_info; //add the script info data to the function as a property
if(!window.bootPlugins) window.bootPlugins = [];
window.bootPlugins.push(setup);
// if IITC has already booted, immediately run the 'setup' function
if(window.iitcLoaded && typeof setup === 'function') setup();
} // wrapper end
// inject code into site context
var script = document.createElement('script');
var info = {};
if (typeof GM_info !== 'undefined' && GM_info && GM_info.script) info.script = { version: GM_info.script.version, name: GM_info.script.name, description: GM_info.script.description };
script.appendChild(document.createTextNode('('+ wrapper +')('+JSON.stringify(info)+');'));
(document.body || document.head || document.documentElement).appendChild(script);

サンプルスクリプトのすべてを理解する必要はない。
以下、いくつか重要な部分だけ紹介する。

UserScript宣言部

// ==UserScript==
// @id             alert-helloworld
// @name           IITC plugin: alert-HelloWorld
// @category       Debug
// @version        0.0.1.20220000
// @namespace      https://github.com/IITC-CE/ingress-intel-total-conversion
// @updateURL      https://raw.githubusercontent.com/syakesaba/iitc-plugin-alert-helloworld/main/alert-helloworld.js
// @downloadURL    https://raw.githubusercontent.com/syakesaba/iitc-plugin-alert-helloworld/main/alert-helloworld.js
// @description    HelloWorld for you all.
// @author         syakesaba
// @match          https://*.ingress.com/*
// @match          https://*.ingress.com/intel*
// @match          https://*.ingress.com/mission/*
// @include        https://*.ingress.com/*
// @include        https://*.ingress.com/intel*
// @include        https://*.ingress.com/mission/*
// @grant          none
// ==/UserScript==
  • author,name,category,description,idは読んで字の如く。idは他と被らないようにしよう。
  • namespaceはhttps://github.com/IITC-CE/ingress-intel-total-conversionにしておこう。
  • スクリプト更新処理部分(実は無くても動く)
    • versionは読んで字の如く。updateURLを参照し、新しいバージョンが無いかチェックするのに使う。
    • updateURL 新しいバージョンが無いかチェックするためのURL。
    • downloadURL 一応、分ける意味があるが、概ねupdateURLと同じになる。
  • include,matchは*がワイルドカードとして使える。このスクリプトを作動させるURLをマッチングしている。
  • grantはnoneにしておこう。おまじない。

過去、このUserScript宣言部で外部のスクリプトライブラリを読み込む機能がTemperMonkeyにもあったのだが、現在はセキュリティ上の理由で機能が封殺されている。もし外部のライブラリをどうしても使いたい場合は生のコードを自作コードの中にコピーして埋め込んでしまうやり方がある。その場合、ライセンスには気をつけよう。

  • スクリプトの更新処理について
    • versionを編集しておくとTemperMonkeyが起動したときに自分が持っているスクリプトが古いかどうかをupdateURLを見に行ってチェックしてくれる。新しいバージョンになっていたら、更新するかどうかをユーザに聞きに行く。ユーザからすると便利な機能であるし、開発者にとってもいちいち更新をしてくれと言う必要が無い。しかし、開発者はこれを悪用し認証情報を盗む不正なスクリプトに途中から差し替える事ができるので、自分が動かそうとしているスクリプトは意図した動きをするのかどうか、実際のコードを見てチェックする必要がある。最初にスクリプトを譲り受けた場合もそうである。つまり、本来、あなたはこのページで紹介されたalert-helloworldというスクリプトを無限定に信頼してはいけない。 これは利用者としてのマナーでもある。

IITC-Wrapper部

Wrapperの部分は正直、理解する必要がほとんど無い。

  • plugin_infoの部分の編集は適当に・・・。
function wrapper(plugin_info) {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};

//PLUGIN AUTHORS: writing a plugin outside of the IITC build environment? if so, delete these lines!!
//(leaving them in place might break the 'About IITC' page or break update checks)
plugin_info.buildName = 'release';
plugin_info.dateTimeVersion = '2022-10-22-180000';
plugin_info.pluginId = 'alert-helloworld';
//END PLUGIN AUTHORS NOTE

// use own namespace for plugin
window.plugin.alertHelloWorld = function() {};

//--------------------------SCRIPT BEGIN

〜省略〜

//---------------------------SCRIPT END

setup.info = plugin_info; //add the script info data to the function as a property
if(!window.bootPlugins) window.bootPlugins = [];
window.bootPlugins.push(setup);
// if IITC has already booted, immediately run the 'setup' function
if(window.iitcLoaded && typeof setup === 'function') setup();
} // wrapper end
// inject code into site context
var script = document.createElement('script');
var info = {};
if (typeof GM_info !== 'undefined' && GM_info && GM_info.script) info.script = { version: GM_info.script.version, name: GM_info.script.name, description: GM_info.script.description };
script.appendChild(document.createTextNode('('+ wrapper +')('+JSON.stringify(info)+');'));
(document.body || document.head || document.documentElement).appendChild(script);
自作スクリプト用の名前空間の宣言部

IITC-Pluginは同じURLにいくつもスクリプトが動くので
自作スクリプトで使う変数名はすべて自分の名前空間の中で宣言する。

window.plugin.alertHelloWorld = function() {};
setup()の実行部

それぞれのIITC-PluginはIngressIntelTotalConversionという親玉のTemperMonkeyスクリプトの手助けで動いている。そのため、自作のプラグインはIITC本体がセットアップ完了した後に呼び出す必要がある。window.iitcLoadedはそのフラグ

// if IITC has already booted, immediately run the 'setup' function
if(window.iitcLoaded && typeof setup === 'function') setup();
} // wrapper end
自作スクリプト実行部

setupという名前で関数を宣言し、setup関数から
自作スクリプトを動かす(ここではmain)関数を実行している。

window.plugin.alertHelloWorld.main = function() {
    window.alert("Hello World!");
}

var setup = function () {
  window.plugin.alertHelloWorld.main();
}

main関数の中で宣言された変数は(global宣言をしなければ)全て
window.plugin.alertHelloWorldという名前空間の中で
定義されるので、他のIITC-Pluginに干渉せず、干渉を受けず実行できている。

自作IITC-CE Pluginを動かしてみよう!: Hook引っ掛け編

https://github.com/IITC-CE/ingress-intel-total-conversion/blob/master/core/code/hooks.js には自作勢が使えるHook系関数のリストが宣言されている。これを使うことで、ブラウザの画面が変化した際に何かを実行することが出来るようになる。

まずは動かしてみよう。

  1. alert-on-portal-selected.jsの中身をすべてコピー
  2. ChromeでTemperMonkeyのアイコンをクリック
  3. 新規スクリプトを追加... をクリック
  4. エディタが開くので、Ctrl+a → Ctrl+vで丸ごと貼り付け、Ctrl+sで保存
  5. https://intel.ingress.com/intel にアクセス
  6. IntelMapが開いて、ポータルを選択した時にアラートボックスが出てきたら成功
    首切地蔵の写真

自作スクリプト(alert-on-portal-selected.js)に関して解説

  • UserScript宣言部,IITC-Wrapper部,自作スクリプト用の名前空間の宣言部は定型的なので解説しない。

自作スクリプト実行部

//--------------------------SCRIPT BEGIN

window.plugin.alertOnPortalSelected.run = function(event) {
    //Called everytime IntelMap is refreshed and if any portal selected
    //event.selectedPortalGuid
    //event.unselectedPortalGuid
    var portal = window.portals[event.selectedPortalGuid];
    if (portal && portal._map && portal.options.data.title) {
        var title = portal.options.data.title;
        window.alert("Hello " + title);
        console.log(portal);
    }
}

window.plugin.alertOnPortalSelected.main = function() {
    //https://github.com/IITC-CE/ingress-intel-total-conversion/blob/master/core/code/hooks.js
    window.addHook('portalSelected', window.plugin.alertOnPortalSelected.run);
}

var setup = function () {
  window.plugin.alertOnPortalSelected.main();
}

//---------------------------SCRIPT END
  • window.plugin.alertOnPortalSelected.run = function(event) {...}
    • window.addHook関数で設定された、IntelMap上でポータルを選択した際に発火する関数
    • eventという引数を持つ。引数には選択された(または選択を解除された)ポータルのGUIDが入る。
  • window.addHook('portalSelected', window.plugin.alertOnPortalSelected.run)
メインの処理
    var portal = window.portals[event.selectedPortalGuid];
    if (portal && portal._map && portal.options.data.title) {
        var title = portal.options.data.title;
        window.alert("Hello " + title);
        console.log(portal);
    }
  • var portal = window.portals[event.selectedPortalGuid];

    • GUIDという識別子からポータルの情報を取得する定型文
    • portal.optionsにIntelMapへの描画用のデータが入っている(上っ面のデータ)
    • portal.options.dataにポータルの生のデータが入っている
  • if (portal && portal._map && portal.options.data.title) {

    • IntelMapは負荷削減の為、ある条件でしかポータルの詳細情報を読み込まないので、その情報が読み込まれている事を確認した上で次の処理に移る。
  • console.log(portal)

    • ChromeのWebコンソールにportal変数の情報を表示する
    • 実際にF12を押して、コンソールのタブを開けば、どんなデータが取れているか確認できる

f12

自作スクリプト実行部の問題点

  • 今のスクリプト実行部の状態だと、window.plugin.alertOnPortalSelected.runがIntelMap上のポータル描画の更新(portalDetailsUpdated)の度に実行されてアラートが何度も出て鬱陶しいという問題が分かっている。解決できる人はしてみよう。

自作IITC-CE Pluginを動かしてみよう!: window.Lでお絵かき編

そもそもwindow.Lって何?

とりあえずお絵かきしてみよう

mylayer=window.L.geodesicCircle(
    {lat:35.686445,lng:139.756757}, 200, {
      fill: true,
      color: "red",
      weight: 3,
      interactive: false
    }
  ).addTo(window.map);

半径200メートルの赤い丸

  • 次に以下をペーストしてみよう。赤い丸が消えるはず。
window.map.removeLayer(mylayer);

丸が消えた

Discussion