Land scanner - Retrieving land owners in entire sim
|
|
Corey Braendle
Registered User
Join date: 26 Oct 2006
Posts: 27
|
11-16-2006 07:52
Hey all I'm having a little difficulty in figuring out how to go about doing this.
Here is what I want the script to do: 1. Scan the entire sim which the object is located in 2. From that scan, retrieve all land owners names/keys and how much land they own 3. Send that data to a php file on my server ready to be parsed and put into a database
Okay, so how far did I get?!
I managed to create a scanner that scanned 16sqm every second and add all the landowners, amount of land they owned, sim name and sim hostname of every plot, up to about 1024sqm which my scanner then began to start over for some strange reason. So I never got past 1024sqm of scanning...
All the information was successfully entered into my database via a llHTTPRequest on a php parser i wrote, but having information on only 1024sqm of a sim is pointless.. and it taking 1 second per 16sqm is ridiculous (the 1 second delay was due to the fact I was sending llHTTPRequests after every 16m plot)
Now I know of someone who has a scanner that scans an entire sim, and does everything i need (gets land owners, sim name, sim host, land size owned, adds it all to a database via php) and it does it in aprox 2 minutes!
Im just wondering how on earth thats possible... Any help is much appreciated.
Thanks
PS: I don't want the code written for me, so please do not flame me telling me to do it myself. I am quite new to LSL ,although I have background experience in other programming languages, so I would like pointers on what functions to use etc.
|
|
Eloise Pasteur
Curious Individual
Join date: 14 Jul 2004
Posts: 1,952
|
11-16-2006 12:05
Who is the person you know with this?
Anyway... I have such a system. Essentially it does it the way you do. It does a few things differently though... its scans multiple plots per run and sends data that way strung together. The php parses them to a list and splits to a database.
No smart maths in lsl, do it all at the database end. There's 4096 16sqm plots in a sim... doing things like a mysql query COUNT * FROM tablename GROUP BY owner_id will tell you how much land they own.
There's a lot more to what my system does than that, but that's how I cope with that bit.
|
|
Matthew Bremser
Registered User
Join date: 9 Oct 2006
Posts: 17
|
11-16-2006 12:58
no wonder SL is so laggy... (shakes head)
|
|
Corey Braendle
Registered User
Join date: 26 Oct 2006
Posts: 27
|
11-16-2006 14:02
From: Matthew Bremser no wonder SL is so laggy... (shakes head) Thanks for that useful comment. --- Anywho, I will have another mess around with it sometime tomorow maybe, if anyone else has any tips they are much appreciated. Thanks eloise.
|
|
Vares Solvang
It's all Relative
Join date: 26 Jan 2005
Posts: 2,235
|
11-16-2006 17:26
Why do you need this information?
|
|
Joannah Cramer
Registered User
Join date: 12 Apr 2006
Posts: 1,539
|
11-16-2006 17:52
From: Corey Braendle Im just wondering how on earth thats possible... Any help is much appreciated. uhmm list owner_keys; list owner_parcels;
integer MAP_SIZE_X = 64; integer MAP_SIZE_Y = 64;
scan_land() { llOwnerSay( "Simulator scan started... please wait." );
owner_keys = owner_parcels = []; integer x; integer y; for( y = 0; y < MAP_SIZE_Y; ++y ) { for( x = 0; x < MAP_SIZE_X; ++x ) {
key land_owner = llGetLandOwnerAt( < ((float)x * 4.0 + 2.0), ((float)y * 4.0 + 2.0), 0.0 > ); integer idx = llListFindList( owner_keys, [ land_owner ] ); if( idx != -1 ) { integer land = llList2Integer( owner_parcels, idx ) + 16; owner_parcels = llListReplaceList( owner_parcels, [land], idx, idx ); } else {
owner_keys += [ land_owner ]; owner_parcels += 16; } } integer percent_done = (integer)(100.0 / (float)MAP_SIZE_X * ((float)y + 1.0)); llSetText( "Simulator scan in progress ... " + (string)percent_done + "% done", <1.0, 1.0, 1.0>, 1.0 ); } llSetText( "", <1.0, 1.0, 1.0>, 1.0 ); llOwnerSay( "Simulator scan finished. The land appears to belong to " + (string)llGetListLength( owner_keys ) + " owner(s)." ); }
default {
touch_start( integer ContactsTotal ) { scan_land(); } }
you'd need to do database queries to get all names but that's about it, i think o.o;
|
|
Senuka Harbinger
A-Life, one bit at a time
Join date: 24 Oct 2005
Posts: 491
|
11-16-2006 20:56
I have a scanner that, depending on how big of a scan you want to do, can do a whole sim from as little as 1.6 seconds (using my cube volume scanner set at 64m^2 footprint), or as long as 32 seconds (footprint of 16m^2). I won't reveal the entire code since it could easily be used to grief/crash sims, but if you want I can post the navigation AI. it's a basic sequential use of the WarpPos library function (.2s per movement) to guide the scanner in a set pattern around the sim based on the scanner's footprint size while keeping the scanner at 50m to avoid no-script land death.
_____________________
My SLExchange shopTypos are forgiven; desecrating the english language with reckless abandon and necrophilic acts is not. The function is working perfectly fine. It's just not working the way you wanted it to work.
|
|
Joannah Cramer
Registered User
Join date: 12 Apr 2006
Posts: 1,539
|
11-16-2006 22:05
... Are you talking of scanning for AVs? because can't quite figure out the point of moving around the sim to determine land owners of parcels and such... o.O;
|
|
Corey Braendle
Registered User
Join date: 26 Oct 2006
Posts: 27
|
11-17-2006 06:34
From: Vares Solvang Why do you need this information? The information will be processed by PHP and entered into a database from which i will be able to access on my home Apache server via a web interface. It will allow me to see who owns what in as many of the maingrid sims as possible (Eventually once I have multiple scanners setup in different sims by friends etc). I will then be able to use this information to find out how much land a particular person owns in total, not just dependant on one sim alone. Without blabbing on too much lets just say it will help me greatly with what I do and many people in my line of work will know that this kind of information is extremely valuable. --- Thanks Joannah I will give your script a test and have a play about with it to see if I can rig it up to my database correctly. It all looks to be the kind of thing I was searching for so I will let you know shortly  EDIT: Joannah that script works absolutely beautifully. I have successfuly rigged it up to my database and got it to split the lists and distribute them appropriately into my desired fields and records. Thanks a bundle to everyone who has left a message in this post. 
|
|
Eloise Pasteur
Curious Individual
Join date: 14 Jul 2004
Posts: 1,952
|
11-17-2006 07:10
From: Vares Solvang Why do you need this information? I don't know why the OP needs it. For me... it's part of land rental package for islands I was commissioned to build. Since people can now sell their parcels on etc. it lets them check the data stored is correct. That's one very obvious use for it that I have no qualms about. Other uses... not sure. I made a sim mapper that would rez prims to show a map of the sim with the ends colour coded by owner. It was a pretty toy, and very expensive in terms of prims, but it is another place where using the core of the system is entirely reasonable.
|
|
Corey Braendle
Registered User
Join date: 26 Oct 2006
Posts: 27
|
11-17-2006 12:15
Okay, I noticed that I was incorrectly using llKey2Name to determine the parcel owner names... So instead I tried using the following: integer i; integer owner_length = (owner_keys != []);
for( i = 0; i < owner_length; i++ ){ string current_name = llList2String(owner_keys, i); llRequestAgentData(current_name, DATA_NAME); }
and dataserver(key queryid, string data) { owner_names += [ data ]; }
But after adding that code into the script, the scanner completes perfectly... or so it seems... It does everything as it should, apart from the fact that the llHTTPRequest no longer seems to function.. Although everything before and after it does..
|
|
Corey Braendle
Registered User
Join date: 26 Oct 2006
Posts: 27
|
11-17-2006 12:49
Sorry for the double post, but here is the script in full for you to have a look at: list owner_keys; list owner_names; list owner_parcels;
integer MAP_SIZE = 64;
string sim_host; string sim_name;
scan_land() { // PREPARE SCAN START llOwnerSay( "Simulator scan started... please wait." ); llSetText( "Retrieving simulator name and host... please wait", <1.0, 0.0, 0.0>, 1.0 ); owner_keys = owner_names = owner_parcels = []; sim_host = llGetSimulatorHostname(); sim_name = llGetRegionName(); // PREPARE SCAN END // LAND SCAN START integer x; integer y; for( y = 0; y < MAP_SIZE; y++ ) { for( x = 0; x < MAP_SIZE; x++ ) {
key land_owner = llGetLandOwnerAt( < ((float)x * 4.0 + 2.0), ((float)y * 4.0 + 2.0), 0.0 > ); integer idx = llListFindList( owner_keys, [ land_owner ] ); if( idx != -1 ) { integer land = llList2Integer( owner_parcels, idx ) + 16; owner_parcels = llListReplaceList( owner_parcels, [land], idx, idx ); } else { owner_keys += [ land_owner ]; owner_parcels += 16; } } integer percent_done = (integer)(100.0 / (float)MAP_SIZE * ((float)y + 1.0)); llSetText( "Simulator scan in progress ... " + (string)percent_done + "% done\nTotal land scanned "+ (string)(((float)x * 4.0 + 2.0)*((float)y * 4.0 + 2.0))+"sqm", <1.0, 0.0, 0.0>, 1.0 ); } // LAND SCAN END // SCAN KEYS START integer i; integer owner_length = (owner_keys != []); for( i = 0; i < owner_length; i++ ){ string current_name = llList2String(owner_keys, i); integer percent_done = (integer)(((i+1)/owner_length)*100); llSetText( "Working...\nTesting key " + (string)(i+1) + " of " + (string)owner_length + ": " + current_name + "\n" + (string)percent_done + "% done", <1.0, 0.0, 0.0>, 1.0 ); llRequestAgentData(current_name, DATA_NAME); } // SCAN KEYS END // FINISHED SCAN START llHTTPRequest("http://255.255.255.255/add.php?keys="+llDumpList2String(owner_keys, ",")+"&names="+llDumpList2String(owner_names, ",")+"&land="+llDumpList2String(owner_parcels, ",")+"&sim="+sim_name+"&simh="+sim_host, [HTTP_METHOD, "GET"], "");
llSetText( "Simulator scan complete", <1.0, 0.0, 0.0>, 1.0 ); llOwnerSay( "Simulator scan finished. The land appears to belong to " + (string)llGetListLength( owner_keys ) + " owner(s)." ); // FINISHED SCAN END }
default { touch_start( integer ContactsTotal ) { scan_land(); } on_rez(integer a) { llResetScript(); } dataserver(key queryid, string data) { owner_names += [ data ]; } }
|
|
Dragon Keen
Registered User
Join date: 24 Apr 2006
Posts: 245
|
11-17-2006 13:29
From: Senuka Harbinger I have a scanner that, depending on how big of a scan you want to do, can do a whole sim from as little as 1.6 seconds (using my cube volume scanner set at 64m^2 footprint), or as long as 32 seconds (footprint of 16m^2). I won't reveal the entire code since it could easily be used to grief/crash sims, but if you want I can post the navigation AI. it's a basic sequential use of the WarpPos library function (.2s per movement) to guide the scanner in a set pattern around the sim based on the scanner's footprint size while keeping the scanner at 50m to avoid no-script land death. you dont need to physically move around the sim to do what he's asking... and can be done with 0 lag gatherData() { data = []; for ( y = min_y; y <= max_y; y+=4 ) { for ( x = min_x; x <= max_x; x+=4 ) { landowner = llGetLandOwnerAt(<x, y, z>); addToList( landowner ); } } }
|
|
Dragon Keen
Registered User
Join date: 24 Apr 2006
Posts: 245
|
11-17-2006 13:31
From: Joannah Cramer ... Are you talking of scanning for AVs? because can't quite figure out the point of moving around the sim to determine land owners of parcels and such... o.O; because he wants to make something like http://www.dragonkeen.com/landmap/
|
|
Dragon Keen
Registered User
Join date: 24 Apr 2006
Posts: 245
|
11-17-2006 13:45
anyone know how this would work llHTTPRequest("http://255.255.255.255/add.php?keys="+llDumpList2String(owner_keys, ",")+"&names="+llDumpList2String(owner_names, ",")+"&land="+llDumpList2String(owner_parcels, ",")+"&sim="+sim_name+"&simh="+sim_host, [HTTP_METHOD, "GET"], ""); its a get with over 2000 characters, he says it works... but my understanding is GET is limited (100 or 255 characters depending who you ask) I used post for mine... just weird that GET works for him
|
|
Corey Braendle
Registered User
Join date: 26 Oct 2006
Posts: 27
|
11-17-2006 14:11
Yup it worked fine hehe. But I've changed it to POST now just incase GET gives me problems in a larger sim.
Still working on the dataserver problem, so il let you know how it all goes.
|
|
Joannah Cramer
Registered User
Join date: 12 Apr 2006
Posts: 1,539
|
11-17-2006 16:48
Uhmm i understand what the land data would be for... what i didn't get was the reply i quoted, which mentioned volume collisions and moving around the sim, which seemed to have little to do with subject at hand... ^^;;
|
|
Joannah Cramer
Registered User
Join date: 12 Apr 2006
Posts: 1,539
|
11-17-2006 16:58
From: Corey Braendle So instead I tried using the following: integer i; integer owner_length = (owner_keys != []);
for( i = 0; i < owner_length; i++ ){ string current_name = llList2String(owner_keys, i); llRequestAgentData(current_name, DATA_NAME); }
and dataserver(key queryid, string data) { owner_names += [ data ]; }
This won't work very reliably. While you're sending a stream of requests to the dataserver, there's absolutely no guarantee that responses you receive will arrive in the same order you fired your questions, or (if it's group key) that they arrive at all. It'd be more reliable to only launch single query at any given time, then move onto next one once the reply arrives, or enough time passes to presume there's not going to be reply at all. Something like: // pseudocode integer key_idx = 0; integer query_id; query_id = llRequestAgentData( llList2Key( agent_keys, key_idx ), DATA_NAME ) llSetTimerEvent( 5.0 );
timer() {
agent_names += "a group"; ++key_idx; if( key_idx < llGetListLength( agent_keys ) ) query_id = llRequestAgent... else { llSetTimerEvent( 0.0 ); // all queries done } }
dataserver( queryid, data ) {
if( queryid != query_id ) return; // not what we asked for
agent_names += data; ++key_idx; if( key_idx < llGetListLength( agent_keys ) ) { query_id = llRequestAgent... llSetTimerEvent( 5.0 ); // renew timer; } else { llSetTimerEvent( 0.0 ); // all queries done } }
|
|
Corey Braendle
Registered User
Join date: 26 Oct 2006
Posts: 27
|
11-17-2006 19:59
Thanks a bundle Joannah. This script works perfectly, to a certain extent... The script works fine on small sims. But once a sim reaches big numbers, say for example 80 land owners in a sim. It crashes and gives me the dreaded Stack/Heap collision error when about to send all the data to the php server. I have a feeling im going to have to split it up into more than one script to reduce memory consumption. But I have no idea how to go about this, ie: which bits to chunk out etc... The code in its entirety thus far is: list owner_keys; list owner_names; list owner_parcels;
integer MAP_SIZE = 64; integer i = 1; integer key_idx = 0;
string sim_host; string sim_name;
key query_id;
scan_land() { // PREPARE SCAN START llOwnerSay( "Simulator scan started... please wait." ); llSetText( "Retrieving simulator name and hostname... please wait", <1.0, 0.0, 0.0>, 1.0 ); owner_keys = owner_names = owner_parcels = []; sim_host = llGetSimulatorHostname(); sim_name = llGetRegionName(); // PREPARE SCAN END // LAND SCAN START integer x; integer y; for( y = 0; y < MAP_SIZE; y++ ) { for( x = 0; x < MAP_SIZE; x++ ) {
key land_owner = llGetLandOwnerAt( < ((float)x * 4.0 + 2.0), ((float)y * 4.0 + 2.0), 0.0 > ); integer idx = llListFindList( owner_keys, [ land_owner ] ); if( idx != -1 ) { integer land = llList2Integer( owner_parcels, idx ) + 16; owner_parcels = llListReplaceList( owner_parcels, [land], idx, idx ); } else { owner_keys += [ land_owner ]; owner_parcels += 16; } } integer percent_done = (integer)(100.0 / (float)MAP_SIZE * ((float)y + 1.0)); llSetText( "Simulator scan in progress ... " + (string)percent_done + "% done\nTotal land scanned "+ (string)(((float)x * 4.0 + 2.0)*((float)y * 4.0 + 2.0))+"sqm", <1.0, 0.0, 0.0>, 1.0 ); } // LAND SCAN END // SCAN KEYS START // SCAN KEYS START query_id = llRequestAgentData(llList2Key(owner_keys, key_idx), DATA_NAME); llSetTimerEvent( 5.0 ); // SCAN KEYS END // SCAN KEYS END
}
default { state_entry() { llSetText( "CB Simulator Scanner", <1.0, 0.0, 0.0>, 1.0 );} touch_start( integer ContactsTotal ) { scan_land(); } on_rez(integer a) { llResetScript(); }
timer() { owner_names += "Group"; key_idx++; if(key_idx < llGetListLength(owner_keys)){ llSetText( "Working...\nTesting key " + (string)(key_idx+1) + " of " + (string)llGetListLength(owner_keys) + ": " + llList2String(owner_keys, key_idx), <1.0, 0.0, 0.0>, 1.0 ); query_id = llRequestAgentData(llList2Key(owner_keys, key_idx), DATA_NAME); } else { llSetTimerEvent( 0.0 ); // all queries done llSetText( "Scanning complete\nSim scanned: "+sim_name+"\nTotal owners in sim: "+(string)(key_idx+1), <1.0, 0.0, 0.0>, 1.0 ); llHTTPRequest("http://82.69.83.122/add.php", [HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"], "keys="+llList2CSV(owner_keys)+"&names="+llList2CSV(owner_names)+"&land="+llList2CSV(owner_parcels)+"&sim="+sim_name+"&simh="+sim_host); } }
dataserver( key queryid, string data ) { if( queryid != query_id ) return; // not what we asked for owner_names += data; key_idx++; if( key_idx < llGetListLength( owner_keys ) ) { llSetText( "Working...\nTesting key " + (string)(key_idx+1) + " of " + (string)llGetListLength(owner_keys) + ": " + llList2String(owner_keys, key_idx), <1.0, 0.0, 0.0>, 1.0 ); query_id = llRequestAgentData(llList2Key(owner_keys, key_idx), DATA_NAME); llSetTimerEvent( 5.0 ); // renew timer; } else { llSetTimerEvent( 0.0 ); // all queries done llSetText( "Scanning complete\nSim scanned: "+sim_name+"\nTotal owners in sim: "+(string)(key_idx+1), <1.0, 0.0, 0.0>, 1.0 ); llHTTPRequest("http://82.69.83.122/add.php", [HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"], "keys="+llList2CSV(owner_keys)+"&names="+llList2CSV(owner_names)+"&land="+llList2CSV(owner_parcels)+"&sim="+sim_name+"&simh="+sim_host); } }
}
I know I am a pain but any help is much appreciated lol.
|
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
11-18-2006 13:28
From: Senuka Harbinger I won't reveal the entire code since it could easily be used to grief/crash sims, but if you want I can post the navigation AI. it's a basic sequential use of the WarpPos library function (.2s per movement) to guide the scanner in a set pattern around the sim based on the scanner's footprint size while keeping the scanner at 50m to avoid no-script land death. Senuka I would be interested in seeing the navigation AI for an unrelated project. I am going to try to make an object to go around a sim looking for the spamming devices tonight. I know I can eventually figure it out but I might be able to make it more efficient or see a trick or two. I am also going to make it so once it has scanned an elevation it will jump up and repeat the scan. Instead of PHP I'll just have it IM the list before the memory is filled and clear it. BTW. Something like this would be kind of laggy but it is a one time or very infrequent type of script. Its "lag" impact is much less then the sum total of AV's with thier AO's and other scripted attachments.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime. From: someone I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
|
|
Corey Braendle
Registered User
Join date: 26 Oct 2006
Posts: 27
|
11-18-2006 21:20
As you all know it's working now and successfully scans the land and retrieves av names etc and puts them in my database.
However, it was running extremely slowly, taking about 10 minutes per scan, as you can imagine. Also, if i try to scan a sim with aprox 100+ owners it gives me a stack/heap collision error, indicating ive used up all of my 16kb of script memory.
So to fix this i tried using llMessageLinked and link_message functions/handlers and setup the following structure:
CONTROLLER - Activates 4 scanners when the scanner is touched, and deals with llSetText SCANNER 1 - Scans 1/4 of the sim and stores data in 1 strided list, keys/parcels SCANNER 2 - Same as above SCANNER 3 - Same as above SCANNER 4 - Same as above STORAGE - Recieves lists from all 4 scanners when they are done and joins them together NAMES - Recieves complete list and gets names from keys within list. Seperates into 3 lists, keys/names/parcels.
I have been messing about with this for over 10 hours but for some reason the scanning freezes at about 35000sq.m... I have tested it with each individual scanner and they all successfully scan aprox 16,000sq.m.
I have also added debug code to check when each scanner reports to be finished. And for some strange reason, number 1&2 report finished at about 30,000sqm and then 3&4 report finished closely together at around 34,000sqm.. after that the scanner freezes and does not procede with the next 2 steps (Storage and name retrieval)
I would post the code here but since it is 7 scripts it is way too large. So i would very much appreciate it if someone with good scripting knowledge would take a look at the scripts within SL.
This is extremely important to me that I have a land scanner, so all help is very much appreciated. If you require payment then that can be negotiated.
Thanks
|
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
11-18-2006 21:56
Why not just have it periodically check the length of the list and if it is getting full it will stop, transmit the data, clear the list and then continue?
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime. From: someone I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
|
|
Corey Braendle
Registered User
Join date: 26 Oct 2006
Posts: 27
|
11-18-2006 22:41
Hi jesse, I guess that would have been one way. Although I have now fixed this problem by having the 4 scanners in 4 different prims and then a small master prim which I click to begin all the 4 scanners. It looks kinda cool that way too lol. That fixes my memory problem and allows me to transmit the 4 lists easily to my database ready to sort out on the php end. Works a charm  Thanks for everyones help
|