Jacek laments the lack of ability of scripts to write to notecards, thus depriving them of a potentially-useful mechanism for saving persistent data across script resets. (Other scripters have used the object name or description to store such persistent data, but the fact that LL is now enforcing strict limits on the length of those fields limits the usability of this technique.) We are told that this is because each edit to a notecard creates a new asset in the asset server, and it would possibly overwhelm the server, as if it wasn’t overwhelmed enough already.
Well, how does it handle people editing notecards normally? I’m guessing that, when you bring up a notecard window in the client, you don’t actually create a “new” asset until you press the Save button. Is there any reason why we couldn’t have script APIs that work the same way? Say, when you open a notecard for writing, buffer the data in memory, and only actually save that data, creating the new asset, when the notecard is closed?
Here’s an example of how these APIs might look. (Warning! These are not real APIs! I’m only showing you what I think they might look like.)
integer llNoteStreamOpen(string name, integer mode);
Opens a notecard for writing. name specifies the name or key of the notecard to be written to, which must be an existing notecard in the inventory of the object holding the current script. mode must be one of NOTESTREAM_OPEN_OVERWRITE (to overwrite the existing data in the notecard) or NOTESTREAM_OPEN_APPEND (to append to the existing data in the notecard). The return value is a “handle” used to interact with this notecard stream, or -1 on error.
Scripts may only have a maximum of N notecard streams open at one time (where N is a small number, perhaps as low as 1). Attempts to open additional streams beyond that result in an error.
integer llNoteStreamWrite(integer handle, string data);
Writes data to the notecard stream. Data written is buffered and is not actually saved to the notecard until the stream is closed. handle specifies the handle of the notecard stream to write to. data specifies the string data to be written. The return value is the number of characters written to the notecard stream, or -1 on error.
key llNoteStreamClose(integer handle, integer disposition);
Closes a notecard stream. handle specifies the stream to be closed. disposition must be either NOTESTREAM_SAVE (to save the changes to the notecard) or NOTESTREAM_DISCARD (to discard the changes to the notecard). Returns the UUID of the notecard that was modified (the new UUID if changes were saved, the original UUID if changes were discarded); returns NULL_KEY on error.
When a script is reset, any notecard stream handles it holds open are closed as if
llNoteStreamClose(handle,NOTESTREAM_DISCARD) were called on them.
I don’t know how feasible this all would be to implement. Perhaps we’d need an upper limit on the buffer size for the notecard stream, which would limit its usability for some purposes, but not for others. Perhaps any or all of these functions would need script execution delays built into them. Perhaps the streams should be automatically closed/discarded when the script changes states, much the same way timer handles get reset, instead of when the whole script is reset.