Forums » Community Projects

SystemNotes wrapper functions

Dec 28, 2013 draugath link
As was briefly discussed here, I've gone ahead and written some wrapper functions for LoadSystemNotes() and SaveSystemNotes() that will allow reading the system notes from a different character.

SaveSystemNotes2(string, number)
string :: as per SaveSystemNotes()
number :: as per SaveSystemNotes()

This function will encapsulate the received string inside a table of the structure {data = string, timestamp = os.time()}. It will then spickle() this table and save the string "return unspickle([[new_string]])"

LoadSystemNotes2(number[, string])
number :: as per LoadSystemNotes()
string :: this is the character whose note you want to read (optional)

If the second argument is provided it will attempt to loadstring() the file. If it's a valid function and returns the proper table structure stored with SaveSystemNotes2() it will then return the original string stored previously.

If the second argument is missing, or the notes file does not contain a valid function, then it will attempt to find the latest copy of the data on one of your other characters. If it can find valid data it will return it. Otherwise it returns an empty-string, as per LoadSystemNotes().
Dec 29, 2013 tinbot link

I like that your wrapper spickles and unspickles, and formats as a dofile. this looks very useful.
I think the heart of the module is the statement:
SaveSystemNotes("return unspickle([["..spickle(tbl).."]])", id)

I like your data structure of: {timestamp = os.time(), data = str}
but I do not like it being mandatory, at the root level. I think it should be a separate layer. I am perhaps being petty on this point.

What I find very limiting, is the part where if it does not find the file, it checks for the file somewhere else. In other words, I can not use this wrapper for character inventory. If I use a file to store the inventory of a character, and one of my characters does not have any inventory, and does not have an inventory file, i do not want the wrapper to go and get the inventory of some other character. so this wrapper will not work for character specific data.

On the other hand, your wrapper looks like it might be useful for some types of account specific data. for example, if i ask a plugin to save my password for an account, then it can record that information on the first character i log onto on that account. your wrapper is perfect for this type of data, as long as i do not change my password, and i do not delete the character where the password is stored.

I feel that level of functionality is not appropriate at the root level. it should be a separate layer. and further, what exactly is your use case for that functionality? what data type will it service?

Thank you for your code. I have not tested it. I expect that at the least, I will be borrowing from your work.

edit: actually, I could make your wrapper work for character specific data, by including the character name in the stored data, and then checking that the data is valid for the character I am working on. I think I should do this, as a matter of good programming, but I do not think I should have to do this.
Dec 29, 2013 draugath link
Well, the only reason to use a wrapper like this is for the express purpose of sharing information across characters. So it makes perfect sense that if it can't find the data locally, it goes looking elsewhere, otherwise you might as well just use the original. The reason the data structure is mandatory is because it's necessary to find the most recent copy.
Dec 29, 2013 tinbot link
Then, if I understand you, your wrapper is not intended for character specific data in the first place.

What data is it for? Can you give me a usage example?
Dec 29, 2013 draugath link
It's intended as a much cleaner alternative to flooding the config.ini with thousands of lines of data that shouldn't be character specific. Sure, you potentially wind up with multiple files floating around that are that size, but in my opinion it's better than the alternative.

Any roid databases, DroidButtons, Trade Assistant, etc. These all store data with system notes that would be best shared across all characters.
Dec 29, 2013 tinbot link
I agree with you on a number of points. These types of data should not be considered character specific and excessively large data sets should not be stored in config.ini

On review of your wrapper, I see that you do provide an interface to find the latest version of the file, without regard for which character is logged in. I had missed this fact in previous reviews.

It would appear that your wrapper is a good solution to those data types.

I will point out a few limitations.

Your wrapper is account specific. It will only search characters of the last account logged into. It will not search any characters, until at least one account is logged into.

On the upside, you do provide an interface to load a file by character name, so if I have an alternative list of characters, I can then search them myself. On the downside, your comparison routine does not have it's own interface, so if I provide my own character list, I can not reuse your comparison method.
Dec 29, 2013 draugath link
True. I wasn't trying to over-engineer it. I wanted it to be simple without trying to do everything under the sun.

You could always make it so that if the specified name doesn't return valid data that it escapes right then so that you could write your own multi-account iterator.
Dec 29, 2013 draugath link
tinbot deleted:
would you mind rewriting LoadSystemNotes2 function, so that it would optionally accept a table of character names, and in finding such, iterate over the table, and not use GetCharacterInfo.


would you mind splitting out your comparison routine, and providing an interface, so I may feed it two data sets, and it will return the latest data set?


Unless I find a problem with the code as it's currently written, I'm not planning to do anything more with it. I wanted to make some form of wrapper available to allow this basic functionality. If you want to modify them, by all means, please do so.

Both of your requests fall under "over-engineering it". Especially since your personal use is a special use-case, not likely to be the norm.
Dec 29, 2013 tinbot link
I believe your code is useful for players with only one account. I do expect that I will use it as a base of code for future work. Thank you.

edit: your personal use is a special use-case. this is true to some extend, although I expect players with more than one account is not that uncommon. I do not intend to accommodate all possible use cases, for example, I am making no provisions for multiple players sharing a single computer (and trying to keep their character information separate). Two people using a single installation could put their config.ini under revision control, and swap branches when they swap players.
Dec 31, 2013 tinbot link
What happens if I delete the character that has the latest SystemNotes file? Your wrapper will not be able to find it. A large body of data could be lost.
Jan 01, 2014 Kierky link
targetless roid data would be an awesome use of this.
Jan 01, 2014 draugath link
tinbot, if you were smart in your implementation, you would store the name of the last character to store data in config.ini. Then you would retrieve data from that character. If it was deleted along with the character, then it will look elsewhere. But you are correct, in that if not fed a specific name it would not be able to find the data. It also shouldn't be over-engineered to try and account for every possibility. As it is, it does exactly what it needs to be capable of doing.
Jan 01, 2014 tinbot link
When a user deletes a character, that character is deleted online. Nothing is deleted locally. All the config.ini entries and system notes files remain intact.

If you use config.ini to store the name of the character of the last system file write, then you do not need a date. there is nothing to search or sort. you have an exact pointer to the last file.

You have finally come out and said it. the best way to find a system notes file for a character that you are not logged onto is to use config.ini And now we are back to talking about using the config.ini file, and worse, we could be talking about a config.ini entry per plugin file, as multiple plugins all track what character they last wrote to. If we have 6 characters, and 20 plugins, we could be talking about 20 config.ini entries to track what could be stored in a single entry: The 6 character names.

There are a few potential solutions to this.
a) We could just store all the character names in a single entry, and let each plugin search those characters.
b) We could have all the plugins share a single config.ini entry, that points to the last character written to, and anytime that any plugin updates the entry, it generates an event, telling all the other plugins to move their files to the new character.
c) We could have a config.ini entry that points to a single systemnotes file, and that systemnotes files holds all the pointers to all the files the plugins use.

In all cases, we are talking about using config.ini to store at least one character name.
Jan 01, 2014 draugath link
Your problems with tracking your accounts and characters has nothing to do with the limited feature scope of these wrappers.