Thread Tools Display Modes
Prev Previous Post   Next Post Next
08/06/18, 09:56 AM   #1
SlippyCheeze
AddOn Author - Click to view addons
Join Date: Jul 2018
Posts: 53
support more frequent write (only) of saved variables

Dear ZOS, one of the biggest pain points around addons, for me, is that the model of saving data only at the clean exit of the application leads to quite some pain when I care about the content stored in them.

As a concrete example, I have been using Notebook 2018 to keep a "travel journal" of sorts for my adventures in Tamriel.

On a couple of occasions I have had the game hang, and lost quite a few notes. Enough pain, for me, that I have started to simple /reloadui after writing one, which is rather uncomfortable, and definitely slows down and breaks up my gameplay experience.

To mitigate this I would propose two possible solutions:

Solution one, my preference, would be to add an API mechanism to permit an addon to signal that it has made "significant" changes, and would like to have them saved to disk. By making this an active request, it helps ensure that authors like myself can request a save when the variables are in a "good", consistent state, and ready to write. (Avoiding, for example, saving half the configuration changes the user has made, but dropping the second half, if the game was to crash.)

Solution two, far less optimal, would be to save more frequently: on zone transitions, or loading screens, or simply on a timed basis. This removes direct control from addon authors, but still delivers the primary benefit, which is that addon users are much less likely to lose their data -- or at least as much of the data -- in the event of a crash.

I see that in the past you expressed significant concerns about real-time communication with applications outside the game:

Originally Posted by ZOS_ChipHilseberg
Our concern is with real time communication to programs outside of the game. There are certain design choices made about what information should be available to other players which could be violated by allowing file writing like this. A solution to your problem would be a lot more restricted than allowing arbitrary data to be written to files at any time. Discussion in the direction of allowing safe data (as dictated by the game design) to be shared in real time is fine. It's just not something we've put a lot of though into at this time.
I absolutely recognise this as a valid and important consideration, and think that real-time access to data externally has both good and bad sides. For example, in GW2, real-time access to player position allowed for "GPS-like" external tools to help navigate maps, which I can certainly see being undesirable from a design perspective.

Given the existence of the /reloadui command as a facility to support writing data at an arbitrary time. A number of addons use exactly that method to ensure they "commit" results to disk - to the point that libSaveToDisk exists to automate the process under user control; examples:

Adding an API driven mechanism that allowed these addons to save their data in a less disruptive way to gameplay would not significantly reduce their ability to transmit data to external programs, though it would limit their ability to read it from them. (Which suggests that in the later case, they may retain the reloadui mechanism.)


The API driven mechanism would also, I would hope, encourage using a mechanism that could be appropriately rate-limited by ZOS, so that data is only saved as frequently as you judge appropriate. (For example, taking an appropriate copy of the data on call, but only writing it to disk every minute.)

API-wise, I'd suggest something like this as what I would personally find most valuable:

Lua Code:
  1. -- wrapper on the existing saved var abstraction
  2. function ZO_SavedVars:SaveNow(importance)
  3.  
  4. -- values for importance:
  5. -- the user is likely to be very upset if this is lost
  6. SV_IMPORTANCE_CRITICAL
  7.   -- the user will probably be a bit annoyed if this is lost
  8. SV_IMPORTANCE_NORMAL
  9. -- the user probably won't notice unless you lose a lot of these
  10. SV_IMPORTANCE_LOW
  11.  
  12. -- SaveNow returns:
  13. -- request was accepted, and data saved
  14. SV_RESULT_SUCCESS
  15. -- request was accepted, and data will be saved later
  16. SV_RESULT_DELAYED
  17. -- too many requests, do not try again for <seconds> seconds
  18. SV_RESULT_RATE_LIMITED, seconds

However, that high level abstraction could obviously be built by the community over a much simpler ZOS API, such as:

Lua Code:
  1. -- just ask for everything to save, nil return
  2. function WriteSavedVars()
  3. -- either a string for "addon", or the SV itself, or something
  4. function WriteSavedVars(what)

If you chose to implement rate limiting, then having an appropriate return from the low level function would be hugely valuable, to prevent foolish loops that call this every second or two. Even a boolean to indicate if it worked or not would reduce the likely pain of repeated calls into the runtime.

Alternately, an event to signal that the variables have been saved, and simply ignoring calls to write them during the period between the two -- with an arbitrary delay possible, making for natural rate limiting -- would also meet the needs; then the high level implementation would be more or less:

Lua Code:
  1. local state = { isDirty = false, isWriting = false }
  2.  
  3. -- I'd actually implement the priority system, and basically
  4. --  aggregate lower priority things until we had either
  5. -- (a) sufficient count of them, or
  6. -- (b) enough time passed.
  7. function state:SaveNow(self)
  8.     self.isDirty = true
  9.     if not self.isWriting then
  10.         -- in my library, I'd probably animate a "saving now" icon
  11.         -- that showed we were busy writing stuff out, so users know
  12.         -- when things are safe, because failing when they know
  13.         -- we are trying to behave as desired is less annoying
  14.         -- than failing when the user thinks everything is just fine.
  15.         self.isWriting = true
  16.         WriteSavedVars()
  17.     end
  18. end
  19.  
  20. function state:OnWriteComplete(self)
  21.     self.isWriting = false
  22.     if self.isDirty then
  23.         self.SaveNow()
  24.     end
  25. end
  26.  
  27. EVENT_MANAGER:RegisterForEvent(
  28.     "MyAddOn", EVENT_SAVED_VARIABLES_WRITTEN,
  29.     function() self.OnWriteCompleted() end
  30. )

Finally, the purpose of this is to implement a user friendly "your data has a high probability of being safe" mechanism; making sure that we can effectively communicate the robustness to the user would have huge value.

Thank you for your time and consideration.


PS: also mentioned here on the official forums.

PPS: I am, as yet, unable to publish any code I have written to the ZOS addon API, as I am awaiting some internal processes at my employer to permit that. Forgive me making requests without published code to back them, please.

Last edited by SlippyCheeze : 08/06/18 at 04:51 PM.
  Reply With Quote
 

ESOUI » Developer Discussions » General Authoring Discussion » support more frequent write (only) of saved variables

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off