Parcel Scanning
Scanning parcels within a simulator can be a slow process if not done efficiently. In order to solve this I devised a neater way of scanning parcels that can reduce the number of operations required by 50% or more.
The following script by Haravikk Mistral is provided as-is, and will simply test the simulator you place it in for land-owners, then every 24 hours it will re-scan and inform you of any new land-owners, or any that have left. It will do this by treating the region first as a square 256 units wide, test it, and if required will sub-divide it in order to narrow down its search to detect individual parcels.
<lsl>list oldOwners = []; list oldGroups = [];
list newOwners = []; list newGroups = [];
list gridAreas = []; list gridDefault = [];
integer operations = 0;
default {
state_entry() { gridAreas = gridDefault = [0.0, 0.0, 255.0, 255.0]; llSetTimerEvent(0.01); } timer() { float cx = llList2Float(gridAreas, 0); float cy = llList2Float(gridAreas, 1); float tx = llList2Float(gridAreas, 2); float ty = llList2Float(gridAreas, 3); gridAreas = llDeleteSubList( (gridAreas = []) + gridAreas, 0, 3 ); float gridSize = llCeil((tx - cx) / 10.0); if (gridSize <= 0.0) gridSize = 1.0; key owner1 = NULL_KEY; key owner2 = NULL_KEY; key owner3 = NULL_KEY; float x = cx; float y = cy; integer pattern = 0; @gridProcess; ++operations; list details = llGetParcelDetails( <x, y, 0.0>, [ PARCEL_DETAILS_OWNER, PARCEL_DETAILS_GROUP, PARCEL_DETAILS_AREA ] ); key k = llList2Key(details, 0); key g = llList2Key(details, 1); list l = [k]; if (!(~llListFindList(oldOwners, l)) && !(~llListFindList(newOwners, l))) { if ((k != NULL_KEY) && (k != g)) newOwners += l; else { k = g; l = [k]; if (!(~llListFindList(oldGroups, l)) && !(~llListFindList(newGroups, l))) { if (k != NULL_KEY) newGroups += l; } } } if (!pattern) { owner1 = k; y = ty; } else if (1 == pattern) { owner2 = k; x = tx; } else if (2 == pattern) { owner3 = k; y = cy; } else if (3 == pattern) { if (gridSize > 1.0) { if ((owner1 != owner2) || (owner2 != owner3) || (owner3 != k) || (owner1 != k) || (llList2Float(details, 2) < (gridSize * gridSize))) { float midX = llRound((tx - cx) / 2.0) + cx; float midY = llRound((ty - cy) / 2.0) + cy; list newGrids = []; if (midX > cx) { if (midY > cy) newGrids = [ cx, cy, midX, midY, midX, cy, tx, midY, cx, midY, midX, ty, midX, midY, tx, ty ]; else newGrids = [ cx, cy, midX, ty, midX, cy, tx, ty ]; } else if (midY > cy) newGrids = [ cx, cy, tx, midY, cx, midY, tx, ty ]; if (newGrids != []) gridAreas = (gridAreas = []) + newGrids + gridAreas; } } } if (3 > pattern) { ++pattern; jump gridProcess; } if ([] == gridAreas) { string msg = "Complete after " + (string)operations + " operations."; integer x = oldOwners != []; while ((--x) >= 0) { integer index = llListFindList( newOwners, [llList2Key(oldOwners, x)] ); if (~index) newOwners = llDeleteSubList( (newOwners = []) + newOwners, index, index ); else oldOwners = llDeleteSubList( (oldOwners = []) + oldOwners, x, x ); } if (x = newOwners != []) { msg += "\nNew land owners:"; while ((--x) >= 0) msg += "\n" + llList2String(newOwners, x); msg += "\n"; } if (x = oldOwners != []) { msg += "\nAbsent land owners:"; while ((--x) >= 0) msg += "\n" + llList2String(oldOwners, x); msg += "\n"; } oldOwners = (oldOwners = newOwners = []) + oldOwners + newOwners; x = oldGroups != []; while ((--x) >= 0) { integer index = llListFindList( newGroups, [llList2Key(oldGroups, x)] ); if (~index) newGroups = llDeleteSubList( (newGroups = []) + newGroups, index, index ); else oldGroups = llDeleteSubList( (oldGroups = []) + oldGroups, x, x ); } if (x = newGroups != []) { msg += "\nNew land groups:"; while ((--x) >= 0) msg += "\n" + llList2String(newGroups, x); msg += "\n"; } if (x = oldGroups != []) { msg += "\nAbsent land groups:"; while ((--x) >= 0) msg += "\n" + llList2String(oldGroups, x); } oldGroups = (oldGroups = newGroups = []) + oldGroups + newGroups; llInstantMessage(llGetOwner(), (msg = "") + msg); gridAreas = gridDefault; float time = 86400.0 - llGetGMTclock(); if (time < 3600.0) time += 86400.0; llSetTimerEvent(time); } else llSetTimerEvent(2.0); }
} </lsl>