// SPDX-License-Identifier: MIT // Copyright (c) 2026 Incoprea // Validate required notecard sections // Not compiled or tested in-world // Setup: Add a saved plain-text notecard named Notes. Touch as owner to scan once; reset to scan again. Reads at most 100 lines. Edit REQUIRED to your documentation standard. // Stop / restore: Disable or remove the script. It makes no inventory changes. // Notes: Line requests time out after 20 seconds. Lines may be truncated by the simulator; use short lines without embedded inventory. Editing Contents resets the scan. Reports only to the owner. Heading matching is exact after trimming. This checks structure, not the truth or completeness of the contents. // License: see LICENSE in this distribution. // Original Incoprea example. MIT. string CARD="Notes"; integer lineNumber; key pending=NULL_KEY; list REQUIRED=["[About]","[Setup]","[License]"]; list found; requestLine() { pending=llGetNotecardLine(CARD,lineNumber); llSetTimerEvent(20.0); } complete() { pending=NULL_KEY; llSetTimerEvent(0.0); integer i; for(i=0;i0) { llOwnerSay("Reset this script to scan again."); return; } if(llGetInventoryType(CARD)!=INVENTORY_NOTECARD) { llOwnerSay("Add a saved plain-text notecard named Notes."); return; } requestLine(); } dataserver(key query,string data) { if(query!=pending || pending==NULL_KEY) return; if(data==EOF) { complete(); return; } string trimmed=llStringTrim(data,STRING_TRIM); if(llListFindList(REQUIRED,[trimmed])!=-1 && llListFindList(found,[trimmed])==-1) found += [trimmed]; ++lineNumber; if(lineNumber>=100) { llOwnerSay("Stopped at 100 input lines; results may be partial."); complete(); return; } requestLine(); } timer() { pending=NULL_KEY; llSetTimerEvent(0.0); llOwnerSay("Timed out; reset before retrying. Partial values were not reported."); lineNumber=100; } changed(integer flags) { if(flags & (CHANGED_INVENTORY|CHANGED_OWNER)) llResetScript(); } }