Jump to content

"Linkset Data" is coming.


Lucia Nightfire
 Share

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

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

Recommended Posts

3 hours ago, Qie Niangao said:

Right, but a page or so ago we were promised that the viewer interface to Linkset Data only needed a simple read-only table and here under the tent I see the camel nose of feature creep. (I'd just note that ideally a scripter would provide some more helpful configuration UI than having to edit Description fields or Linkset Data directly, using the idiosyncratic "language" of that script's configuration parameters. Worst case, give the poor user a setup HUD, or at the very least a llTextBox with a clue-giving prompt.)

I worked with many content creators and - surprise! (for me too) - most of them prefer to use root prim description field, or (OMG) description field of each button. They find it convenient. I don't know why. I give them fullperm scripts but they love to edit description )

Edited by Elisabeth Ohmai
  • Like 1
  • Thanks 1
  • Haha 1
Link to comment
Share on other sites

I feel like this would be significantly more useful if we had a way to remotely access said data. One of the biggest issues when making games in SL is trying to sync data. Like trying to sync player HUD UUIDs in an active game between a multitude of HUDs. With an object description, you're limited to 3 UUIDs. Using the chat system to do that is laggy, async, and prone to events being dropped. The #1 issue when developing large games on SL for me has been to keep things synced.

What I'd like to see is something similar to remote loading:

llSetLinksetRemoteDataPin(int pin)
llRemoteLinksetDataRead(key uuid, int pin, string name);

And if the wrong pin is entered, do the same thing as llRemoteLoadScriptPin and sleep the script + delay.

That way you can pass the pin using messaging or if you want it to be public, just use a constant number.

I don't see the value in being able to write from another script, only read. While previously using prim media URLs to sync data, the best design has always been to assign write permissions for specific values to specific scripts, then using link messages or say messages to have that script update the value. Otherwise you have to battle race conditions.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

48 minutes ago, Jasdac Stockholm said:

One of the biggest issues when making games in SL is trying to sync data. Like trying to sync player HUD UUIDs in an active game between a multitude of HUDs.

I'm all for some means of remote access to Linkset Data, but this seems to match precisely the application for which Experience KVP was designed. Note that game participants can wear HUDs with Experience scripts without themselves being Experience participants (assuming that's a concern). It does mean that any land where the game HUD is used must enable the Experience (or at least anywhere the Experience-syncing script is active), but the Experience comes with 128MB of KVP, compared to the paltry 64K of Linkset Data per object.

If it's a commercial game with wide appeal, there's a practical choice to be made about who actually owns the Experience for a particular installation, and because Experiences are still Premium only (even if only used for the KVP store) there's some appeal to Linkset Data, despite Experience KVP having been developed specifically for this application.

Link to comment
Share on other sites

10 minutes ago, Qie Niangao said:

I'm all for some means of remote access to Linkset Data, but this seems to match precisely the application for which Experience KVP was designed. Note that game participants can wear HUDs with Experience scripts without themselves being Experience participants (assuming that's a concern). It does mean that any land where the game HUD is used must enable the Experience (or at least anywhere the Experience-syncing script is active), but the Experience comes with 128MB of KVP, compared to the paltry 64K of Linkset Data per object.

If it's a commercial game with wide appeal, there's a practical choice to be made about who actually owns the Experience for a particular installation, and because Experiences are still Premium only (even if only used for the KVP store) there's some appeal to Linkset Data, despite Experience KVP having been developed specifically for this application.

Mind blown! 

This could be used in conjunction with Experience KVP, via LSL scripting!

Example:

- Not in Experience region: "Offline", use Linkset KVP

- Check into Experience region to "Save" data: "Online", save Linkset KVP to Experience

 

Edited by Love Zhaoying
  • Like 2
Link to comment
Share on other sites

8 minutes ago, Qie Niangao said:

I'm all for some means of remote access to Linkset Data, but this seems to match precisely the application for which Experience KVP was designed. Note that game participants can wear HUDs with Experience scripts without themselves being Experience participants (assuming that's a concern). It does mean that any land where the game HUD is used must enable the Experience (or at least anywhere the Experience-syncing script is active), but the Experience comes with 128MB of KVP, compared to the paltry 64K of Linkset Data per object.

If it's a commercial game with wide appeal, there's a practical choice to be made about who actually owns the Experience for a particular installation, and because Experiences are still Premium only (even if only used for the KVP store) there's some appeal to Linkset Data, despite Experience KVP having been developed specifically for this application.

These games aren't installed, they're playable anywhere, so experiences won't do anything. Experience keys are also async, which LSD is not. And if you have your own server then HTTP requests becomes a significantly more powerful alternative to experience keys.

  • Like 1
Link to comment
Share on other sites

1 hour ago, Elisabeth Ohmai said:

I worked with many content creators and - surprise! (for me too) - most of them prefer to use root prim description field, or (OMG) description field of each button. They find it convenient. I don't know why. I give them fullperm scripts but they love to edit description )

You know, you're right; I've seen this myself. But I cringe each time I use the Description field because I know I'm just tempting fate that they'll add some other script that tweaks some other property based on descriptors with different flags and delimiters and everything will break and woe be unto me as I read that script's documentation and try to find a format that is mutually compatible with all the other "some other scripts" somebody is using for some other product.

It's the classic feature interaction problem, scaled down to SL-grade silliness.

Link to comment
Share on other sites

28 minutes ago, Jasdac Stockholm said:

These games aren't installed, they're playable anywhere, so experiences won't do anything. Experience keys are also async, which LSD is not. And if you have your own server then HTTP requests becomes a significantly more powerful alternative to experience keys.

Oh, I think I understand the application better. This would use remote access to Linkset Data in order to sync between player HUDs directly. That's a pretty cool approach, much tidier than other comms.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

4 minutes ago, Coffee Pancake said:

I don't think feature creep is a problem at this stage of development.

... we all know that once things are set in stone, no one will ever come back this way to add those features in later.

"Ask now, or forever hold your peace!"

Edited by Love Zhaoying
Ok, is "speak now" for marriages I guess.
  • Like 2
Link to comment
Share on other sites

4 minutes ago, Qie Niangao said:

As long as the viewer functionality only involves viewer developers, and the core scripting functionality can develop and release without waiting for a viewer, as far as I'm concerned those viewer features can creep to their hearts' content. PBR can wait.

Great point! Let the TPV's add a UI first for LSD! 

  • Like 1
Link to comment
Share on other sites

35 minutes ago, Qie Niangao said:

As long as the viewer functionality only involves viewer developers, and the core scripting functionality can develop and release without waiting for a viewer, as far as I'm concerned those viewer features can creep to their hearts' content. PBR can wait.

Don't let your impatience for the new shiny undermine and bite us all in the butt down the road.

31 minutes ago, Love Zhaoying said:

Great point! Let the TPV's add a UI first for LSD! 

If LL don't add the interfaces for the viewer to get the data, there can never be any UI.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

I have created a test script which allows to reset the LSD, store and read keys of it, and it remembers the number of keys it has stored. My Test Plan which I'd like to see to pass at every point is this:

  1. Reset LSD store, add 2 keys, list them - the script must know there are 2 keys in store and the store must have them (pass)
  2. Add 2 keys, detach, reattach the HUD -  the script must know there are 4 keys in store and the store must have them (pass)
  3. Add 2 keys, teleport out, teleport Back - the script must know there are 6 keys in store and the store must have them (pass)
  4. Add 2 keys, Crash the viewer, Relog - the script may think there are 6 keys in the store but the store must have 8 keys
  5. Add 2 more keys, Crash the viewer after 1 minute, Relog - the script may think there are 8 keys in the store but the store must have 10 keys
  6. Add 2 more keys, Crash the viewer after teleport out, teleport in, Relog - the script may think there are 10 keys in store but the store must have 12 keys
  7. Add 2 more keys, Crash the viewer after 15 min, Relog - the script may think there are 12 keys in store but the store must have all 14 keys

I not know yet which viewer error I take for crashing it, maybe I try more than one, but by now the test failed already on TP into region that not supports LSD and teleport back (as reported in this JIRA, there you can also find the script and the test build).

Why all the fuss. Sometimes my viewer crashes or internet disconnects. When I have bad internet sometimes, it can happen within 5 minutes online time and few of my friends have it quite often like this. When this happens, servers fail to write the state of the link set into asset servers, resulting in the loss of data and this data can be very important. And it is hard for the server to know which data is important on the particular link set and which is not.

For example I bought a dress and use texture HUD to style it. I crash after styling, the texture is lost, but after log in i use the HUD again and all is back and propper. No big deal to loose this texture to a crash. Now imagine the creator of the dress invented a revolutionary system where the textures are applied in their store after I paid for them. I paid 1000L$, the dress got all styled, I tp home, crash, log in at infohub and all textures are gone. I may pay an other 1000L$ now.

With Linkset Data we've got an excellent tool to explain the server which part of the linkset is important and has to be saved as soon as possible while the rest is of lower priority and must not survive any crashes. The texture receiver in my dress stores the textures into the LSD and then checks in on_rez() event if the stored data are newer than it knows and if so, it reads and reapplies it. Crashes are no more that bad any more.

At the last user meetings i was told that the Linkset Data was meant to be persistent but I am not sure if my question was understood or the answer was that the LS Data was meant to survive script crashes and resets but not the linkset' crashes. When this level of persistency was not planned originally, I think to fill a feature request to ask for it.

Edit

The version in Jira not remembers the number of keys (represents the linkset state not covered by the LSD system), so when interested, please use this script in an 3 prim HUD:

integer rows = 0;

resetRows() {
    rows = 0;
    llLinksetDataReset();
    listRows();
}

listRows() {
    llOwnerSay("Num Rows (in script): "+(string)rows);
    
    integer size = llLinksetDataCountKeys();
    list    keys = llLinksetDataListKeys(0, -1);
    string  text = "Num Keys (in store):  "+(string)size;
    
    integer i; for (i = 0 ; i < size ; i++) {
        string name = llList2String(keys, i);
        text += "\n\t"+name+" -> "+llLinksetDataRead(name);
    }
    
    llOwnerSay(text);
}

addRow() {
    string  name  = (string)(llLinksetDataCountKeys() +1);
    string  value = llGetTimestamp();
    integer add   = llLinksetDataWrite(name, value);
    
    rows          = llLinksetDataCountKeys();
    
    llOwnerSay("add row ("+name+" -> "+value+"): "+(string)add);
}

default 
{
    state_entry() {
        llSetLinkPrimitiveParams(1, [PRIM_TEXT, "add", <1,1,1>, 1]);
        llSetLinkPrimitiveParams(2, [PRIM_TEXT, "list", <1,1,1>, 1]);
        llSetLinkPrimitiveParams(3, [PRIM_TEXT, "reset", <1,1,1>, 1]);
    }
    
    on_rez(integer start_param) {
        listRows();
    }
    
    touch_start(integer num) {
        num = llDetectedLinkNumber(0);
        
        if      (num == 3) resetRows();
        else if (num == 2) listRows();
        else               addRow();
    }
}

Edit 2

Lucia answered in the Jira and named an other region that supports the system. Teleports between these regions retained the LSD data. So the point 3 is pass. Will continue with the test tomorrow.

Edited by Jenna Felton
linked script is incomplete
  • Like 2
Link to comment
Share on other sites

While we're spitballing ideas anyway: Another benefit of allowing remote linksets to fetch data is that it allows the community to set some standards for metadata. Perhaps a PIN of 0 could be used as a "my data is public, please read me" setting. Trying to read from PIN 0 on a linkset would just return an empty string and not throw an error. That way the community could agree on some standard keys for features like:

  • Footstep sounds: Footstep scripts could parse this for UUIDs for footstep sounds. Paired with the links having a short bit of info in the description like "FS:A". Then when you cast a ray at your feet, see FS:A in the description, you can fetch the list of sounds from the LSD key "FS::A" and play those sounds while walking. Right now what we do is store all the footstep sounds in a script, and set short tags for them to be read from the description. Such as "WOOD" for wood surfaces, just to be able to fit them into the description length. This would eliminate the need for storing all the footstep sounds in a central HUD, allowing for less script memory use and an infinite variety of sounds.
  • Climbing: In GoThongs, to climb ladders, shimmy walls, ropes etc we use an invisible prim spawned by each user's HUD called a supportcube. Currently the HUD raycasts for prims with a climbing tag in the description. The tag is followed by positions, animations, and rotations used as keyframes. When the climbing starts it seats the player on the prim, starts the animation, and moves them along the path using llSetKeyframedMotion, resulting in a much less stuttering way of climbing than if you were to use llSetRegionPos or updating sit targets. The problem is that the description is very limited, so the description could instead point to an LSD key which had this metadata. Another perk of doing it this way is that you don't need a single script in ANY of the ladders/ledges in the entire level/sim!
  • Poseballing: In GoThongs/Fright we also used the supportcube system above to setup sit positions. This allows couches, beds, sofas etc to parse the description of the object for animations and positions. The HUD then sits the player on the supportcube, aligns, and poses the player based on the description. The problem with this is again that descriptions are very limited in size, and I don't think I've been able to make a seat that can handle more than 4 users at a time. The upside of doing it with metadata is that none of the seats need a single script, the user only needs their HUD script and a script in the supportcube. When it comes to larger areas, that's like 40-50 identical poseball scripts that can be deleted.

TL;DR: by using metadata and a HUD for interactions, you can remove a ton of scripts from your world objects when making experiences, games and such.

Edited by Jasdac Stockholm
  • Like 3
Link to comment
Share on other sites

1 hour ago, Jenna Felton said:
  • Add 2 keys, teleport out, teleport Back - the script must know there are 6 keys in store and the store must have them (failed)

Using a totally different test script, I can confirm that merely teleporting to and from a region that doesn't yet support LinksetData is enough to wipe it out, but that teleporting between two regions that do support it works as expected. (I used Blake Sea - Black and Mauve for testing the both supported condition, and Blake Sea - Black and Sistiana for the supported+non-supported condition).

In case anybody is looking for alternative Aditi regions with support, Mazidox listed them in this week's deployment plan:

Quote
  • Blake Sea - Arabian
  • Blake Sea - Atlantic
  • Blake Sea - Beagle
  • Blake Sea - Binnacle
  • Blake Sea - Black
  • Gothlauth
  • Jigglypuff
  • Mauve
  • Moonberry
  • Sapas
  • Smithereens
  • Like 1
  • Thanks 2
Link to comment
Share on other sites

I suppose in a way it makes sense to have the datastore be lost if you move into a region that doesn't support it. The region has no understanding of the feature so not only can it not access it, but when you move to the next region it's not going to be to serialize it back up to send along to the destination. Even if the new destination does support the feature, as soon as you arrive in the non supporting region, the association is lost.

Edited by Fenix Eldritch
rewording awkard structuring
  • Thanks 1
Link to comment
Share on other sites

1 minute ago, Fenix Eldritch said:

I suppose in a way it makes sense to have the datastore be lost if you move into a region that doesn't support it. The region has no understanding of the feature so not only can it not access it, but when you move to the next region it has no knowledge of the feature so it won't serialize it back up to send along to the destination. Even if the new destination does support the feature, as soon as you arrive in the non supporting region, the association is lost.

You'd think..that when you go BACK into a region that DOES support it, the functions would work again!

Link to comment
Share on other sites

Not if said feature is an association. If the middle region doesn't know about the association, I wouldn't expect it to know how to handle it for the next hop. So the association is effectively severed. And from the final destination's perspective, this incoming object was fresh and without any datastore.

Edited by Fenix Eldritch
Link to comment
Share on other sites

Now that I see other posts, I realize I should have mentioned that teleporting to a region without LSD support only wipes the data if the object is attached during teleport (as a HUD would be). Probably obvious, but: take the thing into Inventory, teleport all around and back, then reattach: the LSD is still intact.

  • Like 2
Link to comment
Share on other sites

9 hours ago, Jasdac Stockholm said:

I feel like this would be significantly more useful if we had a way to remotely access said data. One of the biggest issues when making games in SL is trying to sync data. Like trying to sync player HUD UUIDs in an active game between a multitude of HUDs. With an object description, you're limited to 3 UUIDs. Using the chat system to do that is laggy, async, and prone to events being dropped. The #1 issue when developing large games on SL for me has been to keep things synced.

What I'd like to see is something similar to remote loading:

llSetLinksetRemoteDataPin(int pin)
llRemoteLinksetDataRead(key uuid, int pin, string name);

And if the wrong pin is entered, do the same thing as llRemoteLoadScriptPin and sleep the script + delay.

That way you can pass the pin using messaging or if you want it to be public, just use a constant number.

I don't see the value in being able to write from another script, only read. While previously using prim media URLs to sync data, the best design has always been to assign write permissions for specific values to specific scripts, then using link messages or say messages to have that script update the value. Otherwise you have to battle race conditions.

4 hours ago, Jasdac Stockholm said:

While we're spitballing ideas anyway: Another benefit of allowing remote linksets to fetch data is that it allows the community to set some standards for metadata. Perhaps a PIN of 0 could be used as a "my data is public, please read me" setting. Trying to read from PIN 0 on a linkset would just return an empty string and not throw an error.

TL;DR: by using metadata and a HUD for interactions, you can remove a ton of scripts from your world objects when making experiences, games and such.

Per KVP/row pins/passes would be good for this usage. Exposing just the rows needed with granularity.

Going with the game example, an object could have data that all other players' hud can access under one pin, data that only other team memebers' can access under another pin, a another pin that is a constant which forms part of a public API for third-party extensions (like public score boards, telling if somebody is in game, etc.), and everything else in the object's store as private or shared with links within the hud.

For remote access, read-only would be completely workable as each object could read from each other. I keep saying this... the same limits as llGetObjectDetails on where it can work are fine.

Right now, a lot of time, script time, sim time, and especially dev time is spent just getting data from one script in to other scripts.

I've had many projects balloon and eventually die due to rabbit-holing trying to make effective data serialization.The last few I seriously put effort in to (which was many years ago), couple/few weeks was spent on the actual proof of concept, but then many months to most of a year on just data packing and script-to-script messaging, which eventually results in abandoning when the partly working solutions to that core functionality become so complex that adding anything without starting over from scratch is now impossible. You almost have to hyper-optimize first just to get running, or just give up and do it all remotely on a web server while compromising on many ideas for real-time/low latency features.

The joke would be "fast, efficient, reliable; pick two", but usually it's "pick one as long it you pick low memory usage", because all roads lead to string parsing due to the lack of native data types in comms and script mem being highly restrictive even if the script purely dedicated to only serialization and comms. It'd be pretty much unpossible to implement something like ACK to deal with the random comms dropage problems without some steep trade-offs.

There's the potential that LSD could resolve many of the brick walls LSL has with storing and moving data around. As it is right now, its fixing a few, like having to make stored data as compact as possible. Buuut it'll be more awesome if takes away the months of creating project specific custom data (de)sterilizers/protocols and supplants it for using a handful of new llfunctions with much faster type recasting. :D

  • Like 2
Link to comment
Share on other sites

  • Lindens

Documentation for the LSL functions is up on the wiki but not yet linked to the main functions page. You can find it here:

https://wiki.secondlife.com/wiki/Category:LSL_LinksetData

On this roll I've added three new functions

llLinksetDataWriteProtected(string name, string value, string pass);
llLinksetDataReadProtected(string name, string pass);
llLinksetDataDeleteProtected(string name, string pass);

These functions create "protected" keys in the datastore. In order to update, read or delete a protected key/value pair you must provide the same pass string that you supplied when it was originally created. Protecting a key incurs a 32byte overhead in addition to the value and key length. 

Writing to a protected key without the correct pass string will fail and return LINKSETDATA_EPROTECT.  Reading a protected key without the pass string returns an empty string, and attempting to delete one fails silently. 

In the linkset_data event when writing a protected key, the value parameter will always be an empty string. 

Protected keys are removed by a call to llLinksetDataReset.

  • Thanks 12
Link to comment
Share on other sites

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