Second Lifeで気に入ったアイテムの記録です あ、ウソです。スクリプトとか他のことも書いてます

2008/12/21

昨日のコードのこと

昨日のコードですけど、dataserverまわりって
これでいいですよね。

一度書いて、うまくいったコードって
なかなか振り返ることもなかったので
全く気づいてなかったです。
いま、割とメモリを気にする処理を書いてて
いろいろ見直してて気づきました。


dataserver(key query_id, string data){
if (query_id == key_ReadQ){
if (data == EOF)
state idle;

f_Analysis_note(data);
}else if (query_id == key_GetLineNumQ){
gl_i_loop_max = (integer)data;
if (gl_i_loop_max<=0){
llOwnerSay(gl_s_notecard+" is line Zero");
state idle;
}
}
key_ReadQ = llGetNotecardLine(gl_s_notecard, gl_i_loop_cnt);
++gl_i_loop_cnt;
llSetText("Read Note["+gl_s_notecard+"]"
+"\n("+(string)(gl_i_loop_cnt)+"/"+(string)(gl_i_loop_max)+")"
,GL_V_TEXT,1.0);
}


この2行は
key_ReadQ = llGetNotecardLine(gl_s_notecard, gl_i_loop_cnt);
++gl_i_loop_cnt;

当然、こう書いてもいいです。
key_ReadQ = llGetNotecardLine(gl_s_notecard, gl_i_loop_cnt++);

また、これは
gl_i_loop_max = (integer)data;
if (gl_i_loop_max<=0){

これでもいいですね
if ((gl_i_loop_max = (integer)data)<=0){

2008/12/20

久しぶりにNSFWではないのです

どれみちゃんのDVDをぶっ続けで見ています。
ああ、ついに4箱目の最後の最後にきました。
これが終わったら、ナイショシリーズに入ります。

ということで、よくあるやつなんですけど
人が触ったらなんか言うやつです。
ちょっといろいろ事情があって、珍しくソースを貼ったりしてます。
※触るはtouchにあらず

何かオブジェクトを出して、こんな内容のノートと、その下のスクリプトをいれるとできます。
※ノートの名前は"!!Message"ね
#   同じ人にはメッセージを出さないオブジェクト
# ※一定時間経過すると同じ人でもメッセージを出す
#
# 人が触れた回数をDescriptionにセットする
# ※メッセージを出すロジックと同じ
#
# ※一定時間内にメモリがあふれるほど
# 違う人が触ると死にます
#

#表示するメッセージ
# 複数あると改行をつけてつながる
# ※指定しない場合は、メッセージを出さない
MESSAGE:Cheerful
MESSAGE:さいなら

#同じ人が触れた場合、一定時間の間はメッセージを出さない
# ※秒
LEAD_SEC:10

#SETTEXTでのデバッグ表示
# 表示するならON
DEBUG:ON

#最後に人が触れてから、一定時間後に
# メモリクリア処理を行う
# ※秒
SLEEP:30

#オブジェクトがファントムにするか
# ファントムならON
PHANTOM:ON

これ<>は、全角にしてあります。
key GL_K_NULL = NULL_KEY;
vector GL_V_TEXT = <0.0,1.0,1.0>;

string gl_s_message = "";
integer gl_i_lead_sec = 10;
integer gl_i_debug = FALSE;
float gl_f_sleep = 3.0;
integer gl_i_phantom = FALSE;

list gl_l_av_key = [];
list gl_l_time = [];
list gl_l_av_nm = [];

//========== note ==========
string gl_s_note = "!!Message";
key key_GetLineNumQ=NULL_KEY;
key key_ReadQ=NULL_KEY;
integer gl_i_loop_cnt = 0;
integer gl_i_loop_max = 0;
string gl_s_comment_mark = "#";
string gl_s_separate_mark = ":";

// 設定noteの解析
f_Analysis_note(string arg_s_buff)
{
integer idx;
arg_s_buff = llStringTrim(arg_s_buff,STRING_TRIM);
integer i_len = llStringLength(arg_s_buff);
if(i_len==0)
return; // empty
if(llSubStringIndex(arg_s_buff,gl_s_comment_mark)==0)
return; // comment line
idx = llSubStringIndex(arg_s_buff,gl_s_separate_mark);
if(idx<=0) // no delimiter or no key
return;
if(idx+1==i_len)
return; // no data

string s_key = llToUpper(llStringTrim(llGetSubString(arg_s_buff,0,idx-1),STRING_TRIM_TAIL));
string s_data = llStringTrim(llGetSubString(arg_s_buff,idx+1,-1),STRING_TRIM_HEAD);
if(s_data=="")
return;

if(s_key=="MESSAGE"){
if(gl_s_message!="")
gl_s_message += "\n";
gl_s_message += s_data;
}else if(s_key=="LEAD_SEC"){
gl_i_lead_sec = (integer)s_data;
}else if(s_key=="DEBUG"){
if(s_data=="ON")
gl_i_debug = TRUE;
else
gl_i_debug = FALSE;
}else if(s_key=="PHANTOM"){
if(s_data=="ON")
gl_i_phantom = TRUE;
else
gl_i_phantom = FALSE;
}else if(s_key=="SLEEP"){
gl_f_sleep = (float)s_data;
}
}

f_im(key arg_k_av)
{
integer i_idx = llListFindList(gl_l_av_key,[arg_k_av]);
integer b_say = FALSE;
integer i_now_sec = llGetUnixTime();
if(i_idx<0){
// リストにない場合は、追加してSay
gl_l_av_key += [arg_k_av];
gl_l_time += [i_now_sec];
gl_l_av_nm += [llKey2Name(arg_k_av)];
b_say = TRUE;
}else{
integer i_sec = llList2Integer(gl_l_time,i_idx);
// リストにある場合は、時間を更新して後ろに回す
gl_l_av_key = llDeleteSubList(gl_l_av_key,i_idx,i_idx) + [llList2Key(gl_l_av_key,i_idx)];
gl_l_time = llDeleteSubList(gl_l_time,i_idx,i_idx) + [i_now_sec];
gl_l_av_nm = llDeleteSubList(gl_l_av_nm,i_idx,i_idx) + [llList2String(gl_l_av_nm,i_idx)];
if((i_sec+gl_i_lead_sec)<i_now_sec){
// 最後に踏んだ時間から一定時間経過していたらSay
b_say = TRUE;
}
}
if(b_say == TRUE){
if(gl_s_message!="")
llInstantMessage(arg_k_av,gl_s_message);
llSetObjectDesc((string)(1+(integer)llGetObjectDesc()));
}
}

integer f_release()
{
integer i_cnt = llGetListLength(gl_l_av_key);
integer i_max = i_cnt;
integer i_from_idx = 0;
integer i_to_idx = -1;
integer i=0;
integer i_now_sec = llGetUnixTime()-gl_i_lead_sec;
for (i=0;i<i_max;++i){
if(llList2Integer(gl_l_time,i)<i_now_sec){
i_to_idx = i;
--i_cnt;
}else{
jump loop_end;
}
}
@ loop_end;
if(i_to_idx>=0){
gl_l_av_key = llDeleteSubList(gl_l_av_key,i_from_idx,i_to_idx);
gl_l_time = llDeleteSubList(gl_l_time,i_from_idx,i_to_idx);
gl_l_av_nm = llDeleteSubList(gl_l_av_nm,i_from_idx,i_to_idx);
}
return i_cnt;
}

f_debug_disp(float arg_f_sleep)
{
if(gl_i_debug==FALSE){
llSetText("",GL_V_TEXT,1.0);
return;
}
integer i = llGetListLength(gl_l_av_key);
string s_msg = "";
for (--i;i>=0;--i){
s_msg += (string)llList2String(gl_l_av_nm,i)+"("+(string)llList2Integer(gl_l_time,i)+")\n";
}
s_msg += "sleep("+f2s(arg_f_sleep)+")\n";
s_msg += "lead("+(string)gl_i_lead_sec+")";

llSetText(s_msg,GL_V_TEXT,1.0);
}

string f2s(float f)
{
string s_tmp = (string)f;
integer idx = llSubStringIndex(s_tmp,".");
if(idx<0)
return s_tmp;
string s_chr="";
integer i = llStringLength(s_tmp) -1;
for (;i>idx;i--){
s_chr = llGetSubString(s_tmp,i,i);
if(s_chr!="0"){
if(s_chr==".")
return llGetSubString(s_tmp,0,i-1);
else
return llGetSubString(s_tmp,0,i);
}
}
return llGetSubString(s_tmp,0,idx-1);
}

default
{
state_entry()
{
state readnote;
}
collision_start(integer total_number){}
}

state idle
{
state_entry()
{
llVolumeDetect(gl_i_phantom);
llSetStatus(STATUS_PHANTOM,gl_i_phantom);
}
state_exit()
{
llSetTimerEvent(0.0);
}
collision_start(integer total_number)
{
llSetTimerEvent(0.0);
f_debug_disp(0.0);
integer i=0;
for(i=0;i<total_number;++i)
f_im(llDetectedKey(i));
llSetTimerEvent(gl_f_sleep);
f_debug_disp(gl_f_sleep);
}
timer()
{
float f_sleep = 0.0;
llSetTimerEvent(f_sleep);
if(f_release()>0){
f_sleep = gl_f_sleep;
llSetTimerEvent(f_sleep);
}
f_debug_disp(f_sleep);
}
changed(integer i_change)
{
if(i_change&CHANGED_INVENTORY)
state readnote;
}
}

// 設定noteの読み込み
state readnote
{
state_entry()
{
if(llGetInventoryType(gl_s_note)!=INVENTORY_NOTECARD)
state idle;

gl_s_message = "";
gl_i_lead_sec = 10;
gl_i_debug = FALSE;
gl_f_sleep = 3.0;
gl_i_phantom = FALSE;

key_GetLineNumQ = llGetNumberOfNotecardLines(gl_s_note);
gl_i_loop_cnt = 0;
llSetText("Analyze Note["+gl_s_note+"]",GL_V_TEXT,1.0);
}
state_exit()
{
llSetText("",GL_V_TEXT,1.0);
}
dataserver(key query_id, string data){
if (query_id == key_ReadQ){
if (data == EOF)
state idle;

f_Analysis_note(data);

key_ReadQ = llGetNotecardLine(gl_s_note, gl_i_loop_cnt);
++gl_i_loop_cnt;
llSetText("Read Note["+gl_s_note+"]"
+"\n("+(string)(gl_i_loop_cnt)+"/"+(string)(gl_i_loop_max)+")"
,GL_V_TEXT,1.0);
}else if (query_id == key_GetLineNumQ){
gl_i_loop_max = (integer)data;
if (gl_i_loop_max<=0){
llOwnerSay(gl_s_note+" is line Zero");
state idle;
}

key_ReadQ = llGetNotecardLine(gl_s_note, gl_i_loop_cnt);
++gl_i_loop_cnt;
llSetText("Read Note["+gl_s_note+"]"
+"\n("+(string)(gl_i_loop_cnt)+"/"+(string)(gl_i_loop_max)+")"
,GL_V_TEXT,1.0);
}
}
collision_start(integer total_number){}
}

他の人のがどうやってるのか知りませんが
結局は、触れたkeyをとっておいて、それがリストにあるかどうか(前に触れたか)
チェックしてるだけです。
何かがふれるたびに動くので、どこまで処理を軽く仕上げられるかがポイントなんでしょう。
なんだか、こんなの...って感じがしますね。
これなら、普通に毎回IMしてる方がマシな気がします。
IMされてる方はたまったもんじゃないのですが。

ああ、よく考えたら、NOTEに書かれたON/OFFをTRUE/FALSEに変換するのは
関数化した方がいいですね。
これだと二個ですけど、もっと増えるとえらいことです。
integer f_cnv_ONOFF(arg_s_str)
{
if(arg_s_str=="ON")
return TRUE;
return FALSE;
}

デバッグモードのためだけに、名前をリストで残してるのもウザイところですが。
まあ、そのへんはハハハという感じで。

一応、新店舗にも0L$で置いてます(気分次第で撤去ですが)。
タコが守ってますので、要注意。