We have detected that cookies are not enabled on your browser. Please enable cookies to ensure the proper experience.
Results 1 to 5 of 5

Thread: Lua file IO?

  1. #1

    Lua file IO?

    I have a bad feeling this is going to be another "Turbine doesn't let you do that..." issue.


    Can a plugin read in files? Or it is blocked from doing any file IO beyond the Turbine.PluginData commands?

    I've experimented with the standard lua commands, only to get an error (global 'io' is nil), and I don't see anything in Turbine's lua documentation nor in the information revealed by HereBeDragons to point to anything else.


    If file i/o *IS* only through Turbine.PluginData, can you read in different files by changing the 'pluginName' parameter? [e.g. Turbine.PluginData.Load (scope, "myDataFileName", settings, callbackFn) ]

    I know that, after a plugin is loaded, there's that damnable 15-second delay in file-io, which would affect this. (Really Turbine? sheesh.) And that there's a work-around by un- & re-loading the plugin. (A kludge that brings its own limitations.)


    What I'm *trying* to do is to supplement some internal data (e.g. the stuff I pulled in from my plugin's 'settings' file) with additional data from an, as it were, 'partial' settings file.

    Without other file-IO, the only solutions to avoid that stupid delay up with which I can come (>grins<) seem rather kludgy... figured I should consult the lurus before I spin my wheels further.


    So, er... help?


    thanks

  2. #2
    Join Date
    Mar 2007
    Posts
    1,191
    Your feeling is correct, Turbine does not allow any file IO other than .plugindata files. While this is an annoyance to legitimate plugins, it was implemented to prevent plugins from acquiring external information in real time which could be used for less than legitimate purposes. You are also correct that it is possible to work around it by using the re-load mechanism.

    You can read from multiple files as long as they exist within an available scope - you can't read from a file created by a different character that was saved with Character scope - so be sure to save your data with the appropriate scope. It is also possible to load specific .lua files on the fly if multiple versions of code exist and you don't know until runtime which version to use - I've been using this technique to cut down on loaded data for a couple of plugins. You just have to remember that dynamically loaded .lua files will use variables that are locally scoped if you aren't careful.

    FWIW, I would suggest using Vindar's wrapper solution to avoid issues with UTF-8 characters. I would also suggest using my euroNormalize function to avoid issues with decimal numeric data. This will eliminate issues for users that use DE/FR clients as well as those that switch between EN and DE/FR clients.
    Code:
    if (tonumber("1,000")==1) then
    	function euroNormalize(value)
    		return tonumber((string.gsub(value,"%.",",")));
    	end
    else
    	function euroNormalize(value)
    		return tonumber((string.gsub(value,",",".")));
    	end
    end
    Usage:
    value=euroNormalize(someValueL oadedFromAPluginDataFile)
    Last edited by Garan; Feb 21 2014 at 02:33 PM.

  3. #3
    *sigh* I was afraid of that. Thanks!


    Can I bend your ear a little more?

    My 'basic' settings file has all the plugin's settings. I would like different 'configurations' of those settings - or, rather, subsets of it - to be available, stored independently.

    So what I'd like to do is allow the user to select one of those subsets (depending on the desired behavior of the plugin) and load it in. Of course, as this is during "run time", it hits the 15 second delay. Meaning I need the main/helper plugin approach.


    So, if I've sussed all this out correctly, what I'm going to have to do is:

    -- save temporary variables in the settings file [volatile info that'd otherwise be lost]
    -- save the 'user's choice' (the selected subset I want to load in) into the settings file
    -- call the "helper plugin"

    -- Then the helper plugin will have to (and all this during its setup phase, to avoid the delay):
    ---- Unload the main plugin [which will have to realize this is a 'temporary unload' and act accordingly]
    ---- Read in that plugin's settings file
    ---- Extract the 'user choice' info from that file
    ---- Load in that selected data file and integrate its values with the main plugin's settings
    ---- Save the main plugin's settings
    ---- Call the main plugin

    -- Then the main plugin has to:
    ---- Recognize that it is in a 'recover/restart' state
    ---- Tell the help plugin to unload
    ---- Re-load its temporary/volitile variables and remove them from its settings data
    ---- Pick up where it left off.


    Do I have the logic right?


    thanks!

  4. #4
    Join Date
    Mar 2007
    Posts
    1,191
    Quote Originally Posted by Eddenwulf View Post
    *sigh* I was afraid of that. Thanks!


    Can I bend your ear a little more?

    My 'basic' settings file has all the plugin's settings. I would like different 'configurations' of those settings - or, rather, subsets of it - to be available, stored independently.

    So what I'd like to do is allow the user to select one of those subsets (depending on the desired behavior of the plugin) and load it in. Of course, as this is during "run time", it hits the 15 second delay. Meaning I need the main/helper plugin approach.


    So, if I've sussed all this out correctly, what I'm going to have to do is:

    -- save temporary variables in the settings file [volatile info that'd otherwise be lost]
    -- save the 'user's choice' (the selected subset I want to load in) into the settings file
    -- call the "helper plugin"

    -- Then the helper plugin will have to (and all this during its setup phase, to avoid the delay):
    ---- Unload the main plugin [which will have to realize this is a 'temporary unload' and act accordingly]
    ---- Read in that plugin's settings file
    ---- Extract the 'user choice' info from that file
    ---- Load in that selected data file and integrate its values with the main plugin's settings
    ---- Save the main plugin's settings
    ---- Call the main plugin

    -- Then the main plugin has to:
    ---- Recognize that it is in a 'recover/restart' state
    ---- Tell the help plugin to unload
    ---- Re-load its temporary/volitile variables and remove them from its settings data
    ---- Pick up where it left off.


    Do I have the logic right?


    thanks!
    You might be able to simplify this quite a bit. There are a number of approaches depending on how many settings you have and how often and under what conditions they change.

    First, you may be able to load all of the settings into a table so that they are always all available kind of like:
    Settings={}
    Settings[1] = {}
    Settings[2] = {}
    Settings.ver = 2 -- equivalent to Settings["ver"]=2, just a bit easier to read
    Settings[Settings.ver]["SomeSetting"] = "some value"
    Settings[Settings.ver]["SomeOtherSetting"] = someOtherSetting
    etc.
    Then by setting the variable 'Settings.ver' you will change which version of the settings you are using
    Unless you have more than a couple hundred settings this should work fine for you, especially if you keep the setting names short.

    The second approach would be similar to what you are already planning but a bit simpler. You could simply save all values including the intended new settings version and just use the helper app to force a reload - it doesn't appear as though you need to do any processing in the helper app. Then when re-loaded, read your generic settings from one file and then read the version specific settings from a separate plugindata file specified by a value from the generic file. There is no need to extract and merge values, just use multiple plugindata files (you can read multiple files in real time when in the loading state). If you really must track additional state information you can add that to your generic settings (basically what MoorMap does when switching maps, it saves the new map ID as CurrentMap and triggers a reload then reads the mapID from the generic settings and uses that to determine which plugindata file to load for that specific map's annotations).

    The third approach is only good for static information with multiple values such as language versions for text. You can create multiple versions of the same data in .lua files and only read the version that is relevant. This still requires a reload when switching versions.
    Last edited by Garan; Feb 21 2014 at 06:27 PM.

  5. #5
    Ah, you're right - the second suggestion makes more sense, keeping all the processing in one file.

    Now I just need to go back and wade through that plugin-calling-plugin code and actually figure out the nitty-gritty so I can add 'reload' functionality to my generalized plugin class...

    thanks!

 

 

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

This form's session has expired. You need to reload the page.

Reload