Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Key confusion: Casting problem?

Rock Ryder
Registered User
Join date: 6 Oct 2006
Posts: 384
11-17-2007 15:54
Hi Guys,

Can anyone see what I am doing wrong here?

I have a List, called Owners, containing agent keys (of prim owners).

I am having difficulty just trying to get the avatar name for the first key in the list:


key name0 = llList2Key(Owners,0);
llOwnerSay((string)name0); //this gives the correct key
llRequestAgentData(name0, DATA_NAME); // request name for given key
}

dataserver(key queryid, string data)
{
llSay(0, "Name of avatar = " + data);
}

If I copy the key spit out by the llOwnerSay and paste it directly (in quotes) into the llRequestAgentData in place of name0, then I do get the avatar name, so why doesn't name0 produce any output?

TIA

Rock
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
11-17-2007 16:39
It is working for me with this script:

CODE

list Owners;

default
{
state_entry()
{
Owners += llGetOwner();
}

touch_start(integer total_number)
{
key name0 = llList2Key(Owners,0);
llOwnerSay((string)name0); //this gives the correct key
llRequestAgentData(name0, DATA_NAME); // request name for given key
}

dataserver(key queryid, string data)
{
llSay(0, "Name of avatar = " + data);
}
}

returns:
[16:38] Object: 0bf93171-e0d3-4b8c-b6eb-55d2cc30cf26
[16:38] Object: Name of avatar = Jesse Barnett
_____________________
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
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
11-17-2007 18:18
uhm, why are you using llRequestAgentData instead of llKey2Name?

anyways, a few things you should know, llList2* functions don't perform proper typecasting, you'd think they would, but they don't... so if it's a string being saved to the list, it's still a string coming out for the most part (floats and integers will convert on simple notation)... vectors are the worst for that (strings return zero_vector)

the other things to watch for would be leading or trailing spaces in your list Owners; which can creep in if you are reading from notecards... remember to use llStringTrim on them as they are read in...

I don't think lsl cares about case in keys, but to be sure, always use lowercase letters for hex... if you like them displayed uppercase, use llToUpper on outputs, and llToLower on inputs
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
11-17-2007 19:16
From: Void Singer
uhm, why are you using llRequestAgentData instead of llKey2Name?

Since the list is made up of prim owner keys (probably using llDetectedOwner or llGetOwnerKey) then he is probably collecting the list from a sensor etc. llKey2Name wouldn't work unless the owner of the prim was in the sim when this script was executed.
_____________________
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
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
11-17-2007 19:44
good point, ok, why not store the names instead of keys then?

also, since it's prim owners, llRequestAgentData may return a group key for owner if the object is deeded to the group, which won't come back with a name... oversight on LL's part

wait, are you sure? I thought llKey2Name worked regardless if it's fed a valid Av key?
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
11-17-2007 19:55
From: Void Singer
good point, ok, why not store the names instead of keys then?

also, since it's prim owners, llRequestAgentData may return a group key for owner if the object is deeded to the group, which won't come back with a name... oversight on LL's part

wait, are you sure? I thought llKey2Name worked regardless if it's fed a valid Av key?

The only way to get the name, if the owner is not in the sim is by using the dataserver event. In this case he is supplying the key to crosscheck but it is possible it is group owned. In that case the script would fail. Just all depends on how he is getting the keys. If he is supplying the keys then it would be better to just add the name to the same strided list of keys or have a seperate list of names with the same index position as the corresponding key.

per the wiki:
"If the object or agent identified by the key id is in the same simulator as the object containing the script, this function returns their name. Otherwise, an empty string ("";) is returned."

Because of the recent incidents of spam greifing it is possible he is trying to do something along the lines of this script which is modified from the wiki example. I just made mine so that you just turn it on when the griefing object is spamming and no other objects are speaking on channel 0:

CODE

//Warning this script can contribute to lag and should be used sparingly
//For a detailed explanation of this script go to:
// http://www.cheesefactory.us/lslwm/llGetOwnerKey.htm


integer on = TRUE;

default {
touch_start(integer total_number)
{
if(!on){
llOwnerSay("Off");
on = TRUE;
}
else{
llOwnerSay("Now Listening");
llListen(0, "", NULL_KEY, "");
on = FALSE;
}
}

listen(integer channel, string name, key id, string message) {
key ownerid;
if ( llGetAgentSize(id) != ZERO_VECTOR ) return;
ownerid = llGetOwnerKey(id);
llRequestAgentData(ownerid, DATA_NAME);
llOwnerSay("Key of the spamming object's owner " + (string)ownerid);
}

dataserver(key requested, string data)
{
llOwnerSay(data + " is the owner");
}
}
_____________________
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
Rock Ryder
Registered User
Join date: 6 Oct 2006
Posts: 384
11-17-2007 20:19
Odd, very odd. The script would not produce a name. I took it into inventory, had a coffee, and posted my query in this forum. Having returned to the fray, I got it back out of inventory, and it is now behaving and giving me the name!!

Oh well...

To answers some of the queries, the list of keys was obtained using llGetParcelPrimOwners, the strided list was then converted to two lists, using llList2ListStrided, one list containing the keys, and the other list containing the # of prims for each agent. There was no need to make two lists, I just wanted to play with the functions as I hadn't before.

llRequestAgentData is used because it gets the names of agents even if they are not in the sim at the time, llKey2Name does not.

My next task is to identify the keys that are group keys, which fail silently with llRequestAgentData, and produce an output something like:

Unknown Group 01: 14 prims
Unknown Group 02: 6 prims

etc

The code up to now is as follows:
CODE


integer lLength;
list OAndP = [];
list Owners = [];
list Prims = [];

default
{

on_rez(integer start_param)
{
llResetScript();
}

state_entry()
{
OAndP = llGetParcelPrimOwners(llGetPos()); //Get the keys of every owner of prims and the no. of prims of each
lLength = llGetListLength(OAndP); //Total items in the list. Divide this by 2 to get the number of owners
Owners = llList2ListStrided(OAndP, 1, -1, 2); //Extract all the owner keys into a new list
Prims = llList2ListStrided(OAndP, 0, -1, 2); //Extract the numbers of prims into a new list
//llOwnerSay(llDumpList2String(Owners, "; ")); //Just for debugging, list of all keys found
key name1 = llList2Key(Owners,0); //Pick a key to pass to the dataserver
llOwnerSay((string)name1); //Say it, for debug purposes
llRequestAgentData(name1, DATA_NAME); // request name for chosen key
}

dataserver(key queryid, string data)
{
llSay(0, "Name of avatar = " + data); //Say the name returned by the dataserver from the key given
}
}

Rock
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
11-17-2007 21:50
could've sworn llKey2Name worked regardless of av presence, but you're right... doh;

and there shouldn't be an issue of inserting group keys, since the only way to get them is via llGetObjectDetails( objectKey, [OBJECT_GROUP] )...

none of the get owner functions return a group key it seems even if the object is group owned... they either return null key, or just plain fail

I'm going to guess that the OP was having failures due to extraneous spaces in the built list...(depending on how it was built) or maybe just slow dataserver events?

EDIT: ok probably just a slow dataserver event..., llDetectedOwner will return null key for group owned objects, so if you get null key, just replace it with "Unknown (group owned)" or you could even use get object details to grab the key for comparison (and refrence vs a list, to get objects owned by a specific group), but it'll never convert
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Rock Ryder
Registered User
Join date: 6 Oct 2006
Posts: 384
11-18-2007 05:01
Ok, all is working now, current script below. The steps are these:

1. Get a list of owners of prims on this parcel (actually their keys), and how many they own, using llGetParcelPrimOwners(llGetPos());

2. Create two lists, one of owner keys, and one of number of prims

3. Loop through the list of owner keys passing each to llRequestAgentData to get their avatar names.

Now, this is the tricky bit, and the step I need the most help on. llGetParcelPrimOwners(llGetPos()) retrieves ALL keys of owners, including owners that are groups. Unfortunately there is no group key to name function in LSL, and even more unfortunately both llRequestAgentData and llKey2Name silently fail. So as I pass a group key to RequestAgentData nothing happens, but I need to find a way to detect that nothing has happened (tricky eh?) so I can insert 'Unknown Group' in place of a name.

Suggestions are VERY welcome at this point :-)

CODE

integer lLength;
list OAndP = [];
list OwnerKeys = [];
list Owners = [];
list Prims = [];
integer x;
key agentKey;
string agentName;

default
{

on_rez(integer start_param)
{
llResetScript();
}

state_entry()
{
OAndP = llGetParcelPrimOwners(llGetPos()); //Get the keys of every owner of prims and the no. of prims of each
lLength = llGetListLength(OAndP); //Total items in the list. Divide this by 2 to get the number of owners
integer agentsN = lLength/2;
OwnerKeys = llList2ListStrided(OAndP, 0, -1, 2); //Extract all the owner keys into a new list
Prims = llList2ListStrided(OAndP, 1, -1, 2); //Extract the numbers of prims into a new list

for (x = 0; x < agentsN; x++)
{
agentKey = llList2Key(OwnerKeys, x); //Take each agent key in the Owners list
llRequestAgentData(agentKey, DATA_NAME); // request name for each key
}
}

dataserver(key queryid, string data)
{
llSay(0, "Name of avatar = " + data); //Say the name returned by the dataserver from the key given
}
}


Rock
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
11-18-2007 06:16
this may sound stupid...

why not assume all of them are groups in advance, insert that into your list, and then set each list entry to the value returned by your request agent data calls...

to do this you'd need to save your query id's for each request agent data call and tie them to the specific requested key, then dump the list at the end, instead of on the fly... you could even cheat and save the query key to a list, then in the datasever replace the query key with the found name, which would preserve the group key if you wanted, and save space... if you don't want the group keys, just parse the list one more time with a loop and
if (llList2Key( outList, element )){
//-- replace element with string "unknown"
}

you could also precompile a list of expected groups by hard coding your own name database, and getting the group key via get object details... of course this is only a solution for you, and wouldn't work in production
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Rock Ryder
Registered User
Join date: 6 Oct 2006
Posts: 384
11-18-2007 11:32
From: Void Singer
this may sound stupid...

why not assume all of them are groups in advance, insert that into your list, and then set each list entry to the value returned by your request agent data calls...

to do this you'd need to save your query id's for each request agent data call and tie them to the specific requested key, then dump the list at the end, instead of on the fly... you could even cheat and save the query key to a list, then in the datasever replace the query key with the found name, which would preserve the group key if you wanted, and save space... if you don't want the group keys, just parse the list one more time with a loop and
if (llList2Key( outList, element )){
//-- replace element with string "unknown"
}

you could also precompile a list of expected groups by hard coding your own name database, and getting the group key via get object details... of course this is only a solution for you, and wouldn't work in production


Not stupid at all, and is almost the same as what I came up with after studying this for the best part of my Sunday (ouch!).

My plan is to create three 2-strided lists.

The list01 would contain the keys and prim-numbers from llGetParcelPrimOwners, sorted on the keys, looking like this:

Key1, Prims1
Key2, Prims2
Key3, Prims3
Key4, Prims4

etc

The list02 would contain the keys and the queryId sent to the dataserver generated by the RequestAgentData command, (again sorted on keys), like so:

Key1, QueryID1
Key2, QueryID2
Key3, QueryID3
Key4, QueryID4

The list03 would contain the queryids and the returned names from the dataserver event, which may look like this (assuming here, for example, that Key3 was for a group):

QueryID1, Name1
QueryID2, Name2
QueryID4, Name4

I can then search list03 for all the QueryIDs from list02. If a QueryID is found to be missing, it can then be appended to the list03, together with "Unknown Group" as the name, like so (after sorting on key):

Key1, QueryID1, Name1
Key2, QueryID2, Name2
Key3, QueryID3, "Unknown Group"
Key4, QueryID4, Name4

I hope I have no meetings at work on Monday, looks like it is going to be a busy day!!

Rock
Jopsy Pendragon
Perpetual Outsider
Join date: 15 Jan 2004
Posts: 1,906
11-18-2007 12:03
Of course, the downside of storing both name and key will run you out of your available script memory faster, reducing how many you can store. :(
Qie Niangao
Coin-operated
Join date: 24 May 2006
Posts: 7,138
11-18-2007 12:43
In case it's any use, I found this little snippet in a script that snoops around parcel prim owners:

here = llGetPos();
list parcelDetails = llGetParcelDetails(here, [PARCEL_DETAILS_GROUP]);
groupKey = llList2Key(parcelDetails, 0);

the point of which was to just have groupKey with which to recognize the specific group to which the (group-owned) parcel is deeded when it crops up on the list of prim owners.
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
11-18-2007 18:34
how about 1 list in 3 strides?

query, key, primcount

as your dataserver returns names, replace query (or key) with the name... the ones that fail, will still show the group key. that should save a little space... in fact, you could even blank out query each time it returns, to save more space

in the dataserver, you could use the list find list function strided or not, blank the query id it finds, and change the next element to the name...

the only bad thing will be that groups will still take up the space of 2 keys (1 for the failed query, and another for its key)...

also, you may not want to assume all failed queries are groups... it could just be a slow data server.

if you add a set timer event to the dataserver code you can effectively make it pause while waiting for the next query to show up, then add your show code to the timer along with setting the event to 0
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -