Page 1 of 1
ConfigManager - Handy Library for Options Menus
Posted: Wed Nov 30, 2016 4:33 am
by acb5649
I'm in the middle of making my first Lua game and I needed a way to save the user's preferences for the game window. If they set my game to fullscreen mode, I think it had better reopen in fullscreen mode. It works by directly editing the conf.lua file instead of using an outside file to save values. It's my first published bit of Lua code, so I'd love any suggestions or recommendations.
https://github.com/acb5649/ConfigManager
Re: ConfigManager - Handy Library for Options Menus
Posted: Wed Nov 30, 2016 4:47 am
by zorg
acb5649 wrote:I'm in the middle of making my first Lua game and I needed a way to save the user's preferences for the game window. If they set my game to fullscreen mode, I think it had better reopen in fullscreen mode. It works by directly editing the conf.lua file instead of using an outside file to save values. It's my first published bit of Lua code, so I'd love any suggestions or recommendations.
https://github.com/acb5649/ConfigManager
First thing, while using lua io functions isn't a sin, this won't work in many cases, like when you zipped up your project into a .love file.
I'd use love's own filesystem stuff instead. (Though i must admit, i thought io.open needed a full absolute path... if it works for you with only "conf.lua", then that's a surprise for me)
Second issue would be that love.filesystem doesn't allow you to write to the application directory, so even if you tried to write something to conf.lua, it will write that file into your save directory, if you have set an identity for the project, that is.
Re: ConfigManager - Handy Library for Options Menus
Posted: Wed Nov 30, 2016 4:58 am
by acb5649
Thank you, I feel a little silly for forgetting Love projects are zipped for distribution.
I guess I'll leave it up while I work on a replacement, since I can't use this code for release either.
EDIT:
New working version is now online, but it does use extra files stored in the LOVE save directory.
It now uses 100% love.filesystem calls instead of io, and does not impact startup speed. See the included conf.lua file for usage example. Basically, if you want to let the user control a configuration, like MSAA, use:
The config file will check the save directory for a file with the MSAA information inside. If such file is not found, is defaults to 0 because of the "or" condition.
Again, any and all feedback is appreciated. Look how well it went last time!
Re: ConfigManager - Handy Library for Options Menus
Posted: Wed Nov 30, 2016 6:35 am
by ivan
Yes, you should always save progress and settings in the appdata/user directory,
writing files to the installation directory is not good practice and might not work depending on the user's permissions.
Having said that, the code needs work.
Saving a separate ".dat" file for each setting is not ideal,
the easiest option is to save everything in a single Lua table or use bartbes "inifile".
Also, note that:
Code: Select all
function loadWindowPosWidth()
local file = "windowwidth.dat"
if love.filesystem.exists(file) then
local size = love.filesystem.getSize(file)
local data = love.filesystem.read(file, size)
return tonumber(data)
else
return nil
end
end
Is the same as:
Code: Select all
function loadWindowPosWidth()
local file = "windowwidth.dat"
if love.filesystem.exists(file) then
local size = love.filesystem.getSize(file)
local data = love.filesystem.read(file, size)
return tonumber(data)
end
end
PS. Subfolders for each "version" of the configmanager is a good idea too, since APIs change over time.
Either that or try to include the savefile version somewhere in there.
Re: ConfigManager - Handy Library for Options Menus
Posted: Wed Nov 30, 2016 5:04 pm
by Positive07
And this:
ivan wrote:
Code: Select all
function loadWindowPosWidth()
local file = "windowwidth.dat"
if love.filesystem.exists(file) then
local size = love.filesystem.getSize(file)
local data = love.filesystem.read(file, size)
return tonumber(data)
end
end
As this, since read tries to read it all if no size is specified
Code: Select all
function loadWindowPosWidth()
local file = "windowwidth.dat"
if love.filesystem.exists(file) then
local data = love.filesystem.read(file)
return tonumber(data)
end
end
Re: ConfigManager - Handy Library for Options Menus
Posted: Thu Dec 01, 2016 1:05 pm
by ivan
I think the entire API could be rewritten in 2 functions:
Code: Select all
-- very bad example writing each key to a separate file
function api.loadString(key)
local file = key..".dat"
if love.filesystem.exists(file) then
return love.filesystem.read(file)
end
end
-- load custom values if their type matches the default
function api.load(defaults, destination)
-- overwrites the defaults if no destination table is specified
destination = destination or defaults
-- iterate default values
for k, v in pairs(defaults)
local expected = type(v)
-- convert based on expected type
local custom = api.loadString(k)
if expected == "boolean" then
if custom == "true" then
custom = true
elseif custom == "false" then
custom = false
end
elseif expected == "number" then
custom = tonumber(custom)
end
-- check loaded type vs default type
if type(custom) == expected then
destination[k] = custom
end
end
return destination
end
Basically you need a table of default values and you overwrite that:
Code: Select all
local defaults =
{
Width=800,
Height=600,
Borderless=true,
Resizable=0,
MinWidth=0,
MinHeight=0,
Fullscreen=true,
FullscreenType="string",
Vsync=true,
MSAA=0,
Display=0,
HighDPI=true,
WindowPosWidth=0
}
api.load(defaults)
PS. Haven't tested the code, but I hope the technique is clear.
I used this approach in my games and it works quite well, except that you have to do some extra validation,
in particular with paired values like width/height...