In diesem Tutorial möchte ich zeigen, wie ein Avatar über die sogenannte Dropbox-Funktionalität mit einem Objekt interagieren kann. Ganz konkret sieht die Anwendung wie folgt aus. Unseren wohlbekannten web.donator 2.0 will ich erweitern, sodaß der Spender dem web.donator 2.0 eine URL übermitteln kann, welche auf www.avameo.de als Link hinterlegt wird, wie ihr bereits oben rechts sehen könnt. Das heisst also, wir erweitern unsere web 2.0-Anwendung so, dass der Avatar in SL eine beliebige URL an den Donator übermitteln kann. Diese URL wird dann an mein Webserver via http-get gesendet, welcher diese URL in der Datenbank speichert und via PHP hier auf der Seite oben rechts unter der Liste der Donators rendert. Die Übermittlung der URL geschieht über eine vom Donator erstellte Notecard die via Drag & Drop aus dem Avatar-Inventory in das PRIM-Inventory des web.donators 2.0 gezogen wird. Zusätzlich zeige ich, wie man ein Objekt anpassen kann, sodaß die Zahlfunktion “Pay” nicht nur über das PIE-Menu, sondern auch mit Left-Mouse-Click funktioniert. Nachfolgend zeige ich den gesamten Prozess noch einmal zusammenfassend im Detail.
Prim Inventory
Nachdem der Spender (Donator) wie in TechTalk #2 bereits beschrieben, gespendet hat, erhält der Spender vom web.donator 2.0 eine Notecard mir einer Anleitung:
Image may be NSFW.
Clik here to view.
Damit ein Objekt (webdonator) ein anderes Objekt wie eine Notecard an einen Avatar übermitteln kann, muss das zu übermittelnde Objekt in dem Prim-Inventory existieren. Die Notecard, welcher der web.donator 2.0 an den Spender transferiert, muss sich also im Prim-Inventory des web.donators 2.0 befinden und hat in diesem Beispiel den Namen webnote. Um die Notecard mit dem Inventorynamen “webnote” an den Spender zu übergeben, benutze ich folgendes Codefragment im money()-Event-Handler:
Nachfolgender Code wird ausgeführt, wenn über das PIE-Menu bezahlt wurde.
money(key id, integer amount) { llGiveInventory(id, "webnote"); }
Die webnote enthält also lediglich die Anleitung, wie der Spender zu verfahren hat, wenn er seinen Sonsor-Link auf www.avameo.de plazieren möchte. Er muss also eine Notecard selbst erzeugen und dann via Drag & Drop auf den web.donator 2.0 ziehen. Die Notecard muss in der ersten Zeile die gewünschte URL enthalten.
Dropbox-Implementierung
Um es Avataren zu erlauben via Drag & Drop etwas in das Prim-Inventory zu legen, müsst ihr die Funktion llAllowInventoryDrop() aufrufen. Dies mache ich im state_entry()-Event:
Nachfolgender Code bewirkt, dass das Prim via Drag & Drop Objekte in seinem Prim-Inventory aufnehmen kann.
state_entry() { llAllowInventoryDrop(TRUE); }
Sobald nun ein Avatar etwas in das Inventory zieht, wird das change()-Event ausgelost:
Das changed-Event wird ausgelöst, wenn ein Objekt auf das Prim gezogen wurde und sich somit das Prim-Inventory verändert hat.
changed(integer mask) { if(mask & (CHANGED_ALLOWED_DROP | CHANGED_INVENTORY)) { } }
Hier habe ich mit folgendem Programmfragment nur die Notecards ausgelesen und den Erzeuger-Key der Notecard mit der Funktion llGetInventoryCreator() ermittelt:
Das changed-Event wird ausgelöst, wenn ein Objekt auf das Prim gezogen wurde und sich somit das Prim-Inventory verändert hat.
integer num = llGetInventoryNumber(INVENTORY_NOTECARD); integer i = 0; for(i = 0 ; i<num ; i++) { string name = llGetInventoryName(INVENTORY_NOTECARD, i); if(name != "webnote") { key creatorKey = llGetInventoryCreator(name); key query_id = llGetNotecardLine(name,0); query_ids += query_id; creator_keys +=creatorKey; valid_urls+=FALSE; notecards+=name; } }
Am interessantesten ist hier die Funktion llGetNotecardLine(). Diese Funktion führt dazu, dass die erste Zeile der Notecard ausgelesen wird. In der ersten Zeile der Notecard soll ja die URL stehen, die für den Link des Donators verwendet wird, welcher an meinen Web-Server gesendet wird. Die Funktion llGetNotecardLine() gibt allerding nicht den String der ersten Zeile der Notecard zurück, sondern eine Query-ID, weil die Methode sozusagen einen Leseauftrag in einen Queue schiebt. Sobald der Lesenauftrag abgearbeitet wurde, wird wiederrum die Funktion dataserver() vom LSL-Framework aufgerufen. Dies ist eine sogenannte Callback()-Funktion.
Es lohnt ein Blick in die dataserver()-Implementierung:
dataserver wird aufgerufen, wenn eine Zeile aus der Notecard gelesen wurde mit llGetNotecardLine(name,0);
dataserver(key query_id, string data) { key creatorKey = getCreatorKey2QueryKey(query_id); string lowerURL = llToLower(data); string prot = llGetSubString(lowerURL,0,6); if ( prot == "http://" ) { key http_query = llHTTPRequest(data,[HTTP_METHOD,"GET"],""); http_querys+=http_query; urls+=data; }
Hier überprüfe ich zunächst, ob es sich um eine gültigen String handelt der mit http:// beginnt. Wenn dies der Fall ist, erzeuge ich einen Test-Request, um zu prüfen, ob es sich um eine korrekte URL handelt (!). Der Aufruf llHTTPRequest() erzeugt wiederrum ein HTTP-Get-Auftrag an den dataserver. Ist der HTTP-Auftrag abgearbeitet, wird die Callback()-Funktion http_response() vom LSL-Framework aufgerufen. Die Implementierung meiner http_response()-Funktion sieht wie folgt aus:
http_response() wird nach einem llHTTPRequest()-Aufruf aufgerufen.
http_response(key request_id, integer status, list metadata, string body) { integer index = getIndexFromHTTPQuery(request_id); string url = llList2String(urls,index); if(index>=0) { integer untergrenze = index; integer obergrenze = index+1; if(status==200) { valid_urls = llListReplaceList(valid_urls,[TRUE],index,index+1); string creatorName = llKey2Name(llList2String(creator_keys,index)); string donatorkey = llList2String(creator_keys,index); string donatorlink = url; http_querys= llDeleteSubList(http_querys, untergrenze, obergrenze); llHTTPRequest("http://www.avameo.de/name_phpscript.php? donatorkey="+donatorkey+"&donatorlink="+donatorlink, [HTTP_METHOD,"GET"],""); } llRemoveInventory(llList2String(notecards,index)); query_ids = llDeleteSubList(query_ids, untergrenze, obergrenze); creator_keys = llDeleteSubList(creator_keys, untergrenze, obergrenze); valid_urls = llDeleteSubList(valid_urls, untergrenze, obergrenze); urls= llDeleteSubList(urls, untergrenze, obergrenze); notecards = llDeleteSubList(notecards, untergrenze, obergrenze); } }
Wie man leicht sehen kann, bekommt man hier die Variable request_id übergeben, welche der Rückgabewert von llHTTPRequest() zurückgab. Diesen habe ich mit in der Liste http_querys gemerkt, einer globalen Variable. An der selben Stelle habe ich mir die zugehörige URL in einer Liste urls gemerkt. Meine eigene Funktion getIndexFromHTTPQuery() ermittelt den zugehörigen Index zu einer request_id. Wenn die URL okay ist, also Status==200, dann rufe ich das PHP-Script auf mit dem UUID des Donators (donatorkey), sowie den Link (donatorlink). Anschließen räume ich natürlich diverse Listen auf mit dem Aufruf und lösche die Notecard mit llRemoveInventory() die Notecard aus dem Prim-Inventory, damit dieser nicht irgendwann überläuft.
Last but not Least, eine Kleinigkeit. Und zwar die Möglichkeit, die Payment-Menus mit Left-Mouse-Klick zu aktivieren. Das ist ganz einfach und das seht ihr im nächsten Screenshot.
Image may be NSFW.
Clik here to view.
Also dann, bis zum nächsten TechTalk auf www.avameo.de.