Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Multiple Objects with Same name--Comm Problems

Kenn Nilsson
AeonVox
Join date: 24 May 2005
Posts: 897
10-29-2005 21:48
So I have a project I'm working on in which there is a lot of object to object communcation on private channels...

...in order to make the project very end-user friendly and versatile, I had attempted to name all independent pieces of the total build the same...(that way the objects will only listen to "themself" and the owner...and the name can be changed so that multiple instances of the same object can be next to eachother and not interfere with eachother's commands)...

...anyway...I'm finding that a script that works perfectly well on a uniquely named prim does NOT function when placed in 2 or more prims with the same name (i.e....the script won't speak to a group of objects with identical names)...

...so...is this a bug? Is it on purpose? Does anyone have an easy work-around idea? I'll probably end up re-writing my scripts...sigh...
_____________________
--AeonVox--

Computer games don't affect kids; I mean if Pac-Man affected us as kids, we'd all be running around in darkened rooms chasing ghosts, eating magic pills, and listening to repetitive, addictive, electronic music.
Eloise Pasteur
Curious Individual
Join date: 14 Jul 2004
Posts: 1,952
10-30-2005 02:30
I'm not 100% sure I understand what you're after. But keys are the obvious way to uniquely identify different objects with the same name. You can get keys several ways, including from a listen event, sensor event, and rezzed if that helps at all?
Kenn Nilsson
AeonVox
Join date: 24 May 2005
Posts: 897
10-30-2005 02:44
No...the idea is to be able to say somethin' like:

/78 TextureObject:Change


...and have like 8 "TextureObject" objects change texture...

separating by the colon is easy...and the script works with one uniquely named item, but it does not work when I try to use it on multiple items of the same name--the script simply fails to execute.

(no, texture is not what I'm after...but it provides a good example).
_____________________
--AeonVox--

Computer games don't affect kids; I mean if Pac-Man affected us as kids, we'd all be running around in darkened rooms chasing ghosts, eating magic pills, and listening to repetitive, addictive, electronic music.
Myrilla Vixen
Definitely Bloo
Join date: 11 Jun 2005
Posts: 143
10-30-2005 08:32
From: Kenn Nilsson
No...the idea is to be able to say somethin' like:

/78 TextureObject:Change


...and have like 8 "TextureObject" objects change texture...

separating by the colon is easy...and the script works with one uniquely named item, but it does not work when I try to use it on multiple items of the same name--the script simply fails to execute.

(no, texture is not what I'm after...but it provides a good example).


First off I have to state I am a bit confused as to what you actually want, and how you're doing it(are these all seperate objects that are all listening to you? Is there one cotrol object that breaks down the commands and then spits them back out for all the other objects to hear?). I can understand wanting to keep your project secret but it's going to affect your responses a bit..

** I am not 100% on this.. but why not make a global in your script, and make that global the name of your object?

I am assuming you're parsing these commands out, right? in which case "/78 texture : object : change";(or even better "/78 object : texture : change" because the object should know if it needs to listen before it is told what to do.. and it's just a lil neater) would be easier to parse..

IE you have six objects named Randy, and you have set the global 'ObName" to reflect such, if each one checks it's "ObName" global against say.. the first word of every command said on channel 78.. then that would work.. right?

I get the feeling I've missed your problem entirely, but that's the best stab I could take with the information given.

** Also what do you mean 'fails to execute'? have you tried tracking down where the problem actually flares up?.. say putting an llOwnerSay function right before anything "happens" in the script, so you can see how far it gets before it hangs.

** One last, not very likely thing, that happened to me once.. if you're using a function to get the object key, you may need to reset the script(as in say.. an llResetScript in the on_rez event. The script could be working with on 'old key' or no key at all, depending on how you got said key, and where it is in the script.

I hope this helps.. I only just started writing scripts of my own..
Keiki Lemieux
I make HUDDLES
Join date: 8 Jul 2005
Posts: 1,490
10-30-2005 10:34
From: Kenn Nilsson
No...the idea is to be able to say somethin' like:

/78 TextureObject:Change


...and have like 8 "TextureObject" objects change texture...

separating by the colon is easy...and the script works with one uniquely named item, but it does not work when I try to use it on multiple items of the same name--the script simply fails to execute.

(no, texture is not what I'm after...but it provides a good example).

Well you would want a script in each copy of the object which listens to channel 78. When it hears something on that channel it parses it into a list and then checks the first word against a set of commands. Something like this should work:
CODE
default
{
state_entry()
{
// listen on channel 78 for all communications
llListen(78,"",NULL_KEY,"");
}

listen(integer channel, string name, key id, string message)
{
// parses the string into commands
list command = llParseString2List(message, [":"], []);

// checks first piece of the message
if ( llList2String( command, 0 ) == "TextureObject" )
{
// checks for various TextreObject commands
if (llList2String( command, 1 ) == "Change" )
{
// Put code here or call function to change texture
}
}
}
}

As long as this script is in the object you wish to hear the command, this should work with 1 object or 100 objects, as long as they are within listening range of the object which issues the command.
_____________________
imakehuddles.com/wordpress/
Kenn Nilsson
AeonVox
Join date: 24 May 2005
Posts: 897
10-30-2005 10:55
From: Keiki Lemieux
As long as this script is in the object you wish to hear the command, this should work with 1 object or 100 objects, as long as they are within listening range of the object which issues the command.



That's the problem...it's not. Here's a snippet of my code:

CODE

string objectname;
string newname;
string callname;
string command;

integer handle;
integer index;
integer x;

list showcase = [];

getlisten()
{
handle = llListen(100, objectname, NULL_KEY, "");
llListenRemove(handle);
objectname = newname;
llListen(100, objectname, NULL_KEY, "");
}

default
{
state_entry()
{
objectname = llGetObjectName();
newname = llGetObjectName();
llListen(99, "", llGetOwner(), "");
getlisten();
}
listen(integer channel, string name, key id, string message)
{
index = llSubStringIndex(message, ":");
if(index != -1)
{
callname = llGetSubString(message, 0, index - 1);
message = llGetSubString(message, index + 1, -1);
}
command = llGetSubString(message, 0, 3);

if(callname == objectname)
{
if(channel == 99)
{
if(command == "name")
{
newname = llGetSubString(message, 5, -1);
llInstantMessage(id, "Vendor name changed to: " + newname);
getlisten();
}
if(command == "hide")
{
llSetAlpha(0.0, ALL_SIDES);
}
if(command == "show")
{
llSetAlpha(1.0, ALL_SIDES);
}
}
}
}
}




Keep in mind that when I place this script into ONE object, it works PERFECTLY. When I place it in multiple objects (all with the same object name), the script DOES NOT work.
_____________________
--AeonVox--

Computer games don't affect kids; I mean if Pac-Man affected us as kids, we'd all be running around in darkened rooms chasing ghosts, eating magic pills, and listening to repetitive, addictive, electronic music.
Keiki Lemieux
I make HUDDLES
Join date: 8 Jul 2005
Posts: 1,490
10-30-2005 11:45
Alright I'm going to add a bunch of comments. I would think a more experienced programmer might be able to just figure it out. But I'm not sure if I can without pulling it apart piece by piece.
CODE

string objectname;
string newname;
string callname;
string command;

integer handle;
integer index;
integer x;

list showcase = [];

getlisten()
{
// First question is what is the purpose of these first two lines? It opens a listener
// and then immediately closes it.
handle = llListen(100, objectname, NULL_KEY, "");
llListenRemove(handle);

objectname = newname;

// When objectname equals the name of the current object, it will not hear chat from itself. Only other objects with the same name.
llListen(100, objectname, NULL_KEY, "");
}

default
{
state_entry()
{
objectname = llGetObjectName();
newname = llGetObjectName();
llListen(99, "", llGetOwner(), "");
getlisten();
}
listen(integer channel, string name, key id, string message)
{
// So these next commands break down your message for you. gotcha :)
index = llSubStringIndex(message, ":");
if(index != -1)
{
callname = llGetSubString(message, 0, index - 1);
message = llGetSubString(message, index + 1, -1);
}
command = llGetSubString(message, 0, 3);

// Alright, before it processes these commands, it checks to
// see if to see if the command is meant for it. 'callname' would
// normally contain the name of the current object.
if(callname == objectname)
{
// Then it checks if it is from channel 99.
if(channel == 99)
{
if(command == "name")
{
// This looks strange to me... so one of the commands renames
// the object it is listening to on the 100 channel?
// One side affect of this is when the getlisten is called, it changes
// objectname it now listens to on 100 and it will change in effect
// channel 99, since callname must match objectname.
newname = llGetSubString(message, 5, -1);
llInstantMessage(id, "Vendor name changed to: " + newname);
getlisten();
}
if(command == "hide")
{
llSetAlpha(0.0, ALL_SIDES);
}
if(command == "show")
{
llSetAlpha(1.0, ALL_SIDES);
}
}
}
}
}



It feels like objectname is being used to represent two different things to me. First it's used to represent what it should be listening to on channel 100 and also it's used to keep track of the name of the object it is in. And yet when the value for objectname is changed, the name of the current object is not changed.

I don't know if that helps, but in cases like this, I always add a simple command at the beginning of the listen event where it just spits out the message into chat -- llSay( 0, name+": "+message ); -- to see what is going on. You might also add another debug line which lets you know what the value for objectname is.
_____________________
imakehuddles.com/wordpress/
Kenn Nilsson
AeonVox
Join date: 24 May 2005
Posts: 897
10-30-2005 11:54
Well...I have to embarassingly admit that it appears the only failure was due to some weird activity on the SL Grid last night...

...I have re-logged on and tried the script again today and it works perfectly (without changes)...

...but...for academic reasons, I'll answer your comments regarding the script I had written (it should be beneficial to all of us):

CODE

getlisten()
{
// First question is what is the purpose of these first two lines? It opens a listener
// and then immediately closes it.
handle = llListen(100, objectname, NULL_KEY, "");
llListenRemove(handle);

objectname = newname;

// When objectname equals the name of the current object, it will not hear chat from itself. Only other objects with the same name.
llListen(100, objectname, NULL_KEY, "");
}


The getlisten() method is called to remove old listens and re-install new listens when the object changes name. Yes, the first time the method is called, it will stop listening before it starts...but once someone calls a name change...the object will stop listening to the old-named object and then re-listen to the new-named object.

Yes, I am aware that an object will not listen to itself, but I have a group of about 30 objects that share the exact same name and listen to eachother (for ease of use).

CODE

if(command == "name")
{
// This looks strange to me... so one of the commands renames
// the object it is listening to on the 100 channel?
// One side affect of this is when the getlisten is called, it changes
// objectname it now listens to on 100 and it will change in effect
// channel 99, since callname must match objectname.
newname = llGetSubString(message, 5, -1);
llInstantMessage(id, "Vendor name changed to: " + newname);
getlisten();
}


This snippet of code allows the owner to type "/99 <objectname>:name <newname>" and rename the entire 30 object set to something else. The purpose of doing so is to change the listen characteristics. That way you can have one "set" of objects named "My vendor 1" and another "set" of objects named "My vendor 2" within listen distance of eachother, and their commands won't collide.
_____________________
--AeonVox--

Computer games don't affect kids; I mean if Pac-Man affected us as kids, we'd all be running around in darkened rooms chasing ghosts, eating magic pills, and listening to repetitive, addictive, electronic music.
Keiki Lemieux
I make HUDDLES
Join date: 8 Jul 2005
Posts: 1,490
10-30-2005 12:12
Alright... for academic purposes, I have a couple of follow up questions:

CODE
getlisten()
{
handle = llListen(100, objectname, NULL_KEY, "");
llListenRemove(handle);
objectname = newname;
llListen(100, objectname, NULL_KEY, "");
}


So... when you have in effect a duplicate llListen to previous one, it replaces it? Intuitvely I would think it might create a second one with a separate handle, so you end up creating a new listener each time you call this function.

The other question is did you must have taken out the commands that actually change the name of the object? Cause I don't see one in your code.
_____________________
imakehuddles.com/wordpress/
Kenn Nilsson
AeonVox
Join date: 24 May 2005
Posts: 897
10-30-2005 12:21
Hmmm...well, the getlisten() method works as follows:

CODE

getlisten()
{
handle = llListen(100, objectname, NULL_KEY, "");
//handle is an integer set to be equal to the prviously active listen function.
llListenRemove(handle);
//the listen function identified by "handle" is removed.
objectname = newname;
//the objectname is now set to the newname.
llListen(100, objectname, NULL_KEY, "");
//a new listen is created that listens to the objectname.
}


Yes...I took out everything that wasn't necessary :)
_____________________
--AeonVox--

Computer games don't affect kids; I mean if Pac-Man affected us as kids, we'd all be running around in darkened rooms chasing ghosts, eating magic pills, and listening to repetitive, addictive, electronic music.
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
10-31-2005 06:08
Kenn, there is no guarantee that a repeated call to llListen with the same filter will return the same handle. Even if does now - LL may change the behaviour at any time - as it is undocumented behaviour.

The correct way to do this would be something more like:
CODE
integer ListenHandle;
getlisten()
{
if (ListenHandle)
llListenRemove(ListenHandle);

objectname = newname;

ListenHandle = llListen(100, objectname, NULL_KEY, "");
}

...
...
...

default
{
state_entry()
{
ListenHandle = 0;
...
}
...
}
Argent Stonecutter
Emergency Mustelid
Join date: 20 Sep 2005
Posts: 20,263
11-01-2005 11:07
From: Kenn Nilsson
Hmmm...well, the getlisten() method works as follows:
//handle is an integer set to be equal to the prviously active listen function.

No, handle is an integer set to be equal to the listen function you just called. Apparently LSL is sloppy about the handles and the way it re-uses them, because that code shouldn't work.