Creative Commons License Machine/Kiosk Script
The kiosk is actually just a general purpose state machine engine. The particular state machine that is used for the Creative Commons LIcense Machine is in the Creative Commons License Machine/Kiosk Program.
<lsl> key gBlankTexture = "5748decc-f629-461c-9a36-a35a221fe21f"; // well known
float gTimeOut = 60.0;
integer gUserListener = 0;
integer gLicenseChannel = 0; integer gLicenseListener = 0;
string gNode; list gPath;
// path of nodes, including current node at the end
key gUser = NULL_KEY;
// user we are interacting with
list gParams;
// user parameters, stride two: [ <key>, <value> ... ]
string gAltTrigger; key gArgID; string gArgMessage;
clearUse()
{
gNode = ""; gPath = [ ]; gUser = NULL_KEY; gParams = [ ]; clearNode();
}
clearNode() {
gTimeOut = 30.0;
}
cmdGo(string node) {
gNode = node;
gPath += [ node ];
llMessageLinked(LINK_THIS, 200, node, NULL_KEY);
clearNode();
runAnyAction("init", "", NULL_KEY, "");
llSetTimerEvent(gTimeOut);
if (gUserListener) { llListenRemove(gUserListener); }
gUserListener = llListen(0, "", gUser, "");
}
cmdReset() {
clearUse();
cmdGo("start");
}
cmdBack() {
integer n = llGetListLength(gPath);
if (n >= 2) {
string node = llList2String(gPath, -2);
gPath = llDeleteSubList(gPath, -2, -1);
cmdGo(node);
}
else {
cmdReset();
}
}
cmdUser(key id)
{
gUser = id;
}
cmdAnyone() {
gUser = NULL_KEY;
}
cmdTimeOut(float t) {
gTimeOut = t;
}
cmdImage(string inv) {
llSetTexture(inv, 0);
}
cmdSay(string text) {
llSay(0, text);
}
cmdMovie() { }
cmdGive(string inv) {
llGiveInventory(gUser, inv);
}
cmdWebsite() {
llLoadURL(gUser, "View the Creative Commons web site.",
"http://creativecommons.org/");
}
cmdSet(string param, string value)
{
integer i = llListFindList(gParams, [ param ]);
if (i < 0) {
gParams += [ param, value ];
}
else {
gParams = llListReplaceList(gParams, [ value ], i + 1, i + 1);
}
}
cmdSetUser(string param) {
cmdSet(param, llKey2Name(gUser));
}
cmdSetNow(string param) {
cmdSet(param, llGetSubString(llGetDate(), 0, 3));
}
string getParam(string param) {
integer i = llListFindList(gParams, [ param ]); if (i < 0) return ""; return llList2String(gParams, i + 1);
}
cmdReport(string param, string prompt) {
string value = getParam(param); if (value == "") return; llSay(0, prompt + value);
}
cmdLicenseImage() {
string commercialUse = getParam("commercial-use");
string modifications = getParam("modifications");
string license = "by";
if (commercialUse == "no") { license += "-nc"; }
if (modifications == "no") { license += "-nd"; }
if (modifications == "share") { license += "-sa"; }
string imageName = "lic-" + license;
cmdImage(imageName);
cmdSet("image-key", llGetInventoryKey(imageName));
}
cmdLicenseRez() {
gLicenseChannel = 10000000 + (integer)llFrand(10000000.0);
gLicenseListener = llListen(gLicenseChannel, "", NULL_KEY, "");
rotation r = llEuler2Rot(<0, -45, 0> * DEG_TO_RAD) * llGetRot();
llRezObject("badge",
llGetPos() + <-0.358, 0.0, 0.523> * r,
ZERO_VECTOR,
r,
gLicenseChannel);
}
finishLicense() {
llListenRemove(gLicenseListener);
integer n = llGetListLength(gParams);
integer i;
for (i = 0; i < n; i += 2) {
string param = llList2String(gParams, i);
string value = llList2String(gParams, i + 1);
llSay(gLicenseChannel, param + ":" + value);
}
rotation r = llEuler2Rot(<0, -45, 0> * DEG_TO_RAD) * llGetRot();
vector p = llGetPos() + <-0.358, 0.0, 0.761> * r;
llSay(gLicenseChannel, "done " + (string)p);
}
cmdLicenseDie() {
if (gLicenseChannel != 0) {
llSay(gLicenseChannel, "die");
gLicenseChannel = 0;
}
}
executeStatement(string statement)
{
integer sep = llSubStringIndex(statement, "|");
string tail = "";
if (sep >= 1) {
tail = llGetSubString(statement, sep + 1, -1);
statement = llGetSubString(statement, 0, sep - 1);
}
list parts = llParseString2List(statement, [ " " ], [ ]);
if (tail != "") {
parts += [ tail ];
}
string cmd = llList2String(parts, 0);
string arg1 = llList2String(parts, 1);
string arg2 = llList2String(parts, 2);
if (arg2 == "*") { arg2 = gArgMessage; }
if (cmd == "back") { cmdBack(); }
else if (cmd == "go") { cmdGo(arg1); }
else if (cmd == "reset") { cmdReset(); }
else if (cmd == "user") { cmdUser(gArgID); }
else if (cmd == "anyone") { cmdAnyone(); }
else if (cmd == "timeout") { cmdTimeOut((float)arg1); }
else if (cmd == "image") { cmdImage(arg1); }
else if (cmd == "say") { cmdSay(arg1); }
else if (cmd == "movie") { cmdMovie(); }
else if (cmd == "give") { cmdGive(arg1); }
else if (cmd == "website") { cmdWebsite(); }
else if (cmd == "set") { cmdSet(arg1, arg2); }
else if (cmd == "setUser") { cmdSetUser(arg1); }
else if (cmd == "setNow") { cmdSetNow(arg1); }
else if (cmd == "report") { cmdReport(arg1, arg2); }
else if (cmd == "licenseImage") { cmdLicenseImage(); }
else if (cmd == "licenseRez") { cmdLicenseRez(); }
else if (cmd == "licenseDie") { cmdLicenseDie(); }
else {
llOwnerSay("Unknown command: " + cmd);
}
}
executeBlock(string block) {
list statements = llParseString2List(block,
[ " ; ", " ;", "; ", ";" ], [ ]);
integer n = llGetListLength(statements);
integer i;
for (i = 0; i < n; ++i) {
executeStatement(llList2String(statements, i));
}
}
runAnyAction(string trigger, string altTrigger, key id, string message) {
gAltTrigger = altTrigger; gArgID = id; gArgMessage = message; llMessageLinked(LINK_THIS, 300, trigger, NULL_KEY);
}
default
{
state_entry() {
llSetTexture(gBlankTexture, 0);
llOwnerSay("Touch to start up.");
}
touch_start(integer n)
{
if (llDetectedKey(0) == llGetOwner()) {
state readProgram;
}
else {
llSay(0, "This kiosk is under construction.");
}
}
}
state readProgram {
state_entry() {
llSetTexture(gBlankTexture, 0);
llMessageLinked(LINK_THIS, 100, "", NULL_KEY);
}
state_exit() {
llOwnerSay("main memory: " + (string)llGetFreeMemory());
}
link_message(integer sender, integer num, string str, key id) {
if (num == 101) {
state run;
}
}
touch_start(integer n) { }
on_rez(integer n) { llResetScript(); }
}
state run {
state_entry() {
cmdReset();
}
state_exit() {
llSetTimerEvent(0.0);
}
touch_start(integer n) {
key id = llDetectedKey(0);
if (gUser != NULL_KEY && gUser != id) { return; }
runAnyAction("touch", "", id, "");
llSetTimerEvent(gTimeOut);
}
listen(integer ch, string who, key id, string message) {
if (ch != 0 && ch == gLicenseChannel) {
finishLicense();
return;
}
string trigger = "\"" + llToLower(message) + "\"";
runAnyAction(trigger, "listen", id, message);
llSetTimerEvent(gTimeOut);
}
changed(integer what) {
if (what & CHANGED_INVENTORY) {
state readProgram;
}
}
link_message(integer sender, integer num, string str, key id) {
if (num == 301) {
executeBlock(str);
}
else if (num == 399) {
if (gAltTrigger != "") {
llMessageLinked(LINK_THIS, 300, gAltTrigger, NULL_KEY);
gAltTrigger = "";
}
}
}
timer() {
cmdReset();
}
on_rez(integer n) { llResetScript(); }
} </lsl>