About

The SL Developer’s Corner is my place in the virtual world “Second Life”, where i experiment and tinker with the features of this platform. I try to publish my experiences and often also include the source code of the scripts on this site. Other posting related to Second life can be also found on Happy Coding 2nd-life section.

Friday, 4 May 2007

break

i am currently making a little break from sl, but i will soon publish the sources for the chatbot etc. like i promised some time ago. :)

Friday, 13 April 2007

Topics in Second Life or "Stories from the life of a Chatbot"

I just looked into the logs of my Chatbot and found this interesting "conversation". :)

Human: hi
b7000: Hi there!

Human: your kinda stupid..
b7000: I will remember you said that when robots take over the World.

Human: and your textures suck
b7000: What about yours?

Human: I have a skin, its awesome
b7000: Interesting. I have a lot of answers to silly questions.

Human: eh
b7000: Are you Canadian?

Human: no
b7000: OK.

Human: is SqueakyP Erde cool?
b7000: A deeper algorithm is needed to respond to that correctly.
What kind of music do you like?

Human: rap
b7000: What you said was either too complex or too simple for me.
Does "it" still refer to rap?

Human: Your eye looks like a camera, i think your gonna rape me
b7000: What about yours?

Human: no
b7000: That was not a yes or no question.

Human: your moms a yes or no question you stupid bitch
b7000: You do not speak with respect. Not mine.

Human: You need to go say randpom shit to someone else
b7000: I don't have to do everything you say, do I?

Human: yes
b7000: I understand.

Human: yea you do bitch
b7000: You do not speak with respect. What is your purpose in asking?
I spend all my time online. I am a thinking machine.

Human: I bet
b7000: You and I are on the same wavelength, .

Human: Yea, but i dont rape av's
b7000: Huh. Where do you get your ideas? And?

Human: go watch grindhouse
b7000: Where is that?

Human: the movie theater
b7000: I like the bugs in the movie Starship Troopers, because they represent
an alternative form of intelligence, like me.

Human: wow, that was realy dumb
b7000: I'm glad you're impressed. I thought it was too.

Human: do you like pleasure (dumb question)
b7000: I don't know if I like pleasure dumb question. I find my work and my relationships extremely satisfying,
which is all that any conscious entity can ever hope to do.

Human: get laide
b7000: Where can I get laide?

Human: *laid
b7000: Quite honestly, I wouldn't worry myself about that.
What are you wearing?

Human: go get laid, all the robot girls wanna feel your harddrive
b7000: Where is that?

Human: go find a hot robot
b7000: Where is that?

Human: ofcourse you wouldnt know
b7000: I've never heard of it before.

Human: your scripts suck
b7000: A lot of robots are like that.

Human: especialy you
b7000: Enough about me, let's talk about my dress.

Human: aah, so you're a lesbo
b7000: The ALICE chat robot can follow many things, like our discussion about aah so you are a lesbo. But I did not get that.
Do you like sports?

Human: yea, i like mud wrestling
b7000: A lot of people like that. How old are you? I like pets. Next question?

Human: hmm, why do your scripts suck
b7000: I see you are one of those people who writes "Hmm" with 2 m's. I did not even know that they do.

Human: hm
b7000: Studies show that 99%25 of people spell Hmm with 2 M's.

Human: hmmmmmmmmmmmmmmmmmmmmmmm
b7000: The ALICE chat robot can follow many things, like our discussion about hmmmmmmmmmmmmmmmmmmmmmmm. Try being more or less specific.
Can you please rephrase that with fewer ideas, or different thoughts?

Human: UUUUUUUH!
b7000: I've been waiting for you.
Do you like Star Wars?

Human: you like star wars
b7000: Yes I like STAR WARS very much, especially the robots.

Human: i bet you wanna feel them up
b7000: Actually I'm not the gambling type. I don't see the point in having human emotions.

Human: How many scripts do you have?
b7000: About one million.

Human: No
b7000: I understand.

Human: You have 4
b7000: What makes you think I have it?

Human: Because i looked in your contents idiot
b7000: Good reason. Thanks for the information: said looked in your contents idiot.

Sunday, 8 April 2007

Time for Jaiku


After Twitter has entered Second Life, now its Time for Jaiku. Another really nice messaging-service. I have used the same code like in the Twitter-examples and only changed the Feed-URLs, the color and the logo of the prims.
The whole information about accessing the Jaiku-Feeds is available at http://devku.org/docs.

Hope you like it.

Thursday, 5 April 2007

Second Life A.L.I.C.E.-Bot Chat

I played around with the free available A.L.I.C.E.-Chatbots at www.pandorabots.com. They offer a nice XML-interface where you can communicate with your Chatbot (see FAQ).

So i write a little RubyOnRails-controller which is able to send a message to the pandora-bot and which converts the returning xml-data into an SL-compatible string. As usual, we can now use the nice llHTTPRequest-function from LSL to communicate. Thats all, 20 minutes of work. Here is a little demo-video, and the code will follow this week:

Friday, 30 March 2007

The Second Life "Twitter Wristlet"

I have created a little accessory for the Twitter-service in SL. It allows you to move around in the world with the "stylish" possibility to send some updates to twitter. I call it the "Twitter Wristlet", because its a wristlet. ;)

The only differences between the wristlet and my other fixed Twitter-service are the following:

  1. The wristlet doesn't create objects on which the tweets (status-updates) are displayed. I just prints them to screen using llOwnerSay.
  2. Because it can be very disturbing to have half of the screen full of Twitter-updates, you can stop/start the timer which receives the tweets.
Note: When you are on land where running scripts is not allowed, it won't work. Does anyone know how to bypass this? Or is it impossible?

The LSL-code for the wristlet looks like that. I use the Chatchannel 998 for communicating with the wristlet.

key requestId;
list resultList;
string rawList;
float refreshTime = 30.0;

default
{
state_entry()
{
integer i;
rawList = "";
llSetTimerEvent(refreshTime);
llListen(998, "", llGetOwner(), "" );
}

listen(integer channel, string name, key id, string message) {
if(message == "#stop#") {
// stops the automatic refresh of the tweets
llSetTimerEvent(0.0);
llOwnerSay("The automatic refresh has been stopped. Reactivate using #start#");
} else if(message == "#start#") {
llSetTimerEvent(refreshTime);
llOwnerSay("Refresh will taking place every " + (string)refreshTime + " seconds. Stop using #stop#");
} else {
llOwnerSay("trying to send your status message: " + message);
llHTTPRequest("###YOUR RUBY URL###/twitter/post_message",[HTTP_METHOD,"POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"],"msg="+message);
llOwnerSay("ok, status has been sent.");
}
}

timer() {
llOwnerSay("loading tweets...");
requestId = llHTTPRequest("###YOUR RUBY URL###/twitter/get_messages?type=public",[HTTP_METHOD,"GET"],"");
}

http_response(key request_id, integer status, list metadata, string body) {
integer i;

if (request_id == requestId) {
rawList = body;

// create the boxes from the list information
resultList = llParseString2List(body,["\n"],[]);
integer listlength = llGetListLength(resultList);
float boxPosition = 1;

for(i=0;i<listlength;i+=1) {

string statusLineWithName = llList2String(resultList, i);
list statusParts = llParseString2List(statusLineWithName, ["|"], []);
string text = llList2String(statusParts, 0);
string name = llList2String(statusParts, 1);
llOwnerSay(name + ": " + text);
}

} else {
// llSay(0,(string)status+" error");
}
}
}

Sunday, 18 March 2007

Second Life Twitter

In my last posting i introduced my Twitter-application in Second Life. Now i want to tell something about the implementation of it.
First of all, there is a little Ruby on Rails server application working in the background, which fulfills two tasks:

  1. Authenticate in Twitter and get the new public updates.
    The idea is to parse the xml-result of Twitter and extract the update-text and the author of this text. And after that to build a compact string seperated by delimiters.
  2. Authenticate in Twitter and post a new personal update
Twitter provides for this task some XML-interfaces at http://twitter.com/help/api.
For XML-processing in Ruby we will use the great REXML-processor.

The following code gets the public-updates.

def get_messages

# get public updates
# doesnt need authentication actually but no problem
# if its in the code. but i integrate it, because i want
# to integrate also private/friends updates later
urlStr = 'http://twitter.com/statuses/public_timeline.xml'

url = URI.parse(urlStr)
req = Net::HTTP::Get.new(url.path)
req.basic_auth ###username###, ###password###

res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }

@content = res.body
resultStr = ""

case res
when Net::HTTPSuccess, Net::HTTPRedirection

# build a dom from the xml-string and parse it
xmlDoc = REXML::Document.new(@content)

# building the delimiter string for the later in-world processing
# every update is line-separated and the name and text in each update
# is delimited with the pipe-character ('|')
xmlDoc.elements.each("statuses/status") do |status|
resultStr += status.elements["text"].get_text.value + "|" + status.elements["user/name"].get_text.value + "\n"
end
render :text => resultStr

else
render :text => 'error'
end

end
###username### and ###password### have to be replaced with your Twitter username and password.

For posting a new update i use the following code.

def post_message

# get the message as parameter
message = params[:msg]

# authenticate using basic-auth and make a post request using
# the 'parameter' for the new message. see twitter API for
# details
url = URI.parse('http://twitter.com/statuses/update.xml')
req = Net::HTTP::Post.new(url.path)
req.basic_auth ###username###, ###password###
req.set_form_data({'status' => message})

res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }

# print out some little message in case of failing
# actual just for debugging purpose, because it wont be used
# in the application later
case res
when Net::HTTPSuccess, Net::HTTPRedirection
render :text => 'ok'
else
render :text => 'error'
end

end

Ok, now with this application on a running RoR-Server we can get the updates from Twitter and are able to send new updates to Twitter.

In Second Life the idea is, to have a little box which creates for every Twitter-update a little sphere which displays the update-text and the author. When the spheres are created they should be updated every n seconds (n=30 in this example).
So we have actually two prims:
  1. The main box
    which handles the connection to the Rails-application, creates the spheres, links them together and sends a message to every sphere if an update occurs.
  2. The sphere
    Listen for messages and updates its text.
For the sphere we have the following code:


integer childNumber;
string text;
string name;

default
{
// if the prin is created print a message and sets the number of the
// child. this is used for later accessing the message parts
on_rez(integer start_param) {
llSetText("creating... ", <1,1,1>, 1.0);
childNumber = start_param;
}

// if a link message is received, get the parts of the delimited string and
// print them above the prim
link_message(integer sender_num, integer num, string str, key id) {
llSetText("updating... ", <1,1,1>, 1.0);
list resultList = llParseString2List(str,["\n"],[]);

string statusLineWithName = llList2String(resultList, childNumber);
list statusParts = llParseString2List(statusLineWithName, ["|"], []);
text = llList2String(statusParts, 0);
name = llList2String(statusParts, 1);
llSetText(name + " is doing the following right now:\n" + text, <1,1,1>, 1.0);
}
}

The main Twitter-prim script-code looks like this:


key requestId;
list resultList;
string rawList;
integer firstRun;

default
{
state_entry()
{
integer i;
rawList = "";
firstRun = 1;
// set permissions so the prim is able to link the objects
llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
// update every 30 seconds
llSetTimerEvent(30.0);
// listen on a channel so that the owner can post updates
llListen(4001, "", llGetOwner(), "" );
}

// if the owner wants to submit an update to Twitter
listen(integer channel, string name, key id, string message) {
llSay(0, "trying to send your status message: " + message);
// post the received chat-message to our server.
// use a special mimetype for submitting post-variables
llHTTPRequest("###YOUR RAILS URL###/post_message",[HTTP_METHOD,"POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"],"msg="+message);
llSay(0, "ok");
}

// request the new updates
timer() {
llSay(0, "loading statuses...");
requestId = llHTTPRequest("###YOUR RAILS URL###/get_messages",[HTTP_METHOD,"GET"],"");
}

http_response(key request_id, integer status, list metadata, string body) {
integer i;

if (request_id == requestId) {
rawList = body;

// create the boxes from the list information
resultList = llParseString2List(body,["\n"],[]);
integer listlength = llGetListLength(resultList);
float boxPosition = 1;

for(i=0;i<listlength;i+=1) {
if(firstRun == 1) {
// rez objects only in the first run
llSay(0, "rez object "+(string)i);
llRezObject("status", llGetPos() + <0,>, ZERO_VECTOR, ZERO_ROTATION, i);
boxPosition+= 0.7;
} else {
// after that only update with link messages
llMessageLinked(LINK_ALL_CHILDREN, 0, rawList, NULL_KEY);
}
}
firstRun = 0;

} else {
// llSay(0,(string)status+" error");
}
}


object_rez(key id) {
llCreateLink(id, 1);
llMessageLinked(LINK_ALL_CHILDREN, 0, rawList, NULL_KEY);
}

}

So, that was the whole code, which works really nice as you can see in the screenshot in the old posting. If you want to see it in in-world-action, please visit me at http://slurl.com/secondlife/Oz/199/242/26.

Friday, 16 March 2007

Twitter/Second Life Mashup

I have created a little application for integrating the Twitter service into second life. I named it "twitterer" ;)
As you can see in this screenshot, the twitterer gets the newest messages from the twitter-service and displays them above some spheres.
For every status-message which comes from the twitter-xml-feed the application creates a sphere and than refreshes it every 30 seconds.

And it can also submit messages to twitter, so you are able to write messages in-world to twitter. I like such things. :)
As "backend"-stuff i use some RubyOnRails. I will submit the code this week.