|
Fang Xianfu GURU
Joined: 26 Jan 2004 Posts: 5155 Location: United Kingdom
|
Posted: Sat Oct 13, 2007 7:15 pm
Saving preferences across patches |
So the new package format is awesome for sharing your scripts with people, but it's not so awesome for keeping their preferences. If you had a complex script with a lot of user preferences (how verbose it is in reporting what it's doing, colors, names, whatever), they'd be lost if the user were to download a newer version of the package from the package library. I've been trying to think of ways to avoid this problem.
The first thing I thought of was to write out the user's preferences to a file. There are a number of ways to do this, too - should each file have a WritePreferenceFile event that'll dump out things that need saving to a specified file (appending of course), or should there be a single export/import module that uses a GiveMePrefs event to request things that need saving from each package, and then the packages send in the values and the module writes out the values to a file on its own.
Another possible solution would be to have a separate package for storing preferences. The packages that have preferences you want saving could read and write the values of those preferences to this separate preference package, and then just never update the package when they patch the script. There are a number of problems with this method, because all your packages will be reliant on the existence of that prefs package.
Perhaps there could be some kind of RegisterForSave event - the event being in all your packages, with the event handler in the preference package. The packages would send in which variables need saving, and the prefs package would keep track of them, updating them with an onDisconnect event.
The problem is compounded in many situations if you're using Lua, because all tables need to be serialised before they're sent via event.
I was wondering if anyone had tried anything like this already and how they solved the problem, and if anyone who hasn't tried it has any thoughts on ways of handling this. |
|
|
|
Rahab Wizard
Joined: 22 Mar 2007 Posts: 2320
|
Posted: Mon Oct 15, 2007 1:35 pm |
I've been thinking about this same problem. It an especially big problem for me because the most important package I want to share with my fellow mudders is one that keeps track of a character's skill improvements. Right now it simply creates variables within the package for each skill. I originally figured that once the package was stable, no one would have to download new versions. But that seems overly optimistic.
Lately I have been considering creating a 'general' package which provides some basic functions for my mud-of-choice, and a place for any additional packages to store customized variables. This package would have to be very simple and robust, so that it would never have to be upgraded. But it's still not a perfect solution. |
|
|
|
Fang Xianfu GURU
Joined: 26 Jan 2004 Posts: 5155 Location: United Kingdom
|
Posted: Mon Oct 15, 2007 3:43 pm |
The solution I'm leaning towards at the moment is an optional preferences package. It'd contain an alias that'd first use a GiveMePrefs event to ask all packages for stuff to save. The GiveMePrefs event handlers would raise a GivingYouPrefs event, which would be handled by the preferences package. The Prefs package would write out the values it's been given - one class folder per package - and would then read them back out from another alias. This is good because the Prefs package remains optional until you need it and can be patched itself with no troubles.
I haven't decided whether or not this is the best way to go about it for Lua, though. I use Lua pretty extensively at the moment, and the way it'd work currently is that the variable would have to be serialised before it was sent via event, and then saved as a string in the Prefs package. It can then be reloaded with assert(loadstring(...))(), but it's not ideal. One method I've been considering for sorting this out is using the same prefs table to store my preferences in all my packages. The format would be prefs.package name.whatever to avoid naming problems. That way the package they came from is stored away as well, and it should be easy in Lua to load the string in the prefs package and iterate through the prefs table, serialising the parts of it that each package needs and sending them off.
I wish there were an easy solution to this, though :( |
|
|
|
Zugg MASTER
Joined: 25 Sep 2000 Posts: 23379 Location: Colorado, USA
|
Posted: Mon Oct 15, 2007 5:48 pm |
I'll give this some thought.
My first general suggestion is to make sure you design packages that create session-specific variables within the main window of the session, and *not* within the package. Remember that a package is supposed to be able to be used by multiple sessions. So if your package is store in A.PKG, then it can be loaded into different sessions and shouldn't be storing any session-related variables.
In other words, when someone is *using* your package, your package shouldn't be modifying itself.
However, I can understand some cases where this might be difficult. One thing that I'll think about is whether I can improve the downloading of packages from the library so that if you already have a package with the same name, it only overwrites settings that exist with the same ID as in the package, but doesn't clear any other settings that might have been added by the user. I can see some nasty side effect of this, so I need to give it more thought.
Oh, and regarding *Preferences* (like options, colors, etc), these are not yet stored in the Package Library, even though they *are* stored in the *.PKG file. This will be added soon...I just need to come up with an XML format for the preferences data. |
|
|
|
Fang Xianfu GURU
Joined: 26 Jan 2004 Posts: 5155 Location: United Kingdom
|
Posted: Mon Oct 15, 2007 7:27 pm |
Zugg wrote: |
create session-specific variables within the main window of the session |
Verily, this is a most excellent idea. Is there an easier way to get the name of the main window than:
#temp {OMGWTFBBQOLOLOL} {MainWin=%window}
#echo {OMGWTFBBQOLOLOL} |
|
|
|
Vijilante SubAdmin
Joined: 18 Nov 2001 Posts: 5182
|
Posted: Mon Oct 15, 2007 9:58 pm |
I think there is something available from the %sess predefined variable. I would have to check the documentation to be sure on that. I used to just use %item(%names,1) in zMud but I am seeing that packages and thier associated windows aren't always loaded in the same order in CMud.
|
|
_________________ The only good questions are the ones we have never answered before.
Search the Forums |
|
|
|
Tech GURU
Joined: 18 Oct 2000 Posts: 2733 Location: Atlanta, USA
|
Posted: Mon Oct 15, 2007 10:33 pm |
I've been giving this some thought as well, and as Zugg mentioned I *did* forget to make sure the variables are session specific. I just made that update.
What I'm doing is creating another module within in the main session Package.
Code: |
#MODULE %window
#MODULE Preferences
|
I think you approach may be a little bit more robust (since it tries to get the default execution via the temp trigger) but I'm not sure if that really buys you much. The idea is that the first call gets you into the session package and the second then defines the Preferences module.
I also have this code to check ensure I only define this module if it doesn't exist.
Code: |
#IF (%class("//Prefences") == -1) {
#RAISEEVENT initSession
} |
The cool thing about class is the by specifying the '//' I can qualify a root level module item vs. an embedded class. "initSession" is the event I defined to run the first bit of code. |
|
_________________ Asati di tempari! |
|
|
|
Fang Xianfu GURU
Joined: 26 Jan 2004 Posts: 5155 Location: United Kingdom
|
Posted: Mon Oct 15, 2007 10:49 pm |
Thinking about this, I don't think that windows are the way forward, because their name must be known to access variables stored in them. A module in the same package as the main session window would be better.
I'm not sure which approach will turn out simpler, though (employing Occham's Programming Guide). I think a separate package will be easier to write, and it'll be more portable than storing prefs in the main session package. Whichever solution's used, the problem of cross-package communication needs to be surmounted, so neither is going to be trivial. Users may find it simpler not having to pfaff around adding and removing a prefs package and patching it separately. But then again, they might find it more annoying not being able to easily swap their preferences in and out independent of their CMUD session.
It's still a knotty problem, and make no mistake. |
|
|
|
|
|