Plugin support for German and French clients
Since there's not yet discussion about this, I thought I'd start one.
So what we have is a nasty bug with how data is serialized when using the internal Turbine.PluginData.Save method. What happens is that with German (and French?) clients the default decimal separator, which is "." (dot), gets converted to "," (comma). This can obviously break the save file badly since it's parsed as a Lua file. We can expect that this will be fixed by Turbine in the future, but plugin authors can react to this quite a bit faster. So, what should we do about it? 1) Each and every plugin author should find their own way to adjust plugins so that they work for all client versions. That is, if they want or bother to (it can be a lot of work). 2) We expect that those using other clients than English will start to use tools such as the fix provided by Vindar. Personally I'd like to modify mine so that they do work for everyone. But then again does that interfere with the fix? I've also found it problematic to test this since it doesn't appear that anything short of installing a German client is enough to make this bug appear. -Chiran |
If you alias the Turbine.PluginData.Load and Turbine.PluginData.Save methods it will cause the fix to not change anything in your plugin like this:
Code:
local load_alias = Turbine.PluginData.Load; |
Ah, that's a good tip, thanks!
-Chiran |
Since Palantir has a hefty number of settings, I was planning on creating a couple of functions to iterate through the tables before saving, and after loading to convert numbers/bool to strings and back.
|
Quote:
|
Quote:
Code:
function settingsEncode(t) Code:
function settingsDecode(t) |
I implemented a slightly different solution for my plugin.
Basically, before I call Turbine.PluginData.Save(), I serialize my settings table (and subtables) into a string. The string is simply a snippet of Lua code that, when executed, returns my settings table. Then I save that single string with Turbine.PluginData.Save(). After I get the string back from Turbine.PluginData.Load(), I use the built-in loadstring() function to parse it back into a table. Vindar's fix didn't work for me, because my settings table contains tables that look like this: Code:
t = { "a", "b", "c" } Code:
t = { Code:
function SaveSettings(settings) |
Quote:
Full-proof code would probably require escaping line feeds and maybe other control characters though, as string literals within double quotes are supposed to be on one line. Edit: I also don't understand the purpose of "text = string.gsub(text, ",$", "");" |
Quote:
Quote:
Edit: Maybe I can avoid the whole problem by using "long-bracket" literal strings: [[ ... ]]. Edit: Or by using string.format("%q", ...). Updated the source code. Quote:
t = { "a", "b", } into t = { "a", "b" } even though the former is completely acceptable in Lua. For the sake of maximizing efficiency, perhaps I should remove it. |
Seems like I won't get around this stuff either...
Thurallor, I can't reproduce the problem of Vindar's code returning number indices as string indices. Are you sure you converted the saved data back? But in any case it only solves the locale problem partially, it will still save numbers as "1,234" and hence still fails converting back at loading when switching client language. Also I'm not sure why he needs that metatable and other "black magic", I'm pretty sure references to the same table will be lost anyway. Thurallor's solution is certainly interesting, it basically does the same as Turbine's own I/O method by converting it to Lua-code. Only problem is that you need to wrap the result in a single huge string which makes pretty unreadable files, and I'm not too sure that you won't eventually run into any line-length limitation of the interpreter or underlying file I/O. I decided to mix the solutions, I just write out numbers as string and parse them back with loadstring(), and prefix the strings so know if it was was number or not: Code:
function convSave(obj) { [5] = 1.23, ["foo"] = "bar"} becomes { ["n:5"] = "n:1.23", ["s:foo"] = "s:bar" } which can be converted back in all locales. I could also check for current locale and use gsub again and use tonumber() instead of loadstring() for numbers, and I haven't investigated if Lotro can handle non-printable characters or if I should use string.format("%q", ...) too... |
Or you could just use the solution I've been using for nearly two years now, detailed at:http://forums.lotro.com/showthread.p...97#post5784197
It is a two part solution, first using the Vindar patch to save and load data and then forcing numerics to the currently selected client format using my euroNormalize function so that the plugin will work properly even if the user changes client languages between saving and loading data. |
Lynx3d, I've started using a variant of your solution, which I quite like. :)
Garan, the main drawback of your method is that you have to call euroNormalize() for each numeric key or value (and not call it on strings that happen to be numbers). I want the workaround to be done centrally and automatically. Therefore the load function needs to be smart enough to know when to create "1.23" vs. 1.23. |
All times are GMT -5. The time now is 01:30 AM. |
vBulletin® - Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
© MMOUI