Extensible Prim Attributes from LSL
The Chicken and the Egg
There are many new features that can be implemented almost exclusively on the client side, but the main intention would be their use from LSL and/or the server side. The OpenSL project has little ability to work on these features without the corresponding LSL/server-side changes, and LL might be loathe to write in LSL/server side changes until the client side abilities are in place. This creates a classic chicken and egg problem.
Some examples of this are:
The Solution
A generic LSL function set to allow prim-specific communications to the client. This would allow tagging prims with arbitrary communications that the client can pick up and use for whatever purpose.
llSetMetaInformation(string payload); //sets metainformation for tag 0 for this prim.
This would be on a per-prim level, similar to llSetObjectDesc, except hidden to the user. The limit should be at least 1024 bytes. The payload need not persist when the asset is saved to inventory, but it would be nice if it did.
This MetaInformation would be tagged with a numeric identifier, always 0 for llSetMetaInformation. When the feature is accepted and new, feature specific LSL functions are added, this numeric identifier can simply be changed, requiring very little code change.
Examples
Web Textures
llSetMetaInformation("webtexture, face1, http://www.myhost.com/webtexture.php?text=my%20text"); //inserts string into tag 0 for this prim.
This way web textures could be implmented on the client. When LL decides to officially support web textures, they will assign it a new tag number (lets say 2) and add:
llSetWebTexture(string url, integer face); //Updates tag 2 with "webtexture, face<facenum>, <url>"
Which will simply be equivalent to a llSetMetaInformation on tag 2, using the same format that the feature used before, but now packaged in a nice "consumer friendly" format.
Full Boolean CSG Support
Something even as advanced as full boolean CSG support can be added if we had this feature.
During development the developer and tester could use something like:
//Causes the prim to subtract from intersecting prims. llSetMetaInformation("csg, not"); //inserts string into tag 0 for this prim.
Then later on, once CSG was supported and fully tested in the client, the tag number could be changed, and instead of adding an LSL function, the functionality could be added to the build tools in the form of GUI. The key is that this feature provides a test bed for new prim-related attributes that are primarily client-side features, but require minor server-side changes.
Implementation
The sim->viewer protocol already seems to include an extensible prim property functionality.
However, this functionality is not suitable for what we want, currently, according to Kelly.
From what I can tell, it's something like this:
ExtraParams { U8 num_params param { U16 param_type S32 param_size Variable Data } param { ... } param... }
The equivalent viewer->sim structure seems to be called ObjectExtraParams. Most newer prim properties like flexible and lighting use this more flexible dynamic prim property system.
Alternate Approach
This is not really general enough, and only addresses the problem for prim-client communication.
There's all kinds of situations where scripts are forced to hide configuration information in odd prim attributes to hide it from script resets.
Having a general persistent data store in objects would also solve many of the problems that cause people to want editable notecards.
Implementation
The root prim (or any prim) of an object would have an associated list of name-value pairs. The name would be a string and the value could be a string, or alternatively it could be a simple type (string, key, integer, float, vector, or rotation). This list would be saved and restored with the prim, and a client could register its interest in specific values that would be delivered to it. This is similar to MUCK attributes, UNIX environment variables, file metadata in BeFS and later file systems, Lisp property lists, and so on. It's a powerful, efficient, and easily generalised mechanism.
LSL API
llCreateProp(string name, integer perm); llSetPropString(string name, string value); llSetPropInteger(string name, integer value); // ... string llGetPropString(string name); // etc for Integer... llSetPropStringKey(string name,key object,string value); //... // key must be an object in the same sim, and the object must be owned by the script owner or have appropriate permissions string llgetPropStringKey(string name,key object); //... // key must be an object in the same sim, and the object must be owned by the script owner or have appropriate permissions Permissions: 1 ANY_READ 2 ANY_WRITE 4 GROUP_READ 8 GROUP_WRITE 16 READ_PROTECT 32 WRITE_PROTECT 64 CLIENT_PROTECT
READ_PROTECT and WRITE_PROTECT mean that scripts outside the prim can not read or write the attribute. CLIENT_PROTECT means that it isn't sent to the viewer.
This means that the default 0 permission should DTRT in most cases.
Since it would only be sent for attributes the viewer requests, the bandwidth overhead would be minimal.
Communication
The client would send a list of up to 255 properties it was interested in. What it would get from the sim would be a list containing one byte ID (matching the index of the string in the interest list it previously sent the sim) and the associated value. This would reduce the bandwidth requirements considerably.
Limits
The total amount of space available for all attributes on the root prim of an object would be limited to 1024 bytes. This 1024 bytes would include the name, the permission byte, and the value. It could be stored as the byte value, a nul-terminated UTF name, a byte type (optional), and the value (null-terminated if a string), followed immediately by the next value. Two consecutive nulls (zero-length name) would terminate the list. This implementation worked well for early UNIX on machines whose CPU power and available memory was of the same magnitude as an LSL script.
This would take the same space as the proposed meta-information, be more generally useful, and should end up using less bandwidth.
Examples using this approach
llSetPropString("texture1","http://www.myhost.com/webtexture.php?text=my%20text");
To set texture for face 1.
integer CSG_AND = 1; integer CSG_OR = 2; integer CSG_NOT = 3; //... llSetPropInteger("csg",CSG_NOT);
To set the CSG parameters for the object.