Hey,
That's right, I've started it.
https://github.com/ken-noland/OpenXcomHow it worksI've modified Game and Mod so that they take in a ModFile class which contains a list of all the mods active and are in the correct loading order. Once Mod has finished loading, then I load up LuaMod which goes through each metadata.yml and checks to see if there is a tag for a lua file in there. The metadata should look like this:
#
# metadata.yml for Lua Test
name: "Lua_Test"
version: 1.0
description: "Verifying the callback mechanism works"
author: Whispers
master: xcom2
lua: bootstrap.lua
Once it sees the "lua: bootstrap.lua", then it knows this is a mod which uses the new Lua stuff. Once that is detected, it uses the path to the mod, then appends the lua filename, then loads the Lua file. A couple of things to note here is that I don't think this will work for zipped up files in its current state, but that may come later. In fact, I'll
post a bug on the repo so I know I will catch it at some point. The other thing to note is that I've overriden the Lua print and redirected it to log, so anything you print, or any Lua errors, will get output to the game log.
Once loaded, it is executed once, and only once. It's up to the mod to register events.
function onLoad(doc)
print("the above 'doc' contains the entire save state converted from YAML to Lua Tables")))
end
game.on_load_game:register_callback(onLoad)
There will be more hooks, but I had to start somewhere. Once the game is loaded, then things become more interesting. "game.base" becomes available, which I'm currently working on. On the C++ side, I've been working on how to simplify the registration of events and callbacks, as well as how best to expose the data. I've come up with a mechanism which allows a programmer to register a container and the LuaApi does the rest, but it's still very early at the moment.
And that brings me to the current status. All the Lua stuff does at the moment is likely to change. For instance, 2 days ago I was designing the api to use getters and setters, but that's not necessary Lua. Want to change a soldiers name? Just set it in Lua and then you're done. Err, at least that's the idea anyway. Want to send a message to another mod? Sure, I'll get to that eventually. Cross mod communication is definitely on my agenda. My first priority is setting up the API and exposing as much as I can.
So, there are two types of callbacks, at the moment. Events and Accumulators. Events fire off just like you would expect them to. Things like onLoad and onSave or, when I get around to it, onTick are all events. They fire off with parameters that be be read by the Lua state. Most events fire off for every mod that registers a callback, but a handful of events can be consumed. When an event is consumed by the callback, it does not fire off for the next mod and it could also stop the default behavior in C++. Accumulators are a bit different. The first parameter for an accumulator callback is the result of the previous accumulator(or the default value). The accumulator must return a value which is passed to the next one or sent to the game.
The framework for Lua is mostly there. The Api has started to take shape. I'm very hopeful that this time around it will be an official release.
Big changesThis does introduce some changes that I feel are necessary.
1) YAML is no longer required in the binary dependencies. I would also like to get SDL removed, therefore removing all binary dependencies altogether, but... time...
2) I've dropped support for the old MSVC Project, Makefile and I will not be supporting any other build system other than CMake. Reason why is because in order to grab the YAML and (in the future) SDL stuff and build it, I use CMake for that. There's also a strong argument that if you are developing on something that is shared, then you should all be using the same process that is used to trigger the nightly builds.
3) I've squashed over 800 warnings from build the x64 version, but more are coming. I basically squash them as I'm building.
4) I've been slowly but steadily removing the "auto" from the variable declarations. In the process, I've found a TON of potential bugs and issues and fixed them as I went along. Far too many to list here.
5) I've exposed a getGame function callable from anywhere. I hate singletons, but in order to get the hooks where I needed them to be I need to get the Game*. Now, singletons are evil, but there is an alternative called Thread Local Storage. Not that it matters, due to how many other globals are floating around, but theoretically, you could fire off different Game objects on different threads. This keeps things nice and tidy for the future.
6) You need to have a C++20 compiler now
Backstory: A long time ago I started on working with integrating Lua into OpenXcom. At the time, I was basically told the change was not wanted by the authors of OXCE, so I abandoned it. This time around, *I* wanted the change so I could implement some custom logic without having to touch the source. It's taken me the last two weeks to get it up and running again, but this time it's far more powerful than before.
Next StepsContinue implementing more events, exposing more data and fleshing out the API. Specifically, the next API I am working on is for UI.
I haven't even defined what a release looks like. I'd love to get your feedback and thoughts.