Tag: SSP’

そもそも\![embed,…]以外のことがあんまりわかってなかった

 - by Don

前回の記事で検証した仮説「呼び出されたイベントでScriptを返さなければ現在再生中のScriptは中断されない」、よくよく考えたら当たり前なことだと気がついた。

これ、ただのイベント割り込みだ。

ゴーストがランダムトーク中に0分になると、トークが中断して時報トークをする。これはトーク中に割り込まれたイベントOnMinuteChangeに対してScriptを返したため、現在再生中のScriptが中断して時報トークが再生されたからだ。

しかし、時報トークの無いゴーストでも等しくOnMinuteChangeイベントは通知されているのにトークは中断されない。OnMinuteChangeイベントに対して何もScriptを返していないため、現在再生中のトークを中断する必要が無いからだ。

\![raise,...]など自分でイベントをコールする系のScriptを使用した場合でも状況は一緒だ。自分でわざわざイベント割り込みを起こしたのだ。\![raise,...]を実行してその結果何かScriptが返されたなら、現在再生中のScriptは中断して当たり前だし、Scriptが返されなければ再生中のScript(トーク)は継続して当たり前だ。時報トークの割り込みと同じ。

\![embed,...]の使い方がわかった

 - by Don

今更ながら\![embed,…]の使い方を把握したので覚書です。

基本

単純な例

里々でやろうとするときは\![embed,…]の呼び出し先イベントは\eで閉じないよう留意しないといけない。

*
:あいうえお\![embed,OnHoge]さしすせそ

*OnHoge
:かきくけこ

#これを実行すると以下のようになって「あいうえおかきくけこ」と表示された時点で再生が終わる
#\0\s[0]\1\s[10]\0あいうえお\0\s[0]\1\s[10]\0かきくけこ\eさしすせそ\e

単語群なら前後に余計なスクリプトは付かない。

*
:あいうえお\![embed,OnHoge]さしすせそ

@OnHoge
かきくけこ

#これを実行すると以下のようになる
#\0\s[0]\1\s[10]\0あいうえおかきくけこさしすせそ\e

里々であれば以下のように書いても同じ結果が得られる。

*
:あいうえお(OnHoge)さしすせそ

@OnHoge
かきくけこ

#これを実行すると以下のようになる
#\0\s[0]\1\s[10]\0あいうえおかきくけこさしすせそ\e

これでは面白くないので、同じ結果が得られない例を挙げる。

SakuraScriptの再生と同期して呼び出しが実行される例

*
:時計の秒針を一秒おきに数えてみよう!
(現在秒)、\_w[1000](現在秒)、\_w[1000](現在秒)…。

これは期待した動作にならない。「13、14、15…。」みたいになってほしいが、「13、13、13…。」となってしまう。里々が全ての括弧を展開した結果のSakuraScriptをSSPに渡しているだけなので、SSPに届く頃にはすべて13になっている。

しかし、\![embed,…]を使えば期待した動作が可能となる。

*
:時計の秒針を一秒おきに数えてみよう!
\![embed,OnGetSecond]、\_w[1000]\![embed,OnGetSecond]、\_w[1000]\![embed,OnGetSecond]…。

@OnGetSecond
(現在秒)

この例だと「13、14、15…。」みたいに再生される。SakuraScriptの再生と同期してイベント呼び出しが実行され、返されたScriptをその場で埋め込みながら再生を続ける。すごい。

応用

複雑な例

\![embed,…]とはどんなものか、ということについては上述の例さえわかれば十分である。それ以上でもそれ以下でもない。\![embed,…]はそんなに難しいものではない。

\![embed,…]ワカラナイ、というのは往々にして\![embed,…]以外のところに原因がある。例えば、UKADOCの説明には以下のように書いてある。

プロパティシステムの内容によって分岐など、イベントを実行して情報を取得する仕様を、1回のスクリプト実行で有効に使用するための仕様。

何言ってるかワカラナイ。

プロパティシステムというのは、SSPが知っている情報を教えてもらうための仕様だ。例えば現在時を教えてもらうには以下のように書く。

*
\![get,property,OnGetHour,system.hour]

*OnGetHour
:現在(R0)時です。

里々なら里々自身の力で(現在時)と書けば取得できるけど、簡単な例として。

ここで重要なのが、情報を取得するためには別イベントをコールする必要があるということだ。(R0)に入っている情報を(またはそれを使用/加工した文字列を)\![get,property]を実行した直後に埋め込んで再生したい場合もあるのかもしれない。そういうことができますよ、と\![embed,…]の説明には書いてある。

例えば以下のように書いてもkero側のScriptは再生されない。

*
:\![get,property,OnGetHour,system.hour]
:もうそんな時間か。#←これは再生されない

*OnGetHour
:現在(R0)時です。

イベントを呼び出す系のSakuraScriptは、それが実行された時点でそのイベントにおける再生は強制終了されるのが特徴である。

…と思っていた。昨日までは。例外があったのだ。知らなかった。

\![get,property]した後もScriptの再生が続く例

答えを言ってしまうと、以下のように書けばUKADOCの説明にあるようなことが可能となる。

*
:現在\![get,property,OnGetHour,system.hour]\![embed,OnShowHour]時です。
:もうそんな時間か。#←これが再生される!

*OnGetHour
$現在の時間【タブ】(R0)

@OnShowHour
(現在の時間)

\![get,property]した後もScriptの再生が続く条件は、呼び出したイベントで「何も返さない」ことである。

上記の例では(R0)の情報を変数に保存してはいるものの、再生するScriptは何もない。この場合、例外的に呼び出し元のScriptは再生を続けるのだ。知らなかった。

変数に保存したは良いが、再びSSPに処理が戻ってScriptの再生中である。保存した情報を再びSHIORI側で処理し、Scriptを生成し、呼び出し元に埋め込みたい。そこで\![embed,…]の登場だ。

\![embed,…]は極めて単純な仕様であり難しいことはない。\![get,property]の仕様が謎すぎるんだ。「何も返さない」場合のみScriptの再生を続けるとか誰が知ってるんだ。

補足

イベントを呼び出す系のSakuraScriptの代表と言えば\![raise,...]だ。きっと\![get,property]と同様な仕様となっているに違いない。

*
:艦隊のアイドル、\![raise,OnNakachan1]那珂ちゃんだよー!\![raise,OnNakachan2]よっろしくー!

*OnNakachan1
#何も返さない

*OnNakachan2
カーン...カーン...カーン...

予想通りOnNakachan2でScript再生が中断され、カーンカーンとなる。

ちなみに\![raise,...]はMateriaでもサポートされており、Materiaで実行しても同じ結果となった。なので、SSPは本家の仕様を忠実に再現しているものといえる。

複数のゴーストとコミュニケートする

 - by Don

うかべん 横浜#8の発表資料とヒノハルさんのテキスト実況を拝読しているところです。今回もためになる発表が多数行われたようで、こうした資料が公開されることはとてもありがたいことであると感じます。関係者の皆様、大変お疲れ様でした。

コミュニケートとraiseother

もっしょくしさんの発表資料「ゴースト間の交流について ~暦にしき宣伝添え~」は、ゴースト間での情報送受信を含む「絡み」について、利用できそうな現状の仕様をまとめた素敵な資料になっています。複数ゴーストの連携に関して興味のあるゴーストマスタさんは是非ご一読を。

その中で触れられていたコミュニケートとraiseotherの相違点の項目で、以下のように触れられていました。

コミュニケート
送信対象は一度に一人まで
raiseother
その場にいる全員に同時に発信できる(__SYSTEM_ALL_GHOST__)

実は現在(2013-11-03)、最新のSSP(2.3.12)では送信対象に関してコミュニケートもraiseotherと同等の仕様となっています。

via Satori/里々の小技 – PukiWiki

複数のゴーストに同時に話しかける

*AとBとCに話しかける
$Value0【タブ】A(sprintf,%c,1)B(sprintf,%c,1)C
:4人でマージャンしよー!

同時起動中のゴースト全員に話しかける

*全員に話しかける
$Value0【タブ】__SYSTEM_ALL_GHOST__
:みんなでじゃんけんしよー!

「複数の送信相手」を指定する場合はバイト値1区切り、「その場にいる全員」に送信する場合は「__SYSTEM_ALL_GHOST__」を使います。これはコミュニケートの場合はValue0ヘッダに、raiseotherの場合は第一引数に指定することができ、両者の送信対象に関する仕様の差はなくなっています(私がぽなさんの背中を優しくツンツンしてそうして頂きました)。

もしかしたら発表会場でぽなさんが指摘されたかもしれないですが念のため、現状の仕様はこのようになっていますので複数相手のコミュニケートも利用可能です。

SSPのMD5ハッシュ値比較

 - by Don

SSPの開発者さんと話してわかったことですが、とある理由によりSSP/2.02.26 からMD5不一致エラーとなるべきファイルも特定の条件で一致とみなす変更が加わったそうです。

これにより、SSP/2.02.25 以前もしくはmateria、CROW、ninix-ayaなどSSP以外のベースウェアではMD5不一致エラーを検出してもSSP/2.02.26以降では検出されないゴーストがいくつか存在することになりました。

チェックリスト

「ウチのゴーストは最新のSSPでさえ更新できればいいのよ。古いSSPや他の処理系なんて知らないよ。」
→ Ctrl + W を押す
「mjd!?ウチのゴーストは大丈夫なの!?」
→ 次へ進む

検証方法

  1. SSP 2.2.00 Fullsetを用意
  2. ネットワーク更新エラーの検証法に従って全ファイル更新できるか確認
「よかった、MD5不一致エラーになるゴーストはいなかったんだ。」
→ おめでとうございます
「MD5不一致エラー出てるんだけど!?どうすればいいの!?」
→ 次へ進む

解決方法

とりあえず全ファイルFTPで(バイナリモードで)アップロードし直してください。

「あれ?MD5不一致エラー出なくなったぞ?」
→ おめでとうございます or 念のため次へ進む
「MD5不一致直らないんだけど…。」
→ 手作業での更新はやめて「そだて」の使い方を覚えましょう

予防方法

全ファイルFTPアップロードで解決した場合。残念ながら、あなたが利用しているサーバは腐っています。

  • サーバを引っ越す
  • あきらめる

余談

SSPはMD5不一致エラーとみなすべき?

サーバが腐っていた場合でもSSPが気をきかせて一致と判定するようSSP/2.02.26から変更が加えられました。これについては(更新履歴で触れられてすらいないことも含めて)様々思うところがあります。ただ、仕様が絡む問題はかなりセンシティブなものなので、今回はあまり触れないことにします。SSPは元々、伺かの仕様に準拠していない不完全なNARすらも無理矢理動かしてしまうことに執念を燃やしているベースウェアですし、製作者が実現したい機能を実現するという当たり前のことを尊重したいと考えます。

悪者を一つ祭り上げるとすれば、「腐ったサーバ」です。大切なゴーストの更新ファイルを置いておくものですから、サーバ選びは慎重にしましょう。

ネットワーク更新エラーの検証法

 - by Don

ここのところずっとupdates2.dauとにらめっこしている生活をしていますが、このファイルに記載されている更新ファイルが存在しなかったりして、ネットワーク更新エラーとなるであろうゴーストがいくつか見受けられました。

MD5不一致エラーの報告をユーザさんから受けた際に、手元の環境で再現せず困惑するゴーストマスタさんもいらっしゃると思います。SSPは差分しか更新対象としないため、すべてのファイルが更新可能であることを検証するためには、ローカルのすべてのファイルを削除する必要があります。

検証の手順

開発用のSSPとは別に、ネットワーク更新検証用のSSPを用意します。そこに自作ゴーストをインストールするわけですが、SSPを終了した後、 ghost/master/descript.txt だけを残して、それ以外のファイルを全て削除します。ゴーストとして起動できなくなりますが、構いません。

descript.txtに次のようにhomeurlを記述します。

homeurl,http://www.example.com/

別のゴーストでSSPを起動し、Ctrl+Eでゴーストエクスプローラを立ち上げ、自作ゴーストを選択してネットワーク更新を開始します。するとなんと、すべての更新ファイルが降ってきます。髪の毛一本から人体を復元する黒魔術みたいですが、差分更新である伺かのネットワーク更新とは元々そういうものであり、そうあるべきものです。この時に必要なファイルの取得に失敗したら、そのファイルを更新ファイルに含めてあらためてアップロードすることで、エラーを解消することができます。

更新エラーを防ぐために

運良く更新エラーの報告を頂けた場合は上記の方法で検証できますが、そもそも更新エラーを起こさないようにするための工夫があったほうが望ましいでしょう。

エラーを未然に防ぐ最良の方法は、ツールに任せることです。人間が手作業で更新していれば当然間違いが起こります。現在入手可能でメジャーなツールと言えば「そだて」でしょうか。他にご紹介できるものが無いので歯痒いですが。

追記

ninix-aya用のプラグインを作ってみた

 - by Don

ninix-ayaのプラグインを作ってみようと思ったのですが、何を作ったらいいかわからないので、とりあえずSSPのプラグインを移植してみようと思い立ちました。

nikolat/HitThunder – GitHub

使ってみて気が付きましたが、ninix-ayaはNOTIFY SSTP/1.1に対応していないのですねver 4.3.2で対応されました。プラグイン自体はSSTPを送信するだけのシロモノなので、先にSSPを起動しておいた後にninix-ayaを起動し、実体化プラグインを実行するとSSPのゴーストに通知されるので正常に実行されていることが確認できます。

SSPの場合はPLUGIN/2.0の仕様に従ってプラグインに対してイベントが通知される形式なので、色々と情報が取得できる上、ベースウェアが起動している間ずっと常駐できます。しかしninix-ayaの場合はPythonスクリプトを実行するだけのシンプルな構成なのであまり凝ったことはしない方が賢明のようです。プラグイン実行ゴーストなどもSSPであればSenderなどで取得できますが、ninix-ayaでは判別するのも難しいかも。

SSPでネットワーク更新に対応する方法

 - by Don

今時のゴーストマスタさんはどうやっているのでしょうね。「私はこんな便利な方法知ってるよ!」って方はコメント頂けると嬉しいです。

ベースウェアでupdates2.dau作成

まずは基本から。

通常はこの方法でネットワーク更新に対応できますが、updates2.dauを作成して、更新したファイルだけをアップロードして…という煩雑な作業を毎回行うのは大変です。

ただ、教養として原理を理解しておくのは後々きっと役に立ちます。

そだて

updates2.dauの作成や更新されたファイルのみを検出してFTPでアップロードする一連の作業を自動化するツール。

ゴースト1体ごとに必要で、ゴーストディレクトリ内に配置する必要があることから、FTPのパスワードが設定されたままNARに含まれて配布されてしまう事故が時々あるようです。

GDM(ゴースト配布系自動化システム)

これはセキュリティ上の理由により配布終了してしまいましたが、とても優れたネットワーク更新支援ツールでした。

複数のゴーストの情報を登録でき、一括でアップロードできます。ゴーストフォルダ内に設置する必要もないので、安全にNARを作成できます。これに取って代わるツールは今のところ無いのではないでしょうか…。

SoSiReMi

これはアップローダーであって更新支援ツールでは無いですが、宣伝も兼ねて。

実はちゃんと仕組みを解説したことがなかったので、簡単に内部でやっていることを書いてみます。

SoSiReMiにNARがアップロードされると、ZIP展開して中身を調べ、必要なファイルが欠けていないかチェックします。descript.txtにhomeurlを書き足します。updates2.dauを作成します。展開されたファイル一つ一つをディレクトリの通りに配置して保存します。最後にNARを再パックして保存します。

descript.txtのhomeurlをチェックするベースウェアはSSPだけのようなのでSSP専用となってしまいますが、これでネットワーク更新に自動で対応されることになります。

…で、今後新しくゴーストを作成される方には何をオススメすればいいんでしょうね。

未だにGDM使ってる身としては代わりとなるアプリが必要だなーとは思うのですが…。

SSPのインストールに関する実験

 - by Don

通常のNARの構成

emily4.nar
├─balloon
├─ghost
│  └─master
└─shell
    └─master

すべてのベースウェアで正常にインストールされる。

ghost
└─emily4
    ├─ghost
    │  └─master
    └─shell
        └─master

一段深い構成

フォルダを右クリックでzipにしたりするとこうなる。

emily4.zip
└─emily4
    ├─balloon
    ├─ghost
    │  └─master
    └─shell
        └─master

SSPでのみインストール可能。materiaではインストールできない。

SSPのghostフォルダ内に正常にインストールされる。

ghost
└─emily4
    ├─ghost
    │  └─master
    └─shell
        └─master

2つあるとどうなる

2個並べてみた。

double.zip
├─emily4
│  ├─balloon
│  ├─ghost
│  │  └─master
│  └─shell
│      └─master
└─mobilemaster
    ├─balloon
    ├─ghost
    │  └─master
    └─shell
        └─master

SSPでのみインストール可能。materiaではインストールできない。

SSPのghostフォルダ内にemily4だけが正常にインストールされる。mobilemasterはどこかへ消えた。

ghost
└─emily4
    ├─ghost
    │  └─master
    └─shell
        └─master

ルートにinstall.txtを置いてみる

directoryはmobilemasterにしてみた。

mix.zip
├─emily4
│  ├─balloon
│  ├─ghost
│  │  └─master
│  └─shell
│      └─master
├─mobilemaster
│  ├─balloon
│  ├─ghost
│  │  └─master
│  └─shell
│      └─master
└─install.txt

SSPでのみインストール可能。install.txtに忠実に従う。もちろんghostとして起動はできない。

ghost
└─mobilemaster
    ├─emily4
    │  ├─ghost
    │  │  └─master
    │  └─shell
    │      └─master
    └─mobilemaster
        ├─ghost
        │  └─master
        └─shell
            └─master

SSPは最初に見つけたinstall.txtに従って展開するだけのようだ。