OkadaHiroshiの日記 このページをアンテナに追加 RSSフィード

2008-04-04

[][]グループのUUID

先日、チャットで secondlife:///app/group/グループのUUID(key)/about としゃべって、その発言をクリックしてもらうとグループの情報を開くことが出来ることを教えてもらいました。

そこで、問題はグループの UUID(key) を知ることですが、自分の所属しているグループなら次の方法で UUID を知ることができそうです。

まず、適当なオブジェクトを作り、オーナーの UUID(key) を喋るようなスクリプトを作成します。

f:id:OkadaHiroshi:20080404204852p:image

// タッチするとオーナーのUUID(key)を喋る

default
{
	touch_start( integer total_number)
	{
		llSay( 0, llGetOwner());
	}
}

次にオブジェクトのグループを調べたいグループにします。

f:id:OkadaHiroshi:20080404210425p:image

そして、Share with group をチェックし、Deed ... をクリックすることによってオブジェクトをグループに移譲します。

f:id:OkadaHiroshi:20080404211040p:image

グループに移譲したオブジェクトをタッチすると、グループの UUID(key)をしゃべってくれます。

f:id:OkadaHiroshi:20080404211312p:image

できあがり例

secondlife:///app/group/225b8061-ba41-e69b-8418-9c87cb82d245/about

2007-11-20

[]チャットchannel

LSLで、比較的近くにある(リンクされていない)オブジェク間で通信するのにはchatを使います。

chat にはチャンネルという概念があって、0番は人間が普通にchatするチャンネルです。

オブジェクト間で通信するのにはそれ以外のチェンネルを使うのですが、干渉をなるべく避けるため、オブジェクトのオーナーの名前等から計算でチャンネルを決定するプログラムが、LSL Wiki 等に載っています。

http://www.lslwiki.net/lslwiki/wakka.php?wakka=channel

これは、これで有用だとは思うのですが、このプログラムには少し、問題があります。

  • 名前の文字から、数値を計算するのにllListFindListを使って計算しているのでなんとなく重そう。
  • 同じ文字の名前 ( hiroshi と shiroshi 等 )が同じチャンネルになってしまう。
  • llKey2Nameは同じSIMにいないと有効でないため、汎用性に欠ける。(ダイアログとかならば問題はありませんが。)

そこで、それらの点を多少改良した関数を作ってみました。

// オーナーとクリエータのキーからチェンネルを計算
// コードについては、保証なし、ご自由にお使い下さい。(Please treat this code as PDS.)
integer ownerCreatorChannel()
{
    string name = (string)llGetOwner()+(string)llGetCreator();    
    string md5 = llMD5String( name, 1961); 
    return  (integer)("0x" + llGetSubString(md5,0,7)) ^
            (integer)("0x" + llGetSubString(md5,8,15)) ^
            (integer)("0x" + llGetSubString(md5,16,23)) ^
            (integer)("0x" + llGetSubString(md5,24,31))
            | 0x80000000;
}

なお、1961は適当な番号で通信するオブジェクト同士で一致していればOKです。

なお、この関数ではチェンネルの値として常に負の値を返します。

( -1 から -2,147,483,648 )

こうすることによってPUBLIC_CHANNEL(0)とDEBUG_CHANNEL(2147483647)と被ることがなくなります。

また、アバターは負の値のチャットチャンネルを直接打ち込んで話すことができないので、オブジェクト間の通信としてはより良いとおもいます。

2007-11-05

[]日本時間表示(2)

http://d.hatena.ne.jp/OkadaHiroshi/20071104/p1

きのう書いたスクリプトは、年号を計算するのにループを使っていて、

頭が悪すぎるので、修正版

// 日本時間(yyyy-mm-dd hh:mm:ss)を表示する。
integer TZ=9;		// 日本のタイムゾーン
integer INTERVAL=10;	// 更新間隔
string MSG_JAPAN_TIME;	// 日本時間という文字列
integer DAY1YEAR=365;        // 1年の日数
integer DAY4YEAR=1461;     // 4年の日数
integer DAY100YEAR=36524; // 100年の日数
integer DAY400YEAR=146097; // 400年の日数
integer DAY1970=719162;

// 100未満の整数値を "%02d" の形に整形します。 
string zeroprefix( integer n)
{
    if( n < 10){
        return "0" + (string)n;
    }
    return (string)n;
}

// 閏年かどうか
integer is_leap_year( integer year)
{
	if( year % 400 == 0){
		return TRUE;
	}else if( year % 100 == 0){
			return FALSE;
	}else if( year % 4 == 0){
			return TRUE;
	}
	return FALSE;
}

// 一年の初めの日を0とした数値を 01-01 〜 12-31 に変換する
// leap が TURE の時、うるう年とする
string day2mmdd( integer day, integer leap)
{
    list mdays;
    if( leap){
        mdays = [31,29,31,30,31,30,31,31,30,31,30,31];
    }else{
        mdays = [31,28,31,30,31,30,31,31,30,31,30,31];
    }
    integer days = 0;
    integer m = 0;
    for( m=0; m<12; m++){
        integer d = llList2Integer( mdays, m);
        if( days+d > day){
            return zeroprefix( m+1) + "-" + zeroprefix( day - days + 1);
        }
        days += d;
    }
    return "00-00";
}

// 1970年1月1日を0とした日付数値を
// yyyy-mm-dd の形に整形する。
string day2yyyymmdd( integer day)
{
	day += DAY1970; // 1年1月1日基準にする
	integer year = 1;

	year += 400*(day / DAY400YEAR);
	day = day % DAY400YEAR;

	year += 100*(day/DAY100YEAR);
	day = day % DAY100YEAR;

	year += 4*(day/DAY4YEAR);
	day = day % DAY4YEAR;

	year += day/DAY1YEAR;
	day = day % DAY1YEAR;	

	return (string)year + "-" + day2mmdd( day, is_leap_year(year));
}

// unixtime (time_t) の数値を yyyy-mm-dd hh:mm:ss の文字列に変換する
string unixtime2yyyymmddhhmmss( integer unixtime)
{
    integer sec = unixtime % 60;
    integer min = (unixtime / 60) % 60;
    integer hour = (unixtime / 3600) % 24;
    integer day = unixtime / (24*3600);
    return day2yyyymmdd( day) + " " + zeroprefix( hour) 
	+ ":" + zeroprefix( min) + ":" + zeroprefix( sec);
}

// 日本時間(yyyy-mm-dd hh:mm:ss)を表示する。 
default
{
    state_entry() {
        // 日本時間という文字列
        MSG_JAPAN_TIME = llBase64ToString("5pel5pys5pmC6ZaT") + "\n"; 
        llSetTimerEvent( 1.0); // timer() イベントを起こす 
    }

    timer() {
        integer t = llGetUnixTime() ;
        // タイマーイベントが次の間隔で割り切れる時刻におこるようにする。
        llSetTimerEvent( INTERVAL - t % INTERVAL); 
        llSetText(  MSG_JAPAN_TIME 
                         + unixtime2yyyymmddhhmmss( t+TZ*3600), 
                         <1,1,1>, 1.0); // 文字形式に変換して表示
    }
}

なお、コードについては、保証なし、ご自由にお使い下さい。(Please treat this code as PDS.)

2007-11-04

[]日本時間表示

セカンドライフのスクリプト言語 Linden スクリプトの小物を書きとめることにしました。

コードについては、保証なし、ご自由にお使い下さい。(Please treat this code as PDS.)

なお、説明のため、コメントは日本語で表示します。

// 日本時間(yyyy-mm-dd hh:mm:ss)を表示する。
integer TZ=9;		// 日本のタイムゾーン
integer INTERVAL=10;	// 更新間隔
string MSG_JAPAN_TIME;	// 日本時間という文字列

// 100未満の整数値を "%02d" の形に整形します。 
string zeroprefix( integer n)
{
    if( n < 10){
        return "0" + (string)n;
    }
    return (string)n;
}

// 一年の初めの日を0とした数値を 01-01 〜 12-31 に変換する
// leap が TURE の時、うるう年とする
string day2mmdd( integer day, integer leap)
{
    list mdays;
    if( leap){
        mdays = [31,29,31,30,31,30,31,31,30,31,30,31];
    }else{
        mdays = [31,28,31,30,31,30,31,31,30,31,30,31];
    }
    integer days = 0;
    integer m = 0;
    for( m=0; m<12; m++){
        integer d = llList2Integer( mdays, m);
        if( days+d > day){
            return zeroprefix( m+1) + "-" + zeroprefix( day - days + 1);
        }
        days += d;
    }
    return "00-00";
}

// 1970年1月1日を0とした日付数値を
// yyyy-mm-dd の形に整形する。
// ただし、2001年から2099までしか正常に計算しない。
string day2yyyymmdd( integer day)
{
    integer days =11323; // 2001-01-01
    integer year;
    for( year = 2001; year<2100; year++){
        if( year % 4 == 0){  // 2001年から2099年までしか考えないので
            if( days + 366 > day){
                return  (string)year + "-" + day2mmdd( day - days, TRUE); 
            }
            days += 366;
        }else{
            if( days + 365 > day){
                return (string)year + "-" + day2mmdd( day -days, FALSE);
            }
            days += 365;
        }
    }
    return "0000-00-00"; // 計算不能
}

// unixtime (time_t) の数値を yyyy-mm-dd hh:mm:ss の文字列に変換する
// 2001年から2099年までしか正しく計算しない。
string unixtime2yyyymmddhhmmss( integer unixtime)
{
    integer sec = unixtime % 60;
    integer min = (unixtime / 60) % 60;
    integer hour = (unixtime / 3600) % 24;
    integer day = unixtime / (24*3600);
    return day2yyyymmdd( day) + " " + zeroprefix( hour) 
	+ ":" + zeroprefix( min) + ":" + zeroprefix( sec);
}

// 日本時間(yyyy-mm-dd hh:mm:ss)を表示する。 
default
{
    state_entry() {
        // 日本時間という文字列
        MSG_JAPAN_TIME = llBase64ToString("5pel5pys5pmC6ZaT") + "\n"; 
        llSetTimerEvent( 1.0); // timer() イベントを起こす 
    }

    timer() {
        integer t = llGetUnixTime() ;
        // タイマーイベントが次の間隔で割り切れる時刻におこるようにする。
        llSetTimerEvent( INTERVAL - t % INTERVAL); 
        llSetText(  MSG_JAPAN_TIME 
                         + unixtime2yyyymmddhhmmss( t+TZ*3600), 
                         <1,1,1>, 1.0); // 文字形式に変換して表示
    }
}