Add a way to access linkset data from a different linkset.
tracked
Jasdac Stockholm
Proposal:
llLinksetDataWritePublic( string name, string value, string password, integer perm_mask )
If password is an empty string, it does what llLinksetDataWrite does, plus setting a perm mask for that name.
If password is not an empty string, it does what llLinksetDataWriteProtected does, plus setting a perm mask for that name.
Perm mask can be a bitwise combination of:
LINKSET_DATA_OWNER_READ: Allows scripts with the same owner to read.
LINKSET_DATA_OWNER_WRITE: Allows scripts with the same owner to write
LINKSET_DATA_GROUP_READ: Allows scripts with the same group to read.
LINKSET_DATA_GROUP_WRITE: Allows scripts with the same group to write.
LINKSET_DATA_PUBLIC_READ: Allows any script to read.
LINKSET_DATA_PUBLIC_WRITE: Allows any script to write.
The permissions are dropped on:
- Using llLinksetDataWrite / llLinksetDataWriteProtected on the same name (this fixes the issues of someone preloading an object with tons of public values).
- Deleting the key through llLinksetDataDelete... or llLinksetDataReset.
To access the data from a different linkset, use:
string llLinksetDataReadRemote(key uuid, string name, string password)
integer llLinksetDataWriteRemote(key uuid, string name, string value, string password)
These function exactly the same as the non-remote versions, except with a key specifying the prim to read from.
---- Why this? ----
If you're gonna work on a large scale project in SL you're likely going to have to keep some data synced across linksets. This can be anything from a game controller keeping list of player HUD UUIDs, or player metadata such as skill points, status effects such as "broken leg" etc that players and NPCs can react to. In order for linksets to acquire such data, you have a few options:
- A remote server / experience keys: These are relatively slow, and asynchronous, meaning you often have to rely on caching since you can't easily or frequently access the data.
- Listeners: These are faster, but requires some sort of syn/ack system, fallbacks (because listeners have a tendency to fail during lag spikes) and a lot of string parsing, eating up significant script time as you start adding more and more NPCs that all need to be kept updated.
- Descriptions: These are fast and synchronous, but limited to 127 characters and don't allow special characters. And the attachment would need to be either attached to a non-HUD slot, or you'd have to cache the HUD UUID somewhere. In which case you're back to square one.
Being able to using public linkset data would have the following benefits:
- The data is synchronous.
- The data is never dropped because of lag spikes.
- The data doesn't require two-way communication.
- The data isn't limited to 127 characters and may use unicode.
- The data doesn't require your script to perform time-consuming string parsing since linkset data uses key/value pairs.
Personally I'm mostly interested in the reading part, but I know some people have been asking for the ability to write, so I included it in the proposal.
Log In
Nexii Malthus
I think the API should be simplified as possible, so that most calls like read/write are identical to the normal linkset data functions apart from the function names.
Instead there should be a setup call that configures which object to target and any remote pin / password needs.
For example:
llRemoteLinksetDataTarget(key target);
llRemoteLinksetDataWrite(string name, string value);
string bar = llRemoteLinksetDataRead(string name);
Nexii Malthus
Although in the context of SLua, separate functions might make better sense now, the simplification was just wanting to avoid the sprawl of the API surface
Jasdac Stockholm
Doing a little bit more thinkering. An issue that is that a script may crash if you try to read a value that's longer than your remote script can handle. Which is fine when you're working within a linkset where you have more control over what goes where.
But then I realized that HTTP requests solved the issue by letting you specify a body maxlength. As such llLinksetDataReadRemote(key uuid, string name, string password) should probably have a MAX_LENGTH parameter:
string llLinksetDataReadRemote(key uuid, string name, string password, integer maxLength)
Where a maxLength of 0 or less would mean "unlimited".
ST33LDI9ITAL Resident
Somewhat related: https://feedback.secondlife.com/scripting-features/p/changed-event-for-name-and-or-description
Boils down to one issue, easily accessible data store.
" I think the bigger issue though and related to this is that.. we don't have an easily accessible editable data store accessible from both lsl and gui. Because, here's the thing, alot of people use descrip to plop and manipulate data into.
Why? Because it's easy, quick, and accessible. From both lsl and gui. Can be picked up right away by other objects with llGOD.
Notecards are a thing, they trigger changed_inventory, can be read remotely, but aren't writable from lsl and also have their quirks. LSD is writable from lsl but not gui, not accessible remotely. So have to plop in some clunky menu or chat listen code or such for input. No easy way to see and edit something. Also doesn't trigger changed.
So we need some sort of solution to this. Ultimately, a gui for LSD and changed event trigger, and remote LSD or making notecards editable from lsl. "
The issue with writable notecards would be that you couldn't use them in realtime fast access scenarios like you could with LSD.
This would address a large issue with LSD but still need to address the accessibility of it.. it's not accessible like notecard/script from gui. Also doesn't trigger changed event. For script comms you probably wouldn't want a trigger for performance but it would have it's usefulness for data store.
Nelson Jenkins
One major problem I'm running into lately is that linkset data is lost on unlink.
I've got an API script that stores everything in linkset data, which lets the script remain stateless - very useful for a few reasons. I don't want to lose that configuration when unlinking the object from a linkset, but linkset data gets erased on unlink, so I need to keep a backup copy in memory. Right now, all of that is managed through a complicated library that keeps the linkset data and script memory synchronized.
If I could instead be able to "reach out" to the original parent object after unlink, I could simply duplicate the necessary linkset data pairs and save a few kilobytes of memory across dozens if not hundreds of scripts in a region.
edit: I've wasted about a month now trying to figure out a way to do this without wasting tons and tons of memory duplicating everything in linkset data into memory. The only solution I can think of is storing all of that in a notecard, which basically defeats the whole point of linkset data in the first place. I have no damn idea why linkset data gets erased when unlinking a child prim, but it's made linkset data effectively useless for this application until the feature request gets implemented. Sigh. Well, I tried...
JoyofRLC Acker
This could also reduce use of https and email for grid wide inter object communication (eg windsetters for sailboats). InstantMessage only works for agents not objects. And llRegionSayTo is (obviously) not grid wide. And as others have noted many client server type applications.
Using https and email has to be cumbersome in terms of underlying resources plus gives too many opportunities for poorly written implementations.
A good language environment for amateur coders should, inter alia, aim to simplify and minimise the code that needs to be written for any given application.
Signal Linden
tracked
Signal Linden
Hey, Jasdac Stockholm, I can definitely understand the appeal of a better script-to-script communication system. Would it be reasonable to focus on a new communication method rather than using LSD as a vehicle for communication? (Any ideas here?)
Jasdac Stockholm
Signal Linden The major pain point is that the data should be synchronous. Async wouldn't be that much of an issue if LSL did like how javascript does async/await. But since LSL doesn't come with a built in callback system, we're forced to build systems that sends/receives messages, handles potential dropped messages due to lag, edge cases such as sending a request to an object that gets deleted or returned before it can respond. Etc.
It's basically a massive headache even to do something simple like reading a list of UUIDs from a "game server" prim that keeps track of players in the game and scores etc. Remote LSD would allow us to call a single function in line to read a value from an object.
In my case I only care about the ability to READ data. Like what you can currently do with object descriptions, but without the need for heavy string parsing and without the 127 character limitation.
If the WRITING section of the feature request is making it too complex, I'd personally be 100% fine with scrapping that part. As I have no use case for remote writes. I know some people want that feature tho, so I'll let them argue why it should stay.
That said, a better communication method than listeners would be very welcome. But I feel like that's a separate issue.
Jasdac Stockholm
I figure I should probably post a use case as well:
In a game, players wear a HUD and there's a prim (we'll call it the Server) where the host can add or remove players in the active skirmish using an llDialog. Upon inviting:
- The Server stores the invited player UUID, and sends an invite to their HUD.
- The HUD shows a dialog to the owner asking if they want to join. If they hit yes, it responds to the server.
- The server sees that the HUD has been invited, and adds them to the list of active players. It then sends the HUD a list of players in the game, and it sends every user in the game a new list of players.
- The HUD stores the Server UUID and a local copy of the player list in its local linkset data.
- Players in the game interact using listeners. The listener checks through its local copy of the player list if the player who sent the message is actually in the game. It may also need to check data such as player teams, scores, levels etc.
This works (generally) but has some drawbacks:
- Dropped messages: One of the HUD update messages may get dropped. Suddenly one player can't interact with another because they're not in the list, or on the wrong team etc.
- Race conditions: A player may change team, but still be seen as belonging to another team in the time it takes for the Server to update all the HUDs.
- Listener overflows: If your dataset grows larger than 512 characters (14 UUIDs), you'll need to develop a system to send data in chunks.
- Lag: Let's say we add a bunch of item drops and NPCs, if we have 14 players we may need a hundred scripts to parse 504+ character long messages. And that's just to keep the player UUIDs in sync. You may need to sync other data like teams or HP.
If we instead had the option to make that data public on the server:
Step 1&2 are the same.
. 3. The server no longer needs to send a list of UUIDs, the HUDs and objects can read that from the Server.
. 4. The HUD stores only the UUID of the Server.
. 5. When an interaction is received, the HUD checks for the data in the Server synchronously. There's no risk of dropped messages, race conditions or listener overflow. And since the data only exists in the Server, you no longer need to store all that data in every HUD or object you want players in the game to be able to interact with.
The main issue I'm hoping this feature will solve is how to keep multiple linkets "synced".
WolfGang Senizen
Signal Linden Synchronous script to script RPC?
Script 1 sets a secret ->
llScriptRPCSecret(<secret>);
Script 2 requests RPC access with said secret ->
llScriptRPCRequest(<object_uuid>,<script_name>,<secret>);
Script 1 Approves the RPC access request (would probably need a new event)
Script 2 recieves said approval with some sort of handle
Script 2 can now call SYNCHRONOUSLY
llScriptRPC(<handle>,<function_name>,<list_of_arguments>);
Which executes the userfunction in script 1 and returns its value (maybe only list return types)
I mean, i know this can't happen easily especially with the imense ammount of schenanigans this would enable, like changing values in another script..... but I can dream can't I?
Nexii Malthus
Signal Linden the pain of listeners is synchronising data. If the new communication vehicle does not address this issue then it is no better.
You need to: a) get data, b) serialise, c) pass messages, d) deserialise, e) verify/authenticate, f) save data. This is a lot of steps.
By serialise/deserialisation I don't mean just typecasting here but having to construct a message packet with commands, deconstruct it and create complex if-else branches (CRUD; the classic Create, Read, Update, Delete commands) and loops (Bulk / Unstructured messages) to handle these. Only then add typecasting on top of that mess. Ugh.
Then if you want to pass additional config/data you need to overhaul the entire system from start to end.
LSD is great alternative because it is direct (sim handles background details; user doesnt have to do custom message parsing), simple (functions have few arguments) and persists (survives resets, prim prop).
Remote LSD would skip the steps inbetween to allow a) to f) and save a ton of script memory / overhead. There is also the linkset data event already for notifying changes.
Use cases:
- Game Manager that shares a lot of game state that smaller objects can access, such as vehicles, NPCs, door keys/access, etc.
- Resource Manager, like just centralises resources such as mana for an avatar to multiple attachments (HUDs, Weapons), ...
- House Manager that shares info about room lighting, doors, security, ...
- Region Manager that shares custom data related for multiple objects across the sim
- Traffic Lights Manager that shares state info of traffic intersections to many simulated vehicles
LSD is really nice because the API is very simple. Remote LSD should be the same.
Would most objects only remote LSD from one object or multiple? E.g. should every remote LSD call reference the target? Or should there be a configuration to set the remote target once?
For example:
key target = "d9ed6a8b-acca-b406-b7bf-d95950f18462";
llRemoteLinksetDataWrite(target, "foo", "value");
string bar = llRemoteLinksetDataRead(target, "bar");
or:
key target = "d9ed6a8b-acca-b406-b7bf-d95950f18462";
llRemoteLinksetDataTarget(target);
llRemoteLinksetDataWrite("foo", "value");
string bar = llRemoteLinksetDataRead("bar");
I prefer the latter myself. Also might easy any implementation requirements such as if you had to use a remote script pin to use remote LSD, without having to refer to it as an additional argument each time.
Nexii Malthus
Something potentially really neat is that remote LSD could also be used for a target object that doesn't even have a script. Allowing multiple objects to use a central resource object that is actually scriptless. That is wild!
Extrude Ragu
+1
Synchronous access to Linkset Data would also mean scripters are no longer forced to use the object description. It will have the side effect of improving object metadata on the grid, ultimately giving greater accessibility.
Woolfyy Resident
You can already communicate with messages on a dedicated channel.
It is how i already control several builds in one area according to my own protocol. and I also have builds controlling each other as well as lowering script use thx to a client / server communication in between those builds.
At the end, correctly set it even makes it possible to load balance in between prims and scripts.
Plus a trick for your description limit = transform chars in bitwise flags = super quick and efficient ... at the end looking like kanji chars in a description which makes them hard to "decrypt" for players unless you told them what is your own "internal cooking".
PS: Security can be achieved with groups, UUIDs etc.
Jessicatz Fairymeadow
I'm working on experiences that would greatly benefit from a way to remotely read LSD in a safe way, +1.
I also made a ticket for it on the old JIRA. I agree reading is the most important bit, writing would be a bonus.
Load More
→