Jump to content

Communication with many script files in 1 prim


XbabylonX
 Share

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

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

Recommended Posts

Hello,

I have 1 prim to be used as a server and inside this many different script files.

I want to send several commands to this prim using a hud, but each command must point to a different script file (the ones inside the prim).

I know I can send a llRegionSay message to a channel but pointing to a different script file each time, makes me confused. I want to always use the same channel but to a different script file. Can this be done?

Thank you!

Link to comment
Share on other sites

Hi,

every single script file in there supposed to send a message to a certain avatar.

For example:

script_A=sends message to Joe

script_B=sends message to Helen

and like this way, many different scripts inside that prim.

 

The hud I use, has many buttons, as many the script files exist. So:

Button 1 needs to communicate with the script_A

Button 2 needs to communicate with the script_B

etc etc.

Link to comment
Share on other sites

So button 1 uses channel -37262534 + 1
button 2 uses channel -37262534 + 2
and so on (for example).

Why is that a problem?

Listen is listen. If all scripts listen on one channel or every script on its own channel makes no difference.

To save listens you can make 1 script listen and relay the messages by llMessageLinked to the other scripts. In this case again every script will be triggered on every message but only one listen is used.

Most probably many listens are better than many unnecessary triggers. But that depends on the single case and on how often and how many messages you expect.

Are you sure you need many scripts? Maybe one script can handle all this.

 

Link to comment
Share on other sites

Because I want to dedicate to each avatar a certain memory.

The message sent to Joe, animates him with a certain animation.

The one sent to Helen, animates her with another certain animation.

If using the same file script, they will both animate with the same animation, even if I choose a different one for each.

Link to comment
Share on other sites

I see.

One script can animate multiple avatars with multiple animations but has to ask for permission everytime. So you need 1 script per avatar. In this case everyone needs to give the permission once.

Maybe you want to read about the experience tools that will become added to SL "soon". That will allow to handle this with one script but I have no clue how long it will take until release.

How many is many?

20 is nothing and it doesnt matter how you handle this.

100 is worth to think about it.

1000 is too many and you need to spread that on multiple prims.

Link to comment
Share on other sites

when want to play different animations on more than one avatar at the same time then

each avatar needs to have its own script for the permissions needed (as you mention)

do a web search for LIBRARYDANCEMACHINE for an example of how this can be done

Link to comment
Share on other sites

The point is that I actually use this prim (server) as a public ao.

I have it ready but when an avatar click to stop the assigned to him standing (or walking or anything) animation, the command affects the avatar who last clicked on his hud. The script file has in the memory the wrong uuid. 

llSetAnimationOverride cant target a certain person.

As for the number of people, can be up to 100. I guess.

Link to comment
Share on other sites

it will be a lot easier for us to help if you post code snippets of which parts you are stuck on. And any mods you have attempted yourself

if you dont post your attempted mods then the answer is going to be that you be best to put a addy in Help Wanted. Like pay someone to do it for you

if do post some mods then you will get help most likely. bc people on this forum are happy to help you learn but arent going to do it all for you. Like help you to learn how to script  

Link to comment
Share on other sites

Im not stuck. Since llRequestPermissions(uuid, PERMISSION_OVERRIDE_ANIMATIONS) keeps in memory the last avatar, everyone else when using their huds, by clicking their buttons, only instruct the prim server to swicth animations for that last person.

I need a different approach, thats why Im asking how to point to different script files.

 

Link to comment
Share on other sites

you need a control-slave design

where the control script maintains a list of

- active users keys
- active channels (one for each active user)
- active scripts (one for each active user)

when a button is touched then the control script presents a dialog listing the active users. The person touching can then choose which active user the button action is to be applied to

+

eta

you may or may not need to maintain a active channels list in some cases. Depends on what else the app may or may not be doing

eta my eta

if each active user has own HUD and wants to animate any or all other active users then yes, defo need to maintain a list of active channels

in this case then one of the active HUDs needs to act as the master-master script. So that conflicts between the multiple master scripts (one in each active users HUD) can be resolved

to make this seamless then when the user HUD acting as master-master drops out then one of the other actives needs to take over the role

+

eta more

what Nova said below

 

Link to comment
Share on other sites

A visitor can get a hud and animate themselves?

Thats not that simple. It's similar to a danceball and it's a good idea to modify a free danceball script.

The server needs as many driver scripts as avatars fit into the sim.
The server needs a master script that keeps track who is using which script and which script is free.
An avatar gets a hud and a message is sent to the master script.The Master script finds a free driver and messages the driver script the avatar uuid.
Driver and hud need to setup a communication. One way is to calculate a channel # out of the avatar uuid. The hud can do the same and send the button commands over that channel.
The driver needs to check from time to time if the avatar is still there. If not its free and tells the master script about that and logs the avatar out.

Thats the raw plan. There are surey a few details that need attention.

Link to comment
Share on other sites

just thinking about this more. Can do this quite simply design-wise

+

if can only animate another user who is wearing a HUD then

only need one script in each HUD, one channel and a communications message protocol

the HUD script animates the HUD wearer in response to a comms message sent by another

the advantage of only one channel is that every user can be told/know who is currently animating who

any conflicts can be resolved by the wearer of the HUD. i.e. block this user(s)|all while I am being animated by someone else, or even maybe if I am animating myself 

+

if can also animate another person who is not wearing a HUD then

need a additional script for each person (same as a multi-dance ball). With some stop/escape chat command for that person

Link to comment
Share on other sites

Too complicated and my head is hurting me right now. I will carefuly read again tomorrow your suggestions.

A thing I forgot to mention is that not anyone will have this hud available. This part will be controlled by me.

Link to comment
Share on other sites

I admit that I don't understand this application enough to see why there needs to be a HUD involved at all, but one reminder: the script that exercises permission to animate must be in the same object as the animation it will use. So that means the HUDs cannot contain the scripts that animate unless they also contain the animations, and then the animations will need both copy and transfer permissions. (But maybe nobody was talking about animating from the HUDs anyway, I'm not sure.)

Just in passing, the reason Experiences will make this a lot easier is that any script compiled using an Experience can obtain runtime permissions from anybody enrolled in that Experience. They don't need to retain those permissions in the script itself, and hence a single script can choose which of the Experience-enrolled agents for whom it will exercise permissions at any time. (Bottom line: Would eventually need just one script for this application, or maybe one script and a bunch of KVP storage that's also part of Experiences.)

But Experiences aren't generally available yet, so yeah, I gather that what's wanted is an animation server, the simplest model of which is a dance machine. This is no doubt a more sophisticated application than a simple dance machine, but the details here just aren't coming into focus enough to even know what the actual problem is.

Link to comment
Share on other sites

Well I see that the way to achieve it is too much for my skills. I will dedicate a prim server for each person I want to give the hud. Then Ill have to see if this project produces too much lag in the sim.

Thank you all for your answers!

Link to comment
Share on other sites

Don't give up just yet.   I was having a play with this late last night and I don't think it's particularly difficult to do what you describe,insofar as I understand it.

You have some form of animation server that has to hold animation permissions for multiple avatars, which means one script for each animated avatar.

You want to use a HUD to send commands to this server, pertaining to individual avatars (e.g. play such-and-such an animation for this particular avatar).   As Qie notes, you'll need to have the animations in the server rather than the HUD, but presumably you've thought of that.

Anyway, the basic mechanism seems simple enough.   

HUD sends message to server giving the uuid of the avatar and the animation to be played.

Server contains a main relay script, to handle all incoming messages.   This script is the only one listening.   It parses the HUD's message, and then sends a link message to all the animation scripts, containing a number to indicate it's a request to play an animation, the name of the animation to be played, and the uuid of the avatar to be animated.

Each helper animation script, on receiving the message, does something like this: 

 

	link_message(integer sender_number, integer number, string message, key id)	{		if (number == 999 && id == llGetPermissionsKey()){			//number indicates thisis a request to play an animation, and the id is that of the avatar I am animating			if(llGetInventoryType(message)==INVENTORY_ANIMATION){//and the animation is one in my inventory				llStartAnimation(message);			}		}	}

That's off the top of my head, but I think logic there would work.

Link to comment
Share on other sites

Hello,

the server I created contains all the animations I want to use because they are not trasnferable, so indeed the shareable huds do not contain any of them.

In your example you say "It parses the HUD's message, and then sends a link message to all the animation scripts" , which are the animation scripts?

Link to comment
Share on other sites

As you've rightly noted, a script can hold permissions to animate one avatar at a time.   This means that any sort of animation server has to contain one animation script for each avatar you want to animate.    You have to decide how many scripts that is.

It's not at all clear to me how far you've got in your design but it seems to me that you need one main communicator script, to handle all communications between the animation scripts and the outside world, and a number of animation scripts, identical save for their titles.

So, you might have a set-up whereby an avatar touches the server to register with it and de-register (as in a dance ball).   The communicator script would detect the touch and would somehow need to know whether the avatar is already registered (and wants to de-register) or, if it doesn't recognise the avatar, if it needs to register him and, if so, to which animation script.

There's various ways of doing that.   I would take advantage of the fact that, if you drop several copies of a script called "animator" into a prim, SL will label them for you automatically, so you end up with "animator", "animator 1", "animator 2" and so on.

You can use this to assign an index number to each copy of the script you drop in, thus:

string baseName = "animator";integer myNumber;default{    state_entry()    {       string str = llDeleteSubString(llGetScriptName(),0,llStringLength(baseName));          myNumber = (integer) str;         llOwnerSay(llGetScriptName()+": My number is "+(string)myNumber);    }}

(the first instance of the script, called simply "animator", is has the number 0.

So, I would have a list in my communicator script, AvatarsAndScriptNumbers, which I would use to store the uuids of avatars using the server and the index numbers of the scripts holding their animation permissions.

When someone touches the animation server, the communicator checks the list to see if the toucher's uuid appears there.  If it doesn't, I'll send a message to the script simply called "animator"  containing simply the uuid of the avatar who needs to be animated.

Something like 

//THIS IS JUST A FRAGMENT AND WON'T WORK AS ISlist AvatarsAndScripts;default{    state_entry()    {       // llSay(0, "Hello, Avatar!");    }    touch_start(integer total_number)    {       key k = llDetectedKey(0);       integer n = llListFindList(AvatarsAndScripts,[k]);       if(!~n){          //not on the list, so let's find a script to animate the av          llMessageLinked(LINK_THIS,0,"",k);         }    }

Inside each copy of the animator script, I have something like this:

//THIS IS JUST A FRAGMENT AND WON'T WORK AS ISstring baseName = "animator";integer myNumber;integer isKey(key in){    if (in)        return 2;    return (in == NULL_KEY);}default{    state_entry()    {        string str = llDeleteSubString(llGetScriptName(),0,llStringLength(baseName));        myNumber = (integer) str;        llOwnerSay(llGetScriptName()+": My number is "+(string)myNumber);    }    link_message(integer sender, integer num, string msg, key id){        if (num == myNumber){//it's for me            if(msg == "" && isKey(id)){//no message and a valid uuid                //it means the communicator script is trying to animate the avatar whose uuid it is.                if(isKey(llGetPermissionsKey())){                    //if I am already animating someone                    if(id!=llGetPermissionsKey()){//sanity check                        llMessageLinked(LINK_THIS,(myNumber+1),"",id);                        //pass the message on to the next script                    }                }                else{//I am not animating anyone, so I am available to animate the avatar                    llRequestPermissions(id,PERMISSION_TRIGGER_ANIMATION);                }            }        }    }    run_time_permissions(integer permissions)    {        if(permissions & PERMISSION_TRIGGER_ANIMATION){            //do something to animate the avatar, presumably, and also            llMessageLinked(LINK_THIS,myNumber,"now animating",llGetPermissionsKey());            //send a message back to the communicator script so it knows who I am now animating        }    }}

Then, back in the communicator script, I can add something like this:

//THIS IS JUST A FRAGMENT AND WON'T WORK AS IS    link_message(integer sender, integer number, string str, key id){        if("now animating"==str){            AvatarsAndScripts+=[id]+[number];            //store the uuid of the avatar and the number of the script that is holding the animation permissions        }            }}

 I can also add to the touch event to test whether the avatar wants to de-register and tell the appropriate script what to do:

//THIS IS JUST A FRAGMENT AND WON'T WORK AS IS    touch_start(integer total_number)    {       key k = llDetectedKey(0);       integer n = llListFindList(AvatarsAndScripts,[k]);       if(!~n){          //not on the list, so let's find a script to animate the av          llMessageLinked(LINK_THIS,0,"",k);         }        else{          //is on the list, so let's de-register the av          integer int = llList2Integer(AvatarsAndScripts,(n+1));          //the script number, which is stored immediately after the uuid          llMessageLinked(LINK_THIS,int,"stop animating",k);          //tell the appropriate script to stop animating the avatar          AvatarsAndScripts = llDeleteSubList(AvatarsAndScripts,n,n+1);          //remove the avatar and the script number from the list             }    }

 You should now be able to write the code in the animator script to handle the "stop animating" message.

This is only part of the project, of course, but I hope it's enough to get you started.

Link to comment
Share on other sites

Thank you very much for your efforts to help me.

The main concern was to save prims (servers) for each of my members. Then I thought that every member has an adboard on the sim, so I could use it as the animation server too.

So now, the hud each person use, sends region messages to its own adboard (also as server) and the problem solved.

Again so sorry to make you spend your time to find a solution. I really appreciate it and thank you!

 

 

Below is the code I wrote for the HUD (Script for the root)

 

list Anims=["..."]; //ARRAY WITH ANIMATION NAMES AND DURATION eg "Anim1__30.0","Anim2__28.0"string Version;float amt=180;integer Channel=-1000;//TO COMMUNICATE WITH THE SERVERstring Pose="Standing"; //ANIMATION TYPE TO SEND TO THE SERVERstring Pose_Explained="dance";key Who;string Status;string Anim;string Group;string Rand;string Seconds;list randomizedList;integer Timestamp=0;integer Diafora;Send(string A, string B, string C){llRegionSay(Channel,Version + ":" + A + ":" + B + ":" + C);}Random(){randomizedList=llListRandomize(Anims, 0);Rand=llList2String(randomizedList, 0);list Response=llParseString2List(Rand,["__"],[""]);Anim=llList2String(Response,0);Seconds=llList2String(Response,1);Send("1",Pose,Anim);}default{    on_rez(integer start_param)    {        if (!llGetAttached()) {        //llInstantMessage(llGetOwner(),"Do not rez me. Just wear me as a HUD!");        //llDie();        }    }    state_entry()    {    Version=llGetObjectDesc();    Who=llGetOwner();    }    touch_start(integer total_number)    {    llSetLinkPrimitiveParamsFast(1,[PRIM_ROTATION,llGetLocalRot() * llEuler2Rot(<0,0,(amt*=-1)>*DEG_TO_RAD)]);//FOR ROTATING THE HUD (LINKSET)    }        link_message(integer sender_num, integer num, string str, key id)    {    list Response=llParseString2List(str,[":"],[""]);    Status=llList2String(Response,0);    Anim=llList2String(Response,1);    Group=llList2String(Response,2);    Diafora=llGetUnixTime()-Timestamp;    Timestamp=llGetUnixTime();        if(Diafora>5)//TO PREVENT ABUSING THE SERVER WITH CLICK FLOODINGS        {            if(Group!="1")            {            llInstantMessage(Who,"Only group stuff members can use this ao.");            }            else            {                if(Status=="0")//STOP ANIMATIONS                {                llSetTimerEvent(00.0);                Send("0",Pose,"none");                llOwnerSay("Quitting " + Pose_Explained + " animation!");                }                else if(Status=="1")//PLAY SINGLE ANIMATION                {                llSetTimerEvent(00.0);                list TheAnim=llParseString2List(llList2String(Anims,(integer)Anim),["__"],[""]);                Send("1",Pose,llList2String(TheAnim,0));                llOwnerSay("Now using " + llList2String(TheAnim,0) + " " + Pose_Explained);                                }                else if(Status=="2")//SEQUENCE                {                llOwnerSay("Starting random sequence for " + Pose_Explained + ".");                Random();                llSetTimerEvent((float)Seconds);                                    }                                                            }                    }        else        {        llOwnerSay("Please wait 5 seconds before using again this button!");        }                    }        timer()    {    Random();    }            }

 

 

Now the hud has some buttons linked.

1) Button for single animation (its description contains only the animation's place in the array l ist Anims=[...] which we can see in the hud above, 0 for the first animation, 1 for the second animation etc etc). So:

 

default{    touch_start(integer total_number)    {    llMessageLinked(LINK_ROOT, 1, "1:" + llGetObjectDesc() + ":" + (string)llDetectedGroup(0), NULL_KEY);    }}

2) Button for starting random animation sequence (object's description can by anything)

 

default{    touch_start(integer total_number)    {    llMessageLinked(LINK_ROOT, 1, "2:" + llGetObjectDesc() + ":" + (string)llDetectedGroup(0), NULL_KEY);    } }

3) Button to generally stop the animation or the sequence (object's description can by anything)

default{    touch_start(integer total_number)    {    llMessageLinked(LINK_ROOT, 1, "0:" + llGetObjectDesc() + ":" + (string)llDetectedGroup(0), NULL_KEY);    }}

And the server's script

integer listen_handle;integer Channel=-1000;key Who;string R1;string R2;string R3;string R4;string R5;string Accepted_Version="v1.0"; default{    state_entry()    {    Who=llList2String(llGetLinkPrimitiveParams(LINK_ROOT, [ PRIM_DESC ]), 0); //PERSON'S UUID    listen_handle = llListen(Channel, "", "", "");    }     listen( integer channel, string name, key id, string message )    {    list Response=llParseString2List(message,[":"],[""]);    R1=llList2String(Response,0);        if(R1!=Accepted_Version)        {        llInstantMessage(Who,"This ao version is old. Request a new one!");        }        else        {        R2=llList2String(Response,1);        R3=llList2String(Response,2);        R4=llList2String(Response,3);        state Adia;        }    }}state default2{    state_entry()    {    listen_handle = llListen(Channel, "", "", "");    }            listen( integer channel, string name, key id, string message )    {    list Response=llParseString2List(message,[":"],[""]);    R1=llList2String(Response,0);        if(R1!=Accepted_Version)        {        llInstantMessage(R2,"This ao version is old. Request a new one!");        }        else        {        R2=llList2String(Response,1);            if(R2=="1")            {            R3=llList2String(Response,2);            R4=llList2String(Response,3);            state Run;            }            else if(R2=="0")            {            state Stop;            }        }    }}state Adia{    state_entry()    {    llRequestPermissions(Who , PERMISSION_OVERRIDE_ANIMATIONS);    }    run_time_permissions(integer perms)    {        if ( perms & PERMISSION_OVERRIDE_ANIMATIONS )        {        state Run;        }        else        {        state default;        }    }}state Run{    state_entry()    {    llResetAnimationOverride("ALL");    llSetAnimationOverride( R3, R4);    state default2;    }}state Stop{    state_entry()    {    llResetAnimationOverride(R3);    state default2;    }}

Even it can be better written the whole thing, I tested for myself and is working. Next test will be with another one person at the same time with his own server and hud. And the final test will be with many more people to see if its going to create big lag.

 

 

Link to comment
Share on other sites

I'm sorry but I am now thoroughly confused.   This doesn't look much like what you described in your first post.

Anyway, I think that you are going to need to have your server check, when it receives a message, that the avatar whose hud it hears from is the same avatar who is renting that particular adboard (and whose uuid, I assume, is the one stored in key who;).

That's easy enough -- just test

 if (llGetOwnerKey(id)==who)

in the listen event.    

I think you're likely, as the script is written, to run into casting difficulties.   That is, while keys -- uuids -- are only a special sort of string, sometimes when lsl is testing things it's important whether they are both strings or both uuids and sometimes it's not.   I can never remember when it does matter, so I find it easiest always to cast them explicitly as the same type when I try to compare them.

So I would test for

if((string)llGetOwnerKey(id)==(string)who)

That might be over-cautious but it won't be wrong.

 

Link to comment
Share on other sites


XbabylonX wrote:

Not a problem with the uuid, because the adboard is rezzed by me, so I add in the description the person's key.
:)

Sorry people for confusing you, at the time I was writing the thread , I was so mentally tired lol

is all good. dont worry about it (:

is good that you got something working which is the main thing

like Innula said is some tidy ups you can do, but can work on that as you go on

+

ps

i thought you was actually writing a game. With a server and game HUDs (:

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 3272 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...