// SPDX-License-Identifier: MIT // Copyright (c) 2026 Incoprea // Parse a configuration notecard // Not compiled or tested in-world // Setup: Add a saved plain-text notecard named Config. Try label=Garden and interval=30 on separate lines; touch as owner. // Stop / restore: Remove or disable. Editing Contents cancels the read and resets stored settings. // Notes: This demonstration reports settings without applying them. First equals sign separates key from value; duplicate keys replace earlier values. Limits reading to 50 lines and 20 settings. // License: see LICENSE in this distribution. // Original Incoprea example. MIT. string CARD = "Config"; key pending = NULL_KEY; integer lineNumber; list settings; finish() { pending = NULL_KEY; llSetTimerEvent(0.0); integer i; for (i = 0; i < llGetListLength(settings); i += 2) llOwnerSay(llList2String(settings, i) + " = " + llList2String(settings, i + 1)); llOwnerSay("Read complete; " + (string)(llGetListLength(settings) / 2) + " settings."); } requestLine() { pending = llGetNotecardLine(CARD, lineNumber); llSetTimerEvent(20.0); } default { touch_start(integer count) { if (llDetectedKey(0) != llGetOwner()) return; if (pending != NULL_KEY) return; if (llGetInventoryType(CARD) != INVENTORY_NOTECARD) { llOwnerSay("Add the Config notecard first."); return; } settings = []; lineNumber = 0; requestLine(); } dataserver(key query, string data) { if (query != pending || pending == NULL_KEY) return; if (data == EOF) { finish(); return; } data = llStringTrim(data, STRING_TRIM); integer split = llSubStringIndex(data, "="); if (data != "" && llGetSubString(data, 0, 0) != "#" && split > 0) { string name = llStringTrim(llGetSubString(data, 0, split - 1), STRING_TRIM); string value = ""; if (split < llStringLength(data) - 1) value = llStringTrim(llGetSubString(data, split + 1, -1), STRING_TRIM); integer found = -1; integer i; for (i = 0; i < llGetListLength(settings); i += 2) if (llList2String(settings, i) == name) found = i; if (name != "") { if (found != -1) settings = llListReplaceList(settings, [name, value], found, found + 1); else if (llGetListLength(settings) < 40) settings += [name, value]; else llOwnerSay("Skipped setting beyond the 20-setting limit: " + name); } } ++lineNumber; if (lineNumber >= 50) { llOwnerSay("Stopped at the 50-line limit."); finish(); return; } requestLine(); } timer() { pending = NULL_KEY; llSetTimerEvent(0.0); settings = []; llOwnerSay("Timed out; partial settings discarded. Touch to retry."); } changed(integer flags) { if (flags & (CHANGED_INVENTORY | CHANGED_OWNER)) llResetScript(); } }