January 18, 2014

Lua in Leadwerks #1: Settings, Action Maps

(Files here under CC-BY-NC-SA license can be downloaded here.  Root post for series can be found here.)

First, I wanted a central location for me to establish defaults for my games and a consistent way for user overrides to be saved and reloaded.  This is one possible solution.

The ZIP file above contains four files: RomSettings.lua, RomActionMap.lua, DefaultSettings.lua, and App.lua.  App.lua is the stock App.lua, just modified to show how to hook into the

My first thought was that I would use Lua 5.1's function environment features to safely deserialize a Settings object and then do a selective merge into my default settings, but that led to two small problems.  First, the function environment settings in Lua 5.1 are disabled in Leadwerks for Lua and will cause the app to exit immediately upon execution.  Second, the function environment features in Lua are being removed in Lua 5.2, so my scripts wouldn't be future-proof.

Leadwerks does expose two new functions that we can use, though: System:GetProperty and System:SetProperty.  These will allow you to save and load strings that get saved in a file in your AppData/Local/[gamename] folder on Windows.  However, they only allows you to save and load strings, which limit their usefulness.

To use the attached files, extract DefaultSettings.lua, RomSettings.lua, and RomActionMap.lua into your Scripts folder.  At the top of your App.lua file, add the following:
import "Scripts/RomSettings.lua"
import "Scripts/RomActionMap.lua"
At the top of your App:Start() function, add the following:

System:LoadSettings()

At the beginning of App:Loop(), replace the "end program" state with the following:

 --If window has been closed, end the program
 if self.window:Closed() or ActionMap:IsHit(Settings.ActionMap.QuitApp) then
  Settings:SaveSettings()
  return false
 end

After you run it and exit, go check out your [gamename].cfg file in your AppData/Local/[gamename] folder.

Now for a quick walkthrough on how everything works, starting with System:SaveSettings.

System:SaveSettings recursively walks through the Settings object. Since we can only save strings, but need to reinflate to the proper type, I serialize each type to a string and add a prefix so that when I am deserializing I can reinflate correctly.  If there is an array, I'll also create an "n" field so I know how many items there are.

System:LoadSettings acts a little differently.  It recursively walks through the DefaultSettings object and only tries to inflate settings that it knows about.

ActionMap was covered before.

To add/remove/change the default settings, just modify DefaultSettings.lua.  Those will get copied into the Settings global at the top of RomSettings.lua.

I'm going to start work on the replacement player object tomorrow.

No comments: