ソラマメブログ

  

Posted by at

2007年12月11日

libsecondlifeサンプル - チャットとIM送受信

チャンネルを指定したチャットや、相手のUUIDを指定したIMの送信ができます。
libsecondlifeのDeveloper Portal にある以下のページを参照してください。
http://www.libsecondlife.org/wiki/Say_something_inworld_%28chat%29
http://www.libsecondlife.org/wiki/Respond_to_inworld_chat
http://www.libsecondlife.org/wiki/Send_an_instant_message
http://www.libsecondlife.org/wiki/Respond_to_instant_messages

使い方によってはスパムになるので注意しましょう。


以下はサンプルコードです。
自分でチャットに発言した内容を自分で拾っています。
タイピングの開始/終了は出していません。
聞こえる範囲には、Whisper, Normal, Shoutの3つが選べます。
ChatType.Say は古い仕様で削除予定なので使用しないようにとの説明が上記のページにあります。
また、自分にIMを送信し受信しています。



#libsecondlifeのロード
import clr
clr.AddReferenceToFile("libsecondlife.dll")
import libsecondlife
import time

#ログイン情報の設定
firstName = 'abcd' #苗字
lastName = 'efgh' #名前
passWord = 'ijkl' #パスワード

#イベント待ち合わせ用クラスの定義
class EventTracker:
def __init__(self):
self.data=False
def Clear(self):
self.data=False
def Set(self):
self.data=True
def Wait(self):
while not self.data:
time.sleep(0.1)

#チャットイベント処理用ハンドラの定義
def chatHandler(message, hearRange, chatType, chatSourceType, agentName, uuid1, uuid2, locationVector):
print 'message =', message
print 'hearRange =', hearRange
print 'chatType =', chatType #StartTyping, Normal, StopTyping
print 'chatsourceType =', chatSourceType
print 'agentName =', agentName
print 'uuid1 =', uuid1 #SourceID?
print 'uuid2 =', uuid2 #OwnerID?
print 'locationVector =', locationVector

#IM受信イベント処理用のハンドラの定義
def instantMessageHandler(im, sim):
print 'sim=', sim.ToString()
attrList = [
'ToAgentID',
'FromAgentID',
'FromAgentName',
'ParentEstateID',
'RegionID',
'Position',
'Dialog',
'GroupIM',
'IMSessionID',
'Timestamp',
'Message',
'Offline',
'BinaryBucket'
]
for i in attrList:
print i, '=', eval('im.%s' % (i) )

#初期設定
event = EventTracker()
client = libsecondlife.SecondLife()
client.Self.OnChat += libsecondlife.AgentManager.ChatCallback(chatHandler)
client.Self.OnInstantMessage += libsecondlife.AgentManager.InstantMessageCallback(instantMessageHandler)

#接続
client.Network.Login(firstName, lastName, passWord, '', '')
time.sleep(10)

#実際の処理
#現在時刻をチャットで発言する
msg = 'now ' + time.strftime('%Y-%m-%d %H:%M:%S')
chatType = libsecondlife.ChatType.Normal #ChatType.Say is obsolete version and will likely be removed in the near future.
client.Self.Chat(msg, 0, chatType)
time.sleep(10)
#自分自身にIMを送信する
targetUuid = client.Self.AgentID
msg = 'now ' + time.strftime('%Y-%m-%d %H:%M:%S')
client.Self.InstantMessage(targetUuid, msg)
time.sleep(10)

#切断
client.Network.Logout()





AgentManager.cs には、グループIMを送信するための関数もあります。
AgentManager.cs を参照ください。
例:client.Self.InstantMessageGroup(groupUuid, msg)


チャットの内容から特定の単語を拾って、挨拶と簡単な受け答えができ、
詳しい話が聞きたいという人には、担当者を呼ぶのでお待ちくださいと言うような、
コールセンター風の使い方をしてもいいかもしれません。
(外見は普通のアバターですし)

  


Posted by march at 18:13Comments(0)libsecondlife

2007年12月11日

libsecondlifeサンプル - SIM統計情報の取得

SIMの統計情報(Ctrl+Shift+1で表示される情報)により、
SIMのFPS値やアバター数などを知ることが出来ます。
詳細は公式のSECOND LIFE HELPを参照してください。(ちょっと情報が古いようですが)
http://help.secondlife.com/jp/guides/stats.php
http://secondlife.com/app/help/guides/stats.php


現在いるSIMの統計情報を、client.Network.CurrentSim配下のStats構造体から取得できます。
取得のためのリクエストの発行は不要で、最新の情報のみが勝手に上記の構造体に格納されます。
(client.Settings.ENABLE_SIMSTATS はデフォルトでTrueになっています)

以下はサンプルコードです。

#libsecondlifeのロード
import clr
clr.AddReferenceToFile("libsecondlife.dll")
import libsecondlife
import time

#ログイン情報の設定
firstName = 'abcd' #苗字
lastName = 'efgh' #名前
passWord = 'ijkl' #パスワード


#初期設定、
client = libsecondlife.SecondLife()
#client.Settings.ENABLE_SIMSTATS = True

#接続
client.Network.Login(firstName, lastName, passWord, '', '')
time.sleep(10)

#実際の処理(SIM統計情報の取得)
sim = client.Network.CurrentSim
attrList = [
#debug-Simulator
'Dilation', #Time Dilation
'FPS', #Sim FPS
'PhysicsFPS', #Physics FPS
'AgentUpdates', #Agent Updates/Sec
'Agents', #Main Agents
'ChildAgents', #Child Agents
'Objects', #Objects
'ScriptedObjects', #Active Objects
'ActiveScripts', #Active Scripts
'LSLIPS', #Script Perf
'INPPS', #Packets In
'OUTPPS', #Packets Out
'PendingDownloads', #Pending Downloads
'PendingUploads', #Pending Uploads
'UnackedBytes', #Total Unacked Bytes
#debug-Simulator-Time(ms)
'FrameTime', #Total Frame Time
'NetTime', #Net Time
'PhysicsTime', #Sim Time (Physics)
'OtherTime', #Sim Time (Other)
'AgentTime', #Agent Time ##'Agent Time' not found. then LET 0.0
'ImageTime', #Images Time
'ScriptTime', #Script Time
]
for i in (attrList):
try:
val = eval('sim.Stats.%s' % (i) )
except AttributeError:
print i, 'AttributeError'
continue
print i, val

#切断
client.Network.Logout()





・libsecondlife0.2.0では、client.Network.CurrentSim の下に直接FPSなどの値が入っていました。
 0.3.0からその下にStatsという構造体で格納されるようになりました。(Simulator.cs参照)
・ScriptTimeには小さい値が、OtherTimeには大きな値が出力されています。
値の入れ方が逆なのかもしれません。


フォーラム(http://forums.opensecondlife.org/ )は落ちたままだし、
メーリングリストも動きがほとんどありません。
(サーバ移行でデータロスがあったとか投稿がありました)
復活を祈っています。
  


Posted by march at 11:32Comments(0)libsecondlife

2007年12月10日

全自動4コマ - 「march」の巻

SLとは離れて、全自動4コマで遊んだ。名前を入れると自動的に4コマ漫画を作ってくれる。
http://crocro.com/auto4koma/index.cgi


.


.


.

SLネタで何か作ろうと思ったが、SLっぽい言葉って急に言われても出てこないものね。  
タグ :auto4koma


Posted by march at 00:10Comments(0)

2007年12月08日

HiPiHiに登録、黒服脱出

HiPiHiに登録してみた。


首無しの黒服アバターだったけど、GOTTiさんのBLOGからたどって無事に解決。
» HiPiHi 英語版登録ページとblack, headless avatar卒業!iNNX ブログ
http://blog.innx.co.jp/2007/11/63/



まだ全然歩き回ってません^^;
  
タグ :HiPiHi


Posted by march at 15:33Comments(0)

2007年12月08日

気づくとこんな時間^^;

ちよりんオフィスアワーに途中から参加。新しい年齢確認システムと、アカウントとボーナスについての話題。
難しい話は分からないので、チャチャ入れ担当^^;。

新しいサッカーシステムのテストに参加。
最初にもらったHUDでは激しくぶつかるとばったり倒れるシステム搭載。寝て遊ぶ。
その次にもらったやつはいい感じ。

久々にBetaグリッドへ。宇宙服を着た自称エイリアンのかたに
新しいHAVOKのSIMに連れてってもらう。
Bethel - Vehicle Sandboxという所。
箱詰めのボールを置いてみたけど、あんまり変わらないなぁ。
山の上からボールをぶちまけて板に乗ってころのように滑ってみたけど、
楽しくやるには何か工夫がいりそう。

そのSIMのHAVOKのバージョンってどうやったら分かるんだろう。
というか、SIMごとに違うバージョンにできるんかいな。

  


Posted by march at 00:27Comments(0)

2007年12月07日

libsecondlifeサンプル - テレポートと現在位置

テレポートを使ってアバターを遠く離れた場所に短時間で移動させることができます。
テレポート先の指定には2つの方法があります。
(1)SIM名とSIM内の位置
(2)ランドマークのUUID
順に説明します。

(1)SIM名とSIM内の位置を指定してテレポートする
SIM名の文字列と、SIM内の位置をベクトル型で指定してテレポートします。
例:Karuizawaシムの145, 250, 22 にテレポートする場合

simName = 'Karuizawa'
pos = libsecondlife.LLVector3(145, 250, 22)
client.Self.Teleport(simName, pos)


(2)ランドマークのUUIDを指定してテレポートする
UUIDをUUID型で指定してテレポートします。
あらかじめ公式ビューアでインベントリからランドマークを探して、
右クリックして"Copy Asset UUID"を選んでUUIDを取得しておくとよいでしょう。

lmUuid = libsecondlife.LLUUID('51daae92-4279-3530-82a6-349fe31a87bb')
client.Self.Teleport(lmUuid)


テレポート時に何かしたい場合は、以下のようにOnTeleportイベントをハンドルできます。
client.Self.OnTeleport += libsecondlife.AgentManager.TeleportCallback(teleportHandler)
イベントハンドラ側は3つの引数(message, status, flags)を持ちます。
例えば以下のような情報を得られます。
テレポートの開始と終了で2回は呼ばれるので注意が必要です。
例1:ランドマークを使ってテレポートを開始
message= Teleport started
status= Start
flags= ViaLandmark

例2:SIM名と位置を指定したテレポートが完了
message = Teleport finished
status = Finished
flags = ViaLocation


以下はサンプルコードです。
イベントクラスを定義していますが、実際は使っていません(手抜き^^;)

#libsecondlifeのロード
import clr
clr.AddReferenceToFile("libsecondlife.dll")
import libsecondlife
import time

#ログイン情報の設定
firstName = 'abcd' #苗字
lastName = 'efgh' #名前
passWord = 'ijkl' #パスワード

#イベント待ち合わせ用クラスの定義
class EventTracker:
def __init__(self):
self.data=False
def Clear(self):
self.data=False
def Set(self):
self.data=True
def Wait(self):
while not self.data:
time.sleep(0.1)

#テレポートイベント処理用ハンドラの定義
def teleportHandler(message, status, flags):
print 'message=', message
print 'status=', status
print 'flags=', flags
event.Set()

#現在位置を表示する関数の定義
def printCurrentLocation():
global client
print 'current sim =', client.Network.CurrentSim.Name, ',',
print 'pos =', client.Self.Position.ToString()

#初期設定、
event = EventTracker()
client = libsecondlife.SecondLife()
client.Self.OnTeleport += libsecondlife.AgentManager.TeleportCallback(teleportHandler)

#接続
client.Network.Login(firstName, lastName, passWord, '', '')

#実際の処理(テレポートと現在位置の取得)
#(1)SIM名とSIM内の位置を指定してテレポートする
time.sleep(10)
simName = 'Karuizawa'
pos = libsecondlife.LLVector3(145, 250, 22)
client.Self.Teleport(simName, pos)
#現在位置の表示
time.sleep(10)
printCurrentLocation()
#(2)ランドマークのUUIDを指定しててレポートする
time.sleep(10)
lmUuid = libsecondlife.LLUUID('51daae92-4279-3530-82a6-349fe31a87bb')
client.Self.Teleport(lmUuid)
#現在位置の表示
time.sleep(10)
printCurrentLocation()

#切断
client.Network.Logout()

  


Posted by march at 12:53Comments(0)libsecondlife

2007年12月07日

MagSLパーティーから帰宅しました

MagSLパーティーから帰宅しました。終電が遅れていたので助かりました。
会場はけっこう人が集まっていて、ダンゴになると通れないほど。
ミニライブでSolaryさんやバイオリニストのかたたちの
実物が多少緊張しながらのステージを見て、SLの回線の向こうにいるのは人なんだなぁと思ったり。
じょにーさんやはたけさんが意外と大きかった^^;(うちのディスプレイで見ると小さいんで(ぉ
なかなか実際に会って話が出来ない人ともお話できたし
In-Worldだけでは聞けない密度の濃いネタもあったので
後で噛みしめたいと思っちょります。

ビンゴ大会でキッザニアのTシャツがあたったので、NEETを受け入れてくれる施設なのか試そうかどうしようか悩みつつ、もう寝ます。
  


Posted by march at 02:36Comments(3)

2007年12月06日

1.18.6(0)で日本語入力は正式解消/字汚れは継続(寂)

1.18.6(0)がリリースされました。
http://secondlife.com/community/downloads-optional.php

・入力が勝手に日本語半角カナになる現象は解消しています。
 その場入力もOKです。
・字汚れはまだ発生します。
 UIサイズを大きくしている人は、字汚れが気になったらUIサイズを変えるかリログしてください。
・ログイン画面が美しくありません。
 ・プリファレンスボタンが出ないので、ビデオをオフにしたり描画スペックをいじったりするのは
  ログイン後でないとできません。
左上のメニューバーのEdit - Preferenceから変更できます。
 ・カメラ・コントロールや移動コントロールのパネルが表示されますが、
  ログイン画面の山の後ろ側が見えるわけではありません^^;
 ・バージョン情報がURLエンコードされてます。


公式BLOGのアナウンスはこちら。
http://blog.secondlife.com/2007/12/05/new-release-candidate-viewer-1186-rc0-available-today/#more-1449
>Positioning fixes for Japanese IME for fields where only ASCII is allowed
なんて文もあるので、ご一読を。
  


Posted by march at 12:08Comments(2)viewer

2007年12月05日

libsecondlifeサンプル - 所持金照会

Self.RequestBalance() と Self.OnBalanceUpdated を使って、
アバターの所持金を調べることができます。

以下のページがとても参考になります。
このページが無ければ私もlibsecondlifeをさわる気になりませんでした。ありがとうございます。
SecondLifeのボットを5分で書く方法 - TokuLog 改め だまってコードを書けよハゲ
http://d.hatena.ne.jp/tokuhirom/20070921/1190371544



では所持金照会のサンプルです。

#libsecondlifeのロード
import clr
clr.AddReferenceToFile("libsecondlife.dll")
import libsecondlife
import time

#ログイン情報の設定
firstName = 'abcd' #苗字
lastName = 'efgh' #名前
passWord = 'ejkl' #パスワード

#イベント待ち合わせ用クラスの定義
class EventTracker:
def __init__(self):
self.data=False
def Clear(self):
self.data=False
def Set(self):
self.data=True
def Wait(self):
while not self.data:
time.sleep(0.1)

#所持金要求イベント処理用ハンドラの定義
def BalanceHandler(balance):
global event
print 'balance=', balance
event.Set()

#初期設定、
event = EventTracker()
client = libsecondlife.SecondLife()
#client.Self.OnBalanceUpdated += libsecondlife.MainAvatar.BalanceCallback(BalanceHandler) #ver0.2.0
client.Self.OnBalanceUpdated += libsecondlife.AgentManager.BalanceCallback(BalanceHandler) #ver0.3.0

#接続
client.Network.Login(firstName, lastName, passWord, '', '')

#実際の処理(残高照会)
event.Clear()
client.Self.RequestBalance()
event.Wait()

#切断
client.Network.Logout()



クライアントによる所持金照会の要求と、サーバによる応答は非同期です。
ポイントは以下の2つです。

(1)イベントハンドラ(コールバック関数)
41行目で、所持金照会の要求をサーバに投げています。
実際の処理は、所持金照会の要求に応答があったときに呼び出されるイベントハンドラで行います。
24行目でそのハンドラの定義を行い、34行目でハンドラを登録して、使えるようにします


(2)イベントの待ち合わせ
イベントの発生を待ち合わせるため、EventTrackerクラスをグローバル変数として使用します。
具体的には、
31行目でeventという名で(グローバル変数として)実体化し、
BalanceHandler関数内でも26行目でglobal命令文を使ってeventをグローバル変数として扱っています。
待ち合わせの流れは、
40行目のevent.Clear()でフラグを下げてから要求を出し、42行目でevent.Wait()でフラグが上がるのを待ちます。
イベントが発生すると、25行目のBalanceHandler関数が呼ばれ、
その関数の最後(28行目)でフラグを上げます。



間違いの指摘や不明点の質問を歓迎します。
  


Posted by march at 12:15Comments(1)libsecondlife

2007年12月04日

libsecondlifeサンプル - 接続と切断

思うところがあって、いったんSLのアイテム収集のほうは
注力するエネルギーを減らして、
libsecondlifeのサンプルをまとめます。といっても、分かっている範囲の、
接続・切断、残高照会(他のかたのページにあったやつの劣化コピー^^;)、
テレポート、チャットの受信、統計情報の取得、新オブジェクトの情報、
指定オブジェクトの詳細取得、といったあたりです。


まずは、環境の紹介から。
WindowsXP Home Edition SP2 (たまにWindows2000SP2)
IronPython 1.1 (1.1) on .NET 2.0.50727.832 (FePy)
libsecondlife 0.3.0 (11/30に0.3.1が出ましたが、まだ移行してません^^;。)

libsecondlifeは0.2と0.3でクラス内のメンバ名とかが大きく変わっているので、
今からやるなら0.3.1がお勧めです。
まだバージョンアップで大きく変わる時期なので、適宜追随してくださいな。


では、接続と切断のサンプルです。

#libsecondlifeのロード
import clr
clr.AddReferenceToFile("libsecondlife.dll")
import libsecondlife

#ログイン情報の設定
firstName = 'abcd' #苗字
lastName = 'efgh' #名前
passWord = 'ijkl' #パスワード

#接続
client = libsecondlife.SecondLife()
client.Network.Login(firstName, lastName, passWord, '', '')

#実際の処理(ここでは単なるsleep)
import time
time.sleep(30)

#切断
client.Network.Logout()



1-5行目:libsecondlifeを.Net経由でロードして、この言語から使えるようにします。
6-10行目:ログインに必要な最低限の情報をあらかじめ変数に入れます。
11-14行目:ライブラリを使ってSecondLifeに接続します。
16-18行目:30秒間何もしません。
19-20行目:ライブラリを使ってSecondLifeから切断します。
ポイントは、13行目の接続、20行目の切断です。


●接続は13行目です。
client.Network.Login(firstName, lastName, passWord, '', '')
第1引数:ログインするアバターのファースト・ネーム
第2引数:ログインするアバターのファミリー・ネーム
第3引数:ログインするアバターのパスワード
第4引数:プログラム名
第5引数:メールアドレス

●切断は20行目です。
client.Network.Logout()
引数はありません。


20行程度のコードで接続、切断が可能です。
実際の処理はコールバック関数を登録して非同期で行う場合が多いです。
次はコールバック関数を使った処理を書く予定です。


P.S.ソースコードを引用文(blockquote)以外で表示する方法をご存知の方がいらっしゃいましたら教えてください。  


Posted by march at 21:31Comments(3)libsecondlife

2007年12月04日

権利周りは感覚が分からん。

これまでやっていた、SL内のアイテム情報を集めるサイトについて、
詳しい人に意見をもらったところ、
個人のサイトでやるならいいかもしれないが、商用ではだめだよねとのこと。
投稿してもらったらいいんじゃない?とアドバイスをもらった。
商用化は特に考えてなかったが、BLOGページではなく専用ページに
しようと思ってたので、トラブルになりそうだと判断。

SL内の画像が(JPEG2000からJPEGに変換する時点で劣化があるにしても)
ほぼそのままの品質で取れるわけだし、それをうちのサイトから二次利用に
まわされても困る。
UUID教えるからキャッシュに入ってたら
ヘッダ情報とキャッシュファイルをつき合わせてJP2ファイルを
作ってねと言うわけにもいかない。


欧米風に(偏見)、まずやってしまって後から正義(?)を
勝ち取るという方法もあるんだろうが、
問題がおきてプレッシャーがかかった時に
対処している余力はなさそう。


といいつつ50x50くらいのサムネイルなら…と考える、中途半端な私です。
  


Posted by march at 21:12Comments(0)

2007年12月04日

与太話-20071204

艦内でトラブル発生。普段はなんでもない小さな間違いが、
一度に積み重なるとダメージを受ける。
戦闘中でなくてよかった。
こんな時に弾薬があっても役に立たないが、そう豊富にあるわけではないのでとっておく。
燃料が心配だがオイルがもっと心配。

---
フットサル最終戦&閉会式に出られなくてすいません。  


Posted by march at 21:10Comments(0)