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:
-- wrapper on the existing saved var abstraction
function ZO_SavedVars:SaveNow(importance)
-- values for importance:
-- the user is likely to be very upset if this is lost
SV_IMPORTANCE_CRITICAL
-- the user will probably be a bit annoyed if this is lost
SV_IMPORTANCE_NORMAL
-- the user probably won't notice unless you lose a lot of these
SV_IMPORTANCE_LOW
-- SaveNow returns:
-- request was accepted, and data saved
SV_RESULT_SUCCESS
-- request was accepted, and data will be saved later
SV_RESULT_DELAYED
-- too many requests, do not try again for <seconds> seconds
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:
-- just ask for everything to save, nil return
function WriteSavedVars()
-- either a string for "addon", or the SV itself, or something
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:
local state = { isDirty = false, isWriting = false }
-- I'd actually implement the priority system, and basically
-- aggregate lower priority things until we had either
-- (a) sufficient count of them, or
-- (b) enough time passed.
function state:SaveNow(self)
self.isDirty = true
if not self.isWriting then
-- in my library, I'd probably animate a "saving now" icon
-- that showed we were busy writing stuff out, so users know
-- when things are safe, because failing when they know
-- we are trying to behave as desired is less annoying
-- than failing when the user thinks everything is just fine.
self.isWriting = true
WriteSavedVars()
end
end
function state:OnWriteComplete(self)
self.isWriting = false
if self.isDirty then
self.SaveNow()
end
end
EVENT_MANAGER:RegisterForEvent(
"MyAddOn", EVENT_SAVED_VARIABLES_WRITTEN,
function() self.OnWriteCompleted() end
)
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.