// SPDX-License-Identifier: MIT // Copyright (c) 2026 Incoprea // Maintain a private link selection // Not compiled or tested in-world // Setup: Place in your own object and touch. Enter add|link, remove|link, or list. Use a rezzed linkset. // Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds. // Notes: Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. Does not change actual viewer selection or build properties. Relinking can invalidate stored numbers; reset after topology changes. // License: see LICENSE in this distribution. // Original Incoprea example. MIT. list selection; integer positive(string input) { if(input=="" || llStringLength(input)>5)return FALSE; integer i; for(i=0;i0; } integer handle; integer channel; closeInput() { if(handle)llListenRemove(handle); handle=0; llSetTimerEvent(0); } respond(string input) { input=llStringTrim(input,STRING_TRIM); if(llStringLength(input)>200) { llOwnerSay("Use at most 200 characters."); return; } if(llGetAttached()) { llOwnerSay("Use a rezzed linkset."); return; } if(input=="list") { llOwnerSay("Working link numbers: "+llList2CSV(selection)); return; } list p=llParseStringKeepNulls(input,["|"],[]); if(llGetListLength(p)!=2 || !positive(llList2String(p,1))) { llOwnerSay("Use add|link or remove|link."); return; } integer link=llList2Integer(p,1); integer total=llGetObjectPrimCount(llGetKey()); if(total<2 || link>total) { llOwnerSay("Real linked prim number required."); return; } integer index=llListFindList(selection,[link]); if(llList2String(p,0)=="add") { if(index==-1) { if(llGetListLength(selection)>=32) { llOwnerSay("Selection full."); return; } selection += [link]; } llOwnerSay("Added link "+(string)link); } else if(llList2String(p,0)=="remove") { if(index!=-1)selection=llDeleteSubList(selection,index,index); llOwnerSay("Removed from working selection."); } else llOwnerSay("Unknown command."); } default { touch_start(integer touches) { if(llDetectedKey(0)!=llGetOwner())return; closeInput(); channel=-10000-(integer)llFrand(1000000000); handle=llListen(channel,"",llGetOwner(),""); llSetTimerEvent(45); llTextBox(llGetOwner(),"Enter add|link, remove|link, or list. Use a rezzed linkset.",channel); } listen(integer c,string name,key speaker,string input) { if(c!=channel || speaker!=llGetOwner())return; closeInput(); respond(input); } timer() { closeInput(); llOwnerSay("Input closed."); } changed(integer flags) { if(flags & CHANGED_OWNER)llResetScript(); } }