Difference between revisions of "User:Luisa Bourgoin/current projects/gposnp"
m |
|||
(2 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
==GPOSNP Project== | ==GPOSNP Project== | ||
here you will find all things GPOSNP, like current release, locations for additional materials located inworld, and of course the official instructions documented | here you will find all things GPOSNP, like current release, locations for additional materials located inworld, and of course the official instructions documented. | ||
Next class will be at ICE, Wednesday the | ====what is GPOSNP ?==== | ||
"a controller cube containing instruction lists inside notecards" pretty much summarizes the whole approach | |||
Next class will be at ICE, Wednesday the 12th May of 2010 (lookup '''ICE LVL''' inside Events for ''Home, sweet home'' class) | |||
additional scripts, slides and notes can be obtained here: | |||
{{SLurl | |||
|region=Lassie | |||
|x=187 | |||
|y=168 | |||
|z=49 | |||
|title=ICE classes board | |||
}} | |||
An example instruction list demonstrating the usual "Hello World" program. Place the following code inside a Notecard, add that to a plywood prim cube, add a GPOSNP script inside and click the cube. | |||
Hello World | |||
Oh, yes, that's the leanest "Hello World" program example ever :D More verbose examples are [http://luh1.gofreeserve.com/gposnp/colorizing%20for%20stompers.html example Stompers] and [http://luh1.gofreeserve.com/gposnp/colorizing%20for%20drawbridge.html example Drawbridge] | |||
===The instruction keywords=== | ===The instruction keywords=== | ||
Line 11: | Line 29: | ||
the color of the box can be | the color of the box can be | ||
# '''''green''''' for startable, that means not currently running | # '''''green''''' for startable, that means not currently running | ||
# '''''yellow''''' for program is running, but currently pausing. click does continue | # '''''yellow''''' for program is running, but currently pausing. click does completely stop execution (only inter-object communication can continue a pausing program) | ||
# '''''red''''' for emergency stopable by a click, meaning things are running at the moment | # '''''red''''' for emergency stopable by a click, meaning things are running at the moment | ||
Line 42: | Line 60: | ||
;chat | ;chat | ||
: '''chat''', ''text'' | : '''chat''', ''text'' | ||
: chats some text | : chats some text. mostly used for chatting otherwise interpreted keywords, or specifically adressing channel 0 | ||
;counter | ;counter | ||
Line 53: | Line 71: | ||
;restart | ;restart | ||
: '''restart'' | : '''restart''' | ||
: | : restarting the program | ||
;authorize | ;authorize | ||
: '''authorize''', ''name'' | : '''authorize''', ''name'' | ||
: adds '' | : adds ''name'' to the list of people to listen to, or accepting their clicks. ''name'' can point onto objects. | ||
: ''neither using assumingly secret chat channels nor relying onto names can provide real security. use UUID keying instead'' | |||
;public access | ;public access | ||
Line 67: | Line 86: | ||
: '''volume''', ''number'' | : '''volume''', ''number'' | ||
: the controller can chirp some noised, the volume is adjusted by this call onto ''number'' percent | : the controller can chirp some noised, the volume is adjusted by this call onto ''number'' percent | ||
: affects currently played sounds or soundloops | |||
;playsound | ;playsound | ||
: '''playsound''', ''sound'' | : '''playsound''', ''sound'' | ||
: plays ''sound'' which can be any soundfile dropped inside the box | : plays ''sound'' which can be any soundfile dropped inside the box (or a UUID of sound asset) | ||
''these are inside development'' | |||
;define | |||
: '''define''', ''pattern'', ''substitution'' | |||
: define a variable. the controller can accept chat like | |||
: '''define''', ''controllername'', ''pattern'', ''substitution'' | |||
: from external connections and from there on, all instructions sent out undergo substitutions. this does affect urls on http requests, too. http results can overwrite/re-define variables. this way can be harnessed to store information dynamically, and to communicate stored informations. | |||
: it is limited so far, but has been darely needed. | |||
;http | |||
: '''http''', ''url'' | |||
: request some more instructions from the network, continueing on notecard afterwards | |||
;loopsound | |||
: '''loopsound''', ''sound'' | |||
: immediately starts continual playback of ''sound'' which can be any soundfile dropped inside the box | |||
: discontinues over controller standby pauses | |||
;silence | |||
: '''silence''' | |||
: can be quiet relaxing | |||
;await | |||
: '''await''', ''chat string'' | |||
: stopping program, awaiting ''chat string'' on currently active channel to continue | |||
;await click | |||
: '''await click''' | |||
: stopping program, awaiting mouseclick on controller to proceed. access authorisation still applies | |||
;jump | |||
: '''jump''', ''offset'' | |||
: adjusts current program line to offset | |||
;jump if | |||
: a 1st halfbaken approach on conditional program execution | |||
===Controller source code=== | ===Controller source code=== | ||
There are different versions available. The code below is used inside classroom and based upon 1st release, includes bugfixes. In comparison to original, there are some security considerations included and timing is handled differently. | |||
Firstrelease 1 from 4/23/2010 [[User:Luisa_Bourgoin/current projects/gposnp/version1]], which is now historical | |||
This version below (2) makes a good start, does contain most of the instruction calls documented above: | |||
<lsl> | <lsl> | ||
Line 94: | Line 156: | ||
// ...more conditional branching, maybe nameable registers | // ...more conditional branching, maybe nameable registers | ||
// release | // release 2 (push on update) | ||
//preferences values: | //preferences values: | ||
Line 106: | Line 168: | ||
integer access_public = FALSE; | integer access_public = FALSE; | ||
key ownerID; | |||
list access_names; | list access_names; | ||
string confNoteName; | string confNoteName = ""; | ||
integer notecard_line; | integer notecard_line; | ||
integer notecard_lastline; | integer notecard_lastline; | ||
Line 123: | Line 186: | ||
process(string data) | process(string data) | ||
{ | { | ||
if(llStringLength(data) == 0) return; | |||
list instructions = llCSV2List(data); //split recieved message | list instructions = llCSV2List(data); //split recieved message | ||
string command = llList2String(instructions,0); | string command = llStringTrim(llList2String(instructions,0), STRING_TRIM_HEAD); | ||
if(debug) llSetText(data, <1,1,1>, 0.5); | if(debug) llSetText(data, <1,1,1>, 0.5); | ||
Line 133: | Line 197: | ||
else if( command == "display") { | else if( command == "display") { | ||
llSetText(llGetSubString(data,llStringLength(command)+1,-1), <1,1,1>, 0.5); | llSetText(llGetSubString(data,llStringLength(command)+1,-1), <1,1,1>, 0.5); | ||
llSleep(timing_speed); | |||
} | } | ||
else if( command == "debug") { | else if( command == "debug") { | ||
Line 154: | Line 219: | ||
else if( command == "chat") { | else if( command == "chat") { | ||
llSay(0, llGetSubString(data,llStringLength(command)+1,-1)); | llSay(0, llGetSubString(data,llStringLength(command)+1,-1)); | ||
llSleep(timing_speed); | |||
} | } | ||
else if( command == "counter") { | else if( command == "counter") { | ||
Line 168: | Line 234: | ||
} | } | ||
else if( command == "authorize") { | else if( command == "authorize") { | ||
string name = llList2String(instructions,1); | |||
if(llListFindList(access_names, [name]) < 0) access_names += name; | |||
} | } | ||
else if( command == "public access") { | else if( command == "public access") { | ||
Line 174: | Line 241: | ||
} | } | ||
else if( command == "volume") { | else if( command == "volume") { | ||
volume = llList2Float(instructions,1); | volume = llList2Float(instructions,1) / 100; | ||
} | } | ||
else if( command == "playsound") { | else if( command == "playsound") { | ||
llPlaySound(llList2String(instructions,1), volume); | llPlaySound(llList2String(instructions,1), volume); | ||
//llPreloadSound(llList2String(instructions,1)); | //llPreloadSound(llList2String(instructions,1)); | ||
llSleep(timing_speed); | |||
} | } | ||
else { | else { | ||
data = llStringTrim(data, STRING_TRIM); | |||
if(! internal_part) | if(llStringLength(data) > 0) { | ||
if(! internal_part) llSay(broadcast_channel , data); // or llShout() | |||
else llMessageLinked(LINK_ALL_OTHERS, broadcast_channel, data, NULL_KEY); // or LINK_SET | |||
llSleep(timing_speed); | |||
} | |||
} | } | ||
} | } | ||
Line 193: | Line 264: | ||
llSetText("", <1,1,1>, 0.5); | llSetText("", <1,1,1>, 0.5); | ||
if(! internal_part) llSetColor(<0,1,0>, ALL_SIDES); | if(! internal_part) llSetColor(<0,1,0>, ALL_SIDES); | ||
ownerID = llGetOwner(); | |||
access_names = [] + llKey2Name(llGetOwner()); | access_names = [] + llKey2Name(llGetOwner()); | ||
listener = llListen(broadcast_channel,"","",""); | listener = llListen(broadcast_channel,"","",""); | ||
Line 206: | Line 278: | ||
touch_start(integer total_number) | touch_start(integer total_number) | ||
{ | { | ||
if(! access_public) if (llListFindList(access_names, [llDetectedName(0)]) < 0) {return;} | if(! access_public) if(llListFindList(access_names, [llDetectedName(0)]) < 0) {return;} | ||
if(running || running == SUSPENDED) { | if(running || running == SUSPENDED) { | ||
if(! internal_part) { | if(! internal_part) { | ||
Line 229: | Line 302: | ||
listen(integer channel, string name, key id, string data) | listen(integer channel, string name, key id, string data) | ||
{ | { | ||
if(! access_public) if(llListFindList(access_names, [name]) < 0) {return;} | if(! access_public) if(llListFindList(access_names, [name]) < 0 || llList2Key(llGetObjectDetails(id, [OBJECT_OWNER]), 0) != ownerID) {return;} | ||
list instructions = llCSV2List(data); //split recieved message | list instructions = llCSV2List(data); //split recieved message | ||
Line 260: | Line 333: | ||
{ | { | ||
if(query_id == notecard_request && data != EOF && running == TRUE) { | if(query_id == notecard_request && data != EOF && running == TRUE) { | ||
process(data); | if(data != "") process(data); | ||
if((notecard_line -1) >= notecard_lastline) { | if((notecard_line -1) >= notecard_lastline) { | ||
running = FALSE; | running = FALSE; | ||
Line 274: | Line 347: | ||
//eof | //eof | ||
</lsl> | </lsl> | ||
Latest revision as of 23:28, 8 May 2010
GPOSNP Project
here you will find all things GPOSNP, like current release, locations for additional materials located inworld, and of course the official instructions documented.
what is GPOSNP ?
"a controller cube containing instruction lists inside notecards" pretty much summarizes the whole approach
Next class will be at ICE, Wednesday the 12th May of 2010 (lookup ICE LVL inside Events for Home, sweet home class)
additional scripts, slides and notes can be obtained here: ICE classes board🖈
An example instruction list demonstrating the usual "Hello World" program. Place the following code inside a Notecard, add that to a plywood prim cube, add a GPOSNP script inside and click the cube.
Hello World
Oh, yes, that's the leanest "Hello World" program example ever :D More verbose examples are example Stompers and example Drawbridge
The instruction keywords
the controller box understands reset, start, pause and continue commands from currently active chat channel, which can be unreachable from chatbar. a click onto a running box will stop the program.
the color of the box can be
- green for startable, that means not currently running
- yellow for program is running, but currently pausing. click does completely stop execution (only inter-object communication can continue a pausing program)
- red for emergency stopable by a click, meaning things are running at the moment
the possible keywords for program notecards are, as implemented so far:
- channel
- channel, chatchannel
- switches all communications into chatchannel
- timing
- timing, timing
- the default execution timing of instructions will be set to timing seconds. fractions of seconds are allowed
- delay
- delay, seconds
- sets execution to sleeping some seconds
- display
- display, text
- hoovertext text above controller box
- debug
- debug
- hoovertexting currently executed instruction above controller box. used with slow default timing, this can be very helpfull for observing the activity going on
- pause
- pause
- will set controller into idling, again. this consumes as much power as beeing switched off. it's still listening onto chat commands, on last used channel only. external controller prims can use "continue, controllername" to continue with paused program
- chat
- chat, text
- chats some text. mostly used for chatting otherwise interpreted keywords, or specifically adressing channel 0
- counter
- counter, number
- initializes the loop counter with number
- countdown
- countdown
- jumps back onto last counter, number definition if the counter still isn't empty
- restart
- restart
- restarting the program
- authorize
- authorize, name
- adds name to the list of people to listen to, or accepting their clicks. name can point onto objects.
- neither using assumingly secret chat channels nor relying onto names can provide real security. use UUID keying instead
- public access
- public access
- sets controller box into public mode, without any user restrictions
- volume
- volume, number
- the controller can chirp some noised, the volume is adjusted by this call onto number percent
- affects currently played sounds or soundloops
- playsound
- playsound, sound
- plays sound which can be any soundfile dropped inside the box (or a UUID of sound asset)
these are inside development
- define
- define, pattern, substitution
- define a variable. the controller can accept chat like
- define, controllername, pattern, substitution
- from external connections and from there on, all instructions sent out undergo substitutions. this does affect urls on http requests, too. http results can overwrite/re-define variables. this way can be harnessed to store information dynamically, and to communicate stored informations.
- it is limited so far, but has been darely needed.
- http
- http, url
- request some more instructions from the network, continueing on notecard afterwards
- loopsound
- loopsound, sound
- immediately starts continual playback of sound which can be any soundfile dropped inside the box
- discontinues over controller standby pauses
- silence
- silence
- can be quiet relaxing
- await
- await, chat string
- stopping program, awaiting chat string on currently active channel to continue
- await click
- await click
- stopping program, awaiting mouseclick on controller to proceed. access authorisation still applies
- jump
- jump, offset
- adjusts current program line to offset
- jump if
- a 1st halfbaken approach on conditional program execution
Controller source code
There are different versions available. The code below is used inside classroom and based upon 1st release, includes bugfixes. In comparison to original, there are some security considerations included and timing is handled differently.
Firstrelease 1 from 4/23/2010 User:Luisa_Bourgoin/current projects/gposnp/version1, which is now historical
This version below (2) makes a good start, does contain most of the instruction calls documented above:
<lsl> // GPOSNP Project - 'general purpose open source notecarded programming' // // initiated by Luisa Bourgoin 7/2008 for useage inside TUi NEO class // fair use only !! this has been created for educational use initially, respect it's origins // you are free to: // * enhance this code, as long as you publish your additions // * use, for builts (even for sale) but keeping this program piece editable // * combine with listener/recieving interactive parts, even closed source ones
// Todo: fix this stuff, and get a new name for it!!1!
// add soundfiles preloading? could be done by helper script
// caching notes inside memory! getting rid of dataserver events during showtime. Maybe
// llLinkeMessage() connected program storage script?
// ...preparsing notes.
// ...more conditional branching, maybe nameable registers
// release 2 (push on update)
//preferences values: integer broadcast_channel = 0; integer listener; integer internal_part = FALSE;
integer running = FALSE; integer SUSPENDED = -2; float timing_speed = 2.0;
integer access_public = FALSE; key ownerID; list access_names;
string confNoteName = ""; integer notecard_line; integer notecard_lastline; key notecard_lastline_quid; key notecard_request;
integer counter = 0; integer counter_line = 0;
float volume = 1.0; //for sounds integer debug = FALSE;
// if there is anything as in central intelligence, this implements it ... eventually process(string data) {
if(llStringLength(data) == 0) return; list instructions = llCSV2List(data); //split recieved message string command = llStringTrim(llList2String(instructions,0), STRING_TRIM_HEAD); if(debug) llSetText(data, <1,1,1>, 0.5); // parse some instructions if( llGetSubString(command, 0, 0) == "#" || llGetSubString(command, 0, 1) == "////") { //commented out } else if( command == "display") { llSetText(llGetSubString(data,llStringLength(command)+1,-1), <1,1,1>, 0.5); llSleep(timing_speed); } else if( command == "debug") { debug = TRUE; //to debug or not debug, that is the question! (shaking knees) } else if( command == "delay") { llSleep(llList2Float(instructions,1)); } else if( command == "timing") { timing_speed = llList2Float(instructions,1); } else if(command == "pause") { if(! internal_part) llSetColor(<1,1,0>, ALL_SIDES); running = SUSPENDED; } else if( command == "channel") { broadcast_channel = llList2Integer(instructions,1); llListenRemove(listener); listener = llListen(broadcast_channel,"","",""); } else if( command == "chat") { llSay(0, llGetSubString(data,llStringLength(command)+1,-1)); llSleep(timing_speed); } else if( command == "counter") { counter = llList2Integer(instructions,1); counter_line = notecard_line; } else if( command == "countdown") { if(counter-- > 1) { notecard_line = counter_line; } } else if( command == "restart") { notecard_line = 1; } else if( command == "authorize") { string name = llList2String(instructions,1); if(llListFindList(access_names, [name]) < 0) access_names += name; } else if( command == "public access") { access_public = TRUE; } else if( command == "volume") { volume = llList2Float(instructions,1) / 100; } else if( command == "playsound") { llPlaySound(llList2String(instructions,1), volume); //llPreloadSound(llList2String(instructions,1)); llSleep(timing_speed); } else { data = llStringTrim(data, STRING_TRIM); if(llStringLength(data) > 0) { if(! internal_part) llSay(broadcast_channel , data); // or llShout() else llMessageLinked(LINK_ALL_OTHERS, broadcast_channel, data, NULL_KEY); // or LINK_SET llSleep(timing_speed); } }
}
default {
state_entry() { llSetText("", <1,1,1>, 0.5); if(! internal_part) llSetColor(<0,1,0>, ALL_SIDES); ownerID = llGetOwner(); access_names = [] + llKey2Name(llGetOwner()); listener = llListen(broadcast_channel,"","",""); confNoteName = llGetInventoryName( INVENTORY_NOTECARD ,0 ); notecard_lastline_quid = llGetNumberOfNotecardLines(confNoteName); }
on_rez(integer start_params) { llResetScript(); } touch_start(integer total_number) { if(! access_public) if(llListFindList(access_names, [llDetectedName(0)]) < 0) {return;} if(running || running == SUSPENDED) { if(! internal_part) { llWhisper(0, "stopping "+confNoteName); llSetColor(<0,1,0>, ALL_SIDES); } running = FALSE; } else { if(! internal_part) { llWhisper(0, "running program "+confNoteName); llSetColor(<1,0,0>, ALL_SIDES); } running = TRUE; debug = FALSE; notecard_line = 1; notecard_request = llGetNotecardLine( confNoteName, notecard_line++ - 1 ); // request line notecard_lastline_quid = llGetNumberOfNotecardLines(confNoteName); // refresh! otherwise, editing those would kill your patience :) } } listen(integer channel, string name, key id, string data) { if(! access_public) if(llListFindList(access_names, [name]) < 0 || llList2Key(llGetObjectDetails(id, [OBJECT_OWNER]), 0) != ownerID) {return;} list instructions = llCSV2List(data); //split recieved message string command = llList2String(instructions,0); string target = llList2String(instructions,1);
if(target == llGetObjectName()) { if(command == "reset") { llResetScript(); } else if(command == "start") { if(! internal_part) llSetColor(<1,0,0>, ALL_SIDES); running = TRUE; debug = FALSE; notecard_line = 1; notecard_request = llGetNotecardLine( confNoteName, notecard_line++ - 1 ); // request line notecard_lastline_quid = llGetNumberOfNotecardLines(confNoteName); // refresh! } else if(command == "pause") { if(! internal_part) llSetColor(<1,1,0>, ALL_SIDES); running = SUSPENDED; } else if(command == "continue" && running == SUSPENDED) { if(! internal_part) llSetColor(<1,0,0>, ALL_SIDES); running = TRUE; notecard_request = llGetNotecardLine( confNoteName, notecard_line++ - 1 ); // request line } } } dataserver(key query_id, string data) { if(query_id == notecard_request && data != EOF && running == TRUE) { if(data != "") process(data); if((notecard_line -1) >= notecard_lastline) { running = FALSE; if(! internal_part) llSetColor(<0,1,0>, ALL_SIDES); } if(running == TRUE) notecard_request = llGetNotecardLine( confNoteName, notecard_line++ - 1 ); } else if(query_id == notecard_lastline_quid) { notecard_lastline = (integer)data; //inconsequent! } }
} //eof </lsl>