Created
September 28, 2022 08:25
-
-
Save clairem-sl/abbbb23df94771fa43979d14448e0c27 to your computer and use it in GitHub Desktop.
Find Abandoned Parcels
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // FindAbandonedParcels.lsl | |
| // Released to the Public Domain by Claire Morgenthau | |
| // If Public Domain is not applicable in your jurisdiction, | |
| // you can use one of the following licenses: | |
| // WTFPL, CC0, Unlicense, 0BSD, or MIT-0 | |
| integer MINIGRID_SIZE = 8; | |
| // ===== DO NOT EDIT BELOW THIS LINE ===== | |
| key GOVERNOR_LINDEN = "3d6181b0-6a4b-97ef-18d8-722652995cf1"; | |
| key DEPT_PUBLIC_WORKS = "4a18e287-db5b-0551-2500-087da6e89efb"; | |
| // Simple -- and possibly grossly inaccurate -- logic: | |
| integer IsProbablyAbandoned(key owner, string message) { | |
| string strLo = llToLower(message); | |
| // LL-owned parcels | |
| if (owner == GOVERNOR_LINDEN || owner == DEPT_PUBLIC_WORKS) { | |
| if (llSubStringIndex(strLo, "protected land") != -1) return 0; | |
| if (llSubStringIndex(strLo, "route") == 0) return 0; | |
| else return 1; | |
| } | |
| if(llStringLength(message) == 0) return 0; | |
| if(llSubStringIndex(strLo, "abandoned") > -1) return 1; | |
| else return 0; | |
| } | |
| string Vec2IntString(vector vec) { | |
| return | |
| "<" + | |
| (string)((integer)vec.x) + "," + | |
| (string)((integer)vec.y) + "," + | |
| (string)((integer)vec.z) + | |
| ">" | |
| ; | |
| } | |
| vector COLOR_WHITE = <1.0, 1.0, 1.0>; | |
| vector COLOR_BLACK = <0.0, 0.0, 0.0>; | |
| float OPAQUE = 1.0; | |
| float TRANSP = 0.0; | |
| list PARCEL_WANT_DETAILS = [PARCEL_DETAILS_NAME, PARCEL_DETAILS_DESC, PARCEL_DETAILS_AREA, PARCEL_DETAILS_ID, PARCEL_DETAILS_OWNER]; | |
| integer ScanForAbandoned() { | |
| integer x; | |
| integer y; | |
| list parcelDetails; | |
| integer candidates = 0; | |
| list candidatePos = []; | |
| list candidateName = []; | |
| list candidateArea = []; | |
| list candidateID = []; | |
| string status; | |
| string parcelSeen; | |
| string parcelID; | |
| integer parcelArea; | |
| key parcelOwner; | |
| string parcelName; | |
| string parcelNeedle; | |
| // LL does not provide a convenient function to dump a list of parcels in a region, | |
| // so we bruteforce by scanning per 8x8 minigrids. | |
| // The number 8 was chosen by observation of other scanning scripts which had settled for 8. | |
| for (x = 0; x <= 256; x += MINIGRID_SIZE) { | |
| for (y = 0; y <= 256; y += MINIGRID_SIZE) { | |
| status = "(" + (string)x + "," + (string)y + ") " + (string)candidates + " so far"; | |
| llSetText(status, COLOR_WHITE, OPAQUE); | |
| vector parcelPos = <(float) x, (float) y, 0.0>; | |
| parcelDetails = llGetParcelDetails(parcelPos, PARCEL_WANT_DETAILS); | |
| parcelID = llList2String(parcelDetails, 3); | |
| parcelNeedle = "@@" + parcelID; | |
| if (llSubStringIndex(parcelSeen, parcelNeedle) == -1) { | |
| parcelSeen = parcelSeen + parcelNeedle; | |
| parcelOwner = llList2Key(parcelDetails, 4); | |
| parcelName = llList2String(parcelDetails, 0); | |
| parcelArea = llList2Integer(parcelDetails, 2); | |
| if (IsProbablyAbandoned(parcelOwner, parcelName)) { | |
| candidates += 1; | |
| parcelArea = llList2Integer(parcelDetails, 2); | |
| candidatePos = candidatePos + parcelPos; | |
| candidateName = candidateName + parcelName; | |
| candidateArea = candidateArea + parcelArea; | |
| candidateID = candidateID + parcelID; | |
| } | |
| } | |
| } | |
| } | |
| llSetText("", COLOR_BLACK, TRANSP); | |
| // Cleanup the heavy objs | |
| parcelDetails = []; | |
| parcelSeen = ""; | |
| status = "===== Candidates in " + llGetRegionName() + " ====="; | |
| llInstantMessage( llGetOwner(), status); | |
| if (candidates) { | |
| for (x = 0; x < candidates; x++) { | |
| status = | |
| Vec2IntString(llList2Vector(candidatePos, x)) + " " + | |
| llList2String(candidateArea, x) + "m2 " + | |
| "secondlife:///app/parcel/" + llList2String(candidateID, x) + "/about" | |
| ; | |
| llOwnerSay(status); | |
| // llInstantMessage( llGetOwner(), status); | |
| } | |
| llInstantMessage( llGetOwner(), "------------------------------"); | |
| } | |
| else { | |
| llOwnerSay("----- No candidates found -----"); | |
| } | |
| // Cleanup | |
| status = ""; | |
| candidatePos = []; | |
| candidateName = []; | |
| candidateArea = []; | |
| candidateID = []; | |
| return 0; | |
| } | |
| // ############################################################ | |
| default { | |
| state_entry() { | |
| llOwnerSay("I . AM . STARTED !"); | |
| } | |
| touch_start(integer num_detected) { | |
| ScanForAbandoned(); | |
| } | |
| changed(integer change) | |
| { | |
| if (change & CHANGED_REGION) { | |
| // llOwnerSay("Don't move too fast! Region is being scanned..."); | |
| llInstantMessage( llGetOwner(), "Don't move too fast! Region is being scanned..."); | |
| ScanForAbandoned(); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment