Jump to content

Trying to get parcel info on all parcels in a sim without pain and suffering....


StarSong Bright
 Share

You are about to reply to a thread that has been inactive for 4495 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Hi All, Merry Christmas!

I am trying to find a way to find out all of the parcels on a sim and get their parcel info.  I do not want to have to flit around and do parcel info on each one myself... Is there just some way to grab all of the parcel uuids/info without all that hopping around?  Thanks in advance!

Link to comment
Share on other sites

In fact I made a thingy like that once but I wouldn't recommend 4m hops. With sim dimensions being 256x256 you'll end up with 4096 4x4 cells. From my experience 10x10 cells are more manageable in respect to their number. There are only 656 of them. And you do need it moving if you also want to collect other info, for instance prims number, their owners, etc.

Link to comment
Share on other sites

4x4 cells are perfectly fine. You just need to filter the parcels thanks to their UUIDs. The number of parcels in a region is not very high in general, so it is not a problem to store them and compare in order not to check twice the same parcel.

Simple example:

default{    touch_start(integer total_number)    {        list parcel;        integer entry = (PARCEL_FLAG_ALLOW_ALL_OBJECT_ENTRY | PARCEL_FLAG_ALLOW_GROUP_OBJECT_ENTRY);        integer y = 0;        for (; y < 64; ++y)        {            llSetText((string)y, <1.0, 0.0, 0.0>, 1.0);            integer x = 0;            for (; x < 64; ++x)            {                vector pos = <2 + (x << 2), 2 + (y << 2), 0>;                string uuid = llList2String(llGetParcelDetails(pos, [PARCEL_DETAILS_ID]), 0);                if (llListFindList(parcel, [uuid]) == -1) // Parcel UUID not in list...                {                    parcel += uuid; // Point of failure for a large number of parcels                    if ((llGetParcelFlags(pos) & entry) != entry)                    {                        llOwnerSay("Parcel '"                                 + llList2String(llGetParcelDetails(pos, [PARCEL_DETAILS_NAME]), 0)                                 + "' is NO ENTRY");                    }
else
{
llOwnerSay("Parcel '" + llList2String(llGetParcelDetails(pos, [PARCEL_DETAILS_NAME]), 0) + "' allows entry");
}
 } } } llSetText("", <1.0, 0.0, 0.0>, 1.0); parcel = []; }}

Compiled and tested in-world.

It is reasonably fast.

Link to comment
Share on other sites

Yes, that's probably true on most sims.  I imagine there are few 4m square parcels on most well-managed sims, so you're right that 4m hops are overkill.  There could easily be random lost parcels on a less well-managed sim, though,so I wasn't prepared to suggest ignoring them.  If I were digging though 4096 cells by hand, I'd go nuts.  Fortunately, doing it with a script is a piece of cake by comparison.  If you check for duplicate hits as you scan, you increase the time it takes to run the job but you keep the amount of stored data within limits.

Incidentally, I can't get in world to check, but I believe that you can use llGetParcelFlags, llGetParcelMaxPrims, llGetParcelPrimCount, and llGetParcelPrimOwners without actually standing in the parcel, so you should be able to gather those data without moving the scanner physically too, as Rufus suggested. 

Link to comment
Share on other sites

Yes,  all of those APIs work from anywhere in the sim.  I implented a system ("Navigator") to allow it to be done cross-sim, by installing Navigator objects in whatever sims I can and forwaerding the requests to them via HTTP.  Handy for spotting banlines and full parcels in the next sim before you crash into them.   A single object can check anywhere in the sim without moving at all.  (Don't use Navigator to check a whole sim remotely though,  HTTP will get capped before you get very far).

Navigator is free and open-source, so you are welcome to use code from it.   Here is the routine of interest, slightly modified so it is self-contained,  with examples of the use of all of these APIs except llGetParcelPrimOwners:

string parcelinfo(vector pos)// returns string of information about the parcel at position pos:// Regionname:<x,y,z>[ FLAGS ](objs/maxobjs)^groundheight "description" owner// FLAGS are: NOSCRIPT NOFLY DAMAGE REZ REGIONNOFLY REGIONDAMAGE SANDBOX BANLINE//            PARCELFULL SAMEOWNER SAMEGROUP, //   with possible !'s following BANLINE or PARCELFULL to indicate hazard to navigation// ^groundheight is replaced with ~depth if pos is over or in water// owner is only included if the sim has it cached{    string results = "[ ";    integer pflags = llGetParcelFlags(pos);    float ground=llGround(pos - llGetPos());    list det = llGetParcelDetails(pos, [PARCEL_DETAILS_NAME, PARCEL_DETAILS_OWNER, PARCEL_DETAILS_GROUP]);    key ownerkey = llList2Key(det, 1);    key groupkey = llList2Key(det, 2);    string hazard;    float mywater = llWater(ZERO_VECTOR); //  moved here from init_region_vars() to make this self-contained.    integer myregionflags = llGetRegionFlags();//        if (pos.z - ground < 50) {        hazard = "!!";    }        //if (beacon_region == "") {  // don't check if we are the regional beacon        if (ownerkey == llGetOwner()) {            results += "SAMEOWNER ";            hazard = "";                 }        if ((groupkey != NULL_KEY) && llSameGroup(groupkey)) {            results += "SAMEGROUP ";            if (pflags & PARCEL_FLAG_USE_ACCESS_GROUP) {                hazard = "";            }        }    //}        if (pflags & PARCEL_FLAG_USE_ACCESS_GROUP+PARCEL_FLAG_USE_ACCESS_LIST) results += "BANLINE" + hazard + " ";    if (!(pflags & PARCEL_FLAG_ALLOW_SCRIPTS)) results += "NOSCRIPT ";    if (!(pflags & PARCEL_FLAG_ALLOW_FLY)) results += "NOFLY ";    if (pflags & PARCEL_FLAG_ALLOW_DAMAGE) results += "DAMAGE ";    if (pflags & PARCEL_FLAG_ALLOW_CREATE_OBJECTS) results += "REZ ";    if (myregionflags & REGION_FLAG_BLOCK_FLY) results += "REGIONNOFLY ";    if (myregionflags & REGION_FLAG_ALLOW_DAMAGE) results += "REGIONDAMAGE ";    if (myregionflags & REGION_FLAG_SANDBOX) results += "SANDBOX ";    integer regmaxprims = llGetParcelMaxPrims(pos, TRUE);    integer regcurprims = llGetParcelPrimCount(pos, PARCEL_COUNT_TOTAL, TRUE);    if (regcurprims >= regmaxprims) results += "PARCELFULL!!! ";    results += "]"            + " (" + (string)regcurprims + "/" + (string)regmaxprims + ") ";    if (ground > mywater) {        results += "^" + (string)llRound(ground);    } else {        results += "~" + (string)(mywater - ground);    }        results += " \"" + llList2String(det, 0) + "\" ";    string owner;    if (ownerkey == "3d6181b0-6a4b-97ef-18d8-722652995cf1")        owner = "Governor Linden";    else        owner = llKey2Name(ownerkey);    results += owner;    return results;}

 

Link to comment
Share on other sites

Nice.  You may want to reconsider converting each parcel owner's key to a name with llKey2Name, though.  That function will not return a valid name unless the person is in the sim at the moment (or has very recently left it). If you really need that information, it's probably wiser to save the list of UUIDs and then use llRequestAgentData to convert them all later.  Even then, you will run up against a wall if the parcel is owned by a group.  At the moment, I can only think of one way to get the name of  group from its UUID, and that's more trouble than it's worth.

Link to comment
Share on other sites

I did not use llRequestAgentData because of the time lag for the dataserver requests.   In Navigator, timely data is more important than the parcel owner's name.   This way also tells me that the owner is around,  or has been recently,  which may be of interest if I want to visit.

If I want to display the group name,  I can turn the UUID into an slurl.   If I know it is a group:

   secondlife:///app/group/bff098dc-426f-5948-0854-e629b0995578/about

will display as

  
Tiedyed Side of the Force

when sent to the viewer chat window.  and clicking on it will bring up the group profile. If we don't know whether it is a group of a user, and don't want to do a dataserver request to find out:

secondlife:///app/agent/bff098dc-426f-5948-0854-e629b0995578/about

will display agents as above, and display groups as:

  Tiedyed Side of the Force

though clicking on the …/agent/… URL for a group will get a page-not-found error.

The encroachment checker  contains examples of both types of URLs.

Link to comment
Share on other sites

That's the only way I know of too.  It's not a very clean solution, though, because it leaves the user with a stack of URLs to open and inspect manually.  To actually get the group names by script, you'd have to find a way to capture a response from that URL and parse it to extract the name.  As I said before, that's way too much work for a job like this.

Link to comment
Share on other sites

Assuming that all he wants is to display a list of parcels and owners:

Keep them as UUIDs until the list of parcels and owners is assembled,  then display the whole thing to chat with the UUIDs converted to slurls,  then the owner names display,  even if they are groups, because the viewer displays the slurl itself as the owner or group name  (if it is a recent viewer).

If he actually wants to do something further in the script with the information,  then you are correct.

 

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 4495 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...